on master help sign in
Merge branch 'master' into urbit-help
f16c862Morgan Sutherland
concepts/arvo-vs-azimuth.mddeleted−15
@@ -1,15 +0,0 @@
1−+++
2−title = "Arvo vs. Azimuth"
3−weight = 4
4−template = "doc.html"
5−description = "A quick explanation of the two parallel systems that compose Urbit."
6−+++
7−Urbit is a project, not a single computer system. It has three components: Arvo, the operating system; Azimuth, the identity system; and Aegean, the pattern for creating software experiences for individual Urbit communities. This document compares the first two.
8−
9−[**Arvo**](https://github.com/urbit/arvo) is an operating system that provides the software for a personal server. These personal servers together constitute the peer-to-peer Arvo network. To make this network work on the social level, Arvo is built to work with a system of scarce and immutable identities.
10−
11−[**Azimuth**](https://github.com/urbit/azimuth) is the public-key infrastructure built to be such a system. A suite of smart-contracts on the Ethereum blockchain, Azimuth determines which Ethereum addresses own which Azimuth identities, called _points_. All point-related operations, such as transfers, are governed at this layer. But Azimuth isn't built strictly for Arvo -- it could be used as a generalized identity system for other projects.
12−
13−These otherwise-parallel systems meet when you want to connect to the Arvo network. Your Arvo personal server, called your _ship_, needs to be able to prove cryptographically that it is who it says it is. This proof comes in the form of a keyfile, derived from your point, that you use to start your ship.
14−
15−A metaphor might help illustrate the relationship between these two systems: the Arvo network is the neighborhood that you live in; Azimuth is the bank vault that stores the deed to your house.
concepts/azimuth.mdnew file+93
@@ -0,0 +1,93 @@
1++++
2+title = "Azimuth"
3+weight = 4
4+template = "doc.html"
5+description = "An explanation of the Urbit identity layer."
6++++
7+Azimuth is a general-purpose public-key infrastructure (PKI) on the Ethereum blockchain, used as a platform for Urbit identities that we call _points_. You need a point to use the Arvo network.
8+
9+The primary way to interact with Azimuth is through our [Bridge](https://github.com/urbit/bridge) application and the node libraries that it depends on, azimuth-js and keygen-js. Take a look at the source and play around or see [Getting Started](/docs/getting-started).
10+
11+## Arvo vs. Azimuth
12+
13+Urbit is a project, not a single computer system. It has three components: Arvo, the operating system; Azimuth, the identity system; and Aegean, the pattern for creating software experiences for individual Urbit communities. Let's compare the first two.
14+
15+**Arvo** is an operating system that provides the software for a personal server. These personal servers together constitute the peer-to-peer Arvo network. To make this network work on the social level, Arvo is built to work with a system of scarce and immutable identities.
16+
17+**Azimuth** is the public-key infrastructure built to be such a system. A suite of smart-contracts on the Ethereum blockchain, Azimuth determines which Ethereum addresses own which Azimuth identities, called _points_. All point-related operations, such as transfers, are governed at this layer. But Azimuth isn't built strictly for Arvo -- it could be used as a generalized identity system for other projects.
18+
19+These otherwise-parallel systems meet when you want to connect to the Arvo network. Your Arvo personal server, called your _ship_, needs to be able to prove cryptographically that it is who it says it is. This proof comes in the form of a keyfile, derived from your point, that you use to start your ship.
20+
21+A metaphor might help illustrate the relationship between these two systems: the Arvo network is the neighborhood that you live in; Azimuth is the bank vault that stores the deed to your house.
22+
23+## Why Urbit Uses a Blockchain
24+
25+The Arvo network is composed of personal servers: instances of the Arvo operating system, called ships, that communicate as peers.
26+
27+Every ship has an associated secure identity, called a point, that it needs to connect to the network. Your point is your name and your network address. Each point has associated authentication and encryption keys for networking. Think of a point as an IP address, a domain name, and a PGP key-pair.
28+
29+There are a limited number of points and, as you might expect, scarcity gives points value. This means that bad actors – spammers, scammers, and malware-spreaders – can be made economically unviable. Points being immutable allows for reputation systems to be built on top, keeping the network friendly and giving users information to help them decide who to treat as a trusted peer.
30+
31+At the user level, having one identity for your digital life means that all the services that you trust recognize you. You no longer need to worry about managing dozens of different logins. When you're using Arvo, everything you do is "verified" in the sense that it links back to your point.
32+
33+But wait! We need some way to secure these identities. To that end, we have built the Azimuth identity layer on the Ethereum blockchain to determine which PKI. As mentioned above, it's separate from and parallel to the Arvo network.
34+
35+In theory, our ecosystem doesn't need a blockchain, because Urbit identities are more like real estate than currency: they change hands slowly. A low-friction, zero-trust solution to the double-spend problem isn't an economic necessity for transactions such as ours. So we could have the Arvo network run its own key-signing system. But, since Azimuth identities are valuable, you don't want to put them in an self-hosted PKI that isn't generally recognized as secure. Arvo is still young, we'd prefer to use an existing system for people to secure their property.
36+
37+Moving the Urbit land registry to Ethereum is an easy and obvious solution to this problem. We chose Ethereum over Bitcoin because the former is built for computation Landscape the latter is not. We need a computational blockchain to enforce the specific rules of the Urbit identity registry.
38+
39+For more background on the decision to use the Ethereum blockchain, check out [these](https://urbit.org/posts/essays/urbit-and-the-blockchain/) [two](https://urbit.org/posts/essays/bootstrapping-urbit-from-ethereum/) posts.
40+
41+## The Urbit HD Wallet
42+
43+Owners of Azimuth points need safeguards that allow for the use of Urbit without jeopardizing cryptographic ownership of their assets. Toward this end, we created the **Urbit Hierarchical Deterministic (HD) Wallet** for the storage of points. The Urbit HD Wallet is not one key-pair, but a system of related key-pairs that each have distinct powers, from setting networking keys for communicating in the Arvo network to transferring ownership of points.
44+
45+The Urbit HD Wallet's derivation paths have a hierarchical structure, so that keys with different powers can be physically separated. A \"master ticket" can re-derive the entire wallet in case of loss. The encryption and authentication keys that points ships use to sign messages within the network are also derived from the wallet.
46+
47+Urbit HD wallets are composed of the following items, which are each assigned to their own individual Ethereum key-pairs.
48+
49+### Master Ticket
50+
51+Think of your master ticket like a very high-value password. The master ticket is the secret code from which all of your other keys are derived. Technically, your master ticket is seed entropy. You should never share it with anyone, and store it very securely. This ticket can derive all of your other keys: your ownership key and all of the related proxies.
52+
53+### Ownership Address
54+
55+An ownership address has all rights over the assets deeded to it. These rights are on-chain actions described and implemented in the Ecliptic, Azimuth's suite of governing smart-contracts.
56+
57+### Proxies
58+
59+Proxy addresses allow you to execute non-ownership related actions like spawning child points, voting, and setting networking keys without jeopardizing the keys you've designated with ownership rights. Setting proxy rights is optional, but it is recommended for on-chain actions you will execute more frequently.
60+
61+- **Management Proxy**
62+
63+ Can configure or set Arvo networking keys and conduct sponsorship related
64+ operations.
65+
66+- **Voting Proxy**
67+
68+ Galaxies only. Galaxies are the part of the galactic senate, and this means
69+ they can cast votes on new proposals including changes to the Ecliptic.
70+
71+- **Spawn Proxy**
72+
73+ For stars and galaxies only. Can create new child points.
74+
75+![](https://media.urbit.org/fora/proposals/UP-8.jpg)
76+
77+
78+Most Ethereum tokens use the ERC-20 standard for smart contracts. Azimuth points
79+are, however, essentially different from most Ethereum tokens, due to points not
80+being fungible. Since any two stars will handle social-networking realities in a
81+different way, they will carry a different reputation. Points are to houses as
82+tokens are to gold.
83+
84+The ERC-721 standard, having been made specifically to provide a smart-contract
85+interface for non-fungible assets, serves our needs well. This is the standard
86+that we use for deeding Azimuth points.
87+
88+Points, and all of their blockchain operations, are governed by the Ecliptic.
89+The Ecliptic is an Ethereum smart-contract that governs point state and the
90+ownership, spawn, management, and voting rights affiliated with your points.
91+
92+For the technical implementation details Azimuth, take a look at the
93+[Github repo](https://github.com/urbit/azimuth).
concepts/azimuth/_index.mddeleted−21
@@ -1,21 +0,0 @@
1−+++
2−title = "Azimuth"
3−weight = 6
4−sort_by = "weight"
5−template = "sections/docs/chapters.html"
6−+++
7−Azimuth is a general-purpose public-key infrastructure (PKI) on the Ethereum blockchain, used as a platform for Urbit identities that we call _points_. You need a point to use the Arvo network.
8−
9−The primary way to interact with Azimuth is through our [Bridge](https://github.com/urbit/bridge) application and the node libraries that it depends on, azimuth-js and keygen-js. Take a look at the source and play around or see [Getting Started](/docs/getting-started).
10−
11−## Arvo vs. Azimuth
12−
13−Urbit is a project, not a single computer system. It has three components: Arvo, the operating system; Azimuth, the identity system; and Aegean, the pattern for creating software experiences for individual Urbit communities. Let's compare the first two.
14−
15−**Arvo** is an operating system that provides the software for a personal server. These personal servers together constitute the peer-to-peer Arvo network. To make this network work on the social level, Arvo is built to work with a system of scarce and immutable identities.
16−
17−**Azimuth** is the public-key infrastructure built to be such a system. A suite of smart-contracts on the Ethereum blockchain, Azimuth determines which Ethereum addresses own which Azimuth identities, called _points_. All point-related operations, such as transfers, are governed at this layer. But Azimuth isn't built strictly for Arvo -- it could be used as a generalized identity system for other projects.
18−
19−These otherwise-parallel systems meet when you want to connect to the Arvo network. Your Arvo personal server, called your _ship_, needs to be able to prove cryptographically that it is who it says it is. This proof comes in the form of a keyfile, derived from your point, that you use to start your ship.
20−
21−A metaphor might help illustrate the relationship between these two systems: the Arvo network is the neighborhood that you live in; Azimuth is the bank vault that stores the deed to your house.
concepts/azimuth/blockchain.mddeleted−47
@@ -1,47 +0,0 @@
1−+++
2−title = "Why Urbit Uses a Blockchain"
3−weight = 1
4−template = "doc.html"
5−+++
6−The Arvo network is composed of personal servers: instances of the Arvo operating system, called ships,
7−that communicate as peers.
8−
9−Every ship has an associated secure identity, called a point, that it needs
10−to connect to the network. Your point is your name and your network address.
11−Each point has associated authentication and encryption keys for networking.
12−Think of a point as an IP address, a domain name, and a PGP key-pair.
13−
14−There are a limited number of points and, as you might expect, scarcity gives
15−points value. This means that bad actors – spammers, scammers, and malware-spreaders – can be made economically unviable. Points being
16−immutable allows for reputation systems to be built on top,
17−keeping the network friendly and giving users information to help them decide
18−who to treat as a trusted peer.
19−
20−At the user level, having one identity for your digital life means that all the
21−services that you trust recognize you. You no longer need to worry about
22−managing dozens of different logins. When you're using Arvo, everything you do
23−is "verified" in the sense that it links back to your point.
24−
25−But wait! We need some way to secure these identities. To that end, we have
26−built a public-key infrastructure (PKI) called _Azimuth_ on the Ethereum
27−blockchain. Azimuth acts as a decentralized ledger for points: it determines
28−which Ethereum addresses own which points. It's separate from and parallel to
29−the Arvo network.
30−
31−In theory, our ecosystem doesn't need a blockchain, because Urbit identities are
32−more like real estate than currency: they change hands slowly. A low-friction,
33−zero-trust solution to the double-spend problem isn't an economic necessity for
34−transactions such as ours. So we could have the Arvo network run its own
35−key-signing system. But, since Azimuth identities are valuable, you don't want
36−to put them in an self-hosted PKI that isn't generally recognized as secure.
37−Arvo is still young, we'd prefer to use an existing system for people to secure
38−their property.
39−
40−Moving the Urbit land registry to Ethereum is an easy and obvious solution to
41−this problem. We chose Ethereum over Bitcoin because the former is built for
42−computation Landscape the latter is not. We need a computational blockchain to
43−enforce the specific rules of the Urbit identity registry.
44−
45−For more background on the decision to use the Ethereum blockchain, check out
46−[these](https://urbit.org/posts/essays/urbit-and-the-blockchain/)
47−[two](https://urbit.org/posts/essays/bootstrapping-urbit-from-ethereum/) posts.
concepts/azimuth/wallet.mddeleted−75
@@ -1,75 +0,0 @@
1−+++
2−title = "The Urbit HD Wallet"
3−weight = 2
4−template = "doc.html"
5−+++
6−Owners of Azimuth _points_ need safeguards that allow for the use of Urbit
7−without jeopardizing cryptographic ownership of their assets. Toward this end,
8−we created the **Urbit Hierarchical Deterministic (HD) Wallet** for the storage of
9−points. The Urbit HD Wallet is not one key-pair, but a system of related
10−key-pairs that each have distinct powers, from setting networking keys for
11−communicating in the Arvo network to transferring ownership of points.
12−
13−The Urbit HD Wallet's derivation paths have a hierarchical structure, so
14−that keys with different powers can be physically separated. A \"master ticket"
15−can re-derive the entire wallet in case of loss. The encryption and
16−authentication keys that points ships use to sign messages within the network
17−are also derived from the wallet.
18−
19−Urbit HD wallets are composed of the following items, which are each assigned to
20−their own individual Ethereum key-pairs.
21−
22−#### Master Ticket
23−
24−Think of your master ticket like a very high-value password. The master ticket
25−is the secret code from which all of your other keys are derived. Technically,
26−your master ticket is seed entropy. You should never share it with anyone, and
27−store it very securely. This ticket can derive all of your other keys: your
28−ownership key and all of the related proxies.
29−
30−#### Ownership Address
31−
32−An ownership address has all rights over the assets deeded to it. These rights
33−are on-chain actions described and implemented in the Ecliptic, Azimuth's suite
34−of governing smart-contracts.
35−
36−#### Proxies
37−
38−Proxy addresses allow you to execute non-ownership related actions like spawning
39−child points, voting, and setting networking keys without jeopardizing the keys
40−you've designated with ownership rights. Setting proxy rights is optional, but
41−it is recommended for on-chain actions you will execute more frequently.
42−
43−- **Management Proxy**
44−
45− Can configure or set Arvo networking keys and conduct sponsorship related
46− operations.
47−
48−- **Voting Proxy**
49−
50− Galaxies only. Galaxies are the part of the galactic senate, and this means
51− they can cast votes on new proposals including changes to the Ecliptic.
52−
53−- **Spawn Proxy**
54−
55− For stars and galaxies only. Can create new child points.
56−
57−![](https://media.urbit.org/fora/proposals/UP-8.jpg)
58−
59−
60−Most Ethereum tokens use the ERC-20 standard for smart contracts. Azimuth points
61−are, however, essentially different from most Ethereum tokens, due to points not
62−being fungible. Since any two stars will handle social-networking realities in a
63−different way, they will carry a different reputation. Points are to houses as
64−tokens are to gold.
65−
66−The ERC-721 standard, having been made specifically to provide a smart-contract
67−interface for non-fungible assets, serves our needs well. This is the standard
68−that we use for deeding Azimuth points.
69−
70−Points, and all of their blockchain operations, are governed by the Ecliptic.
71−The Ecliptic is an Ethereum smart-contract that governs point state and the
72−ownership, spawn, management, and voting rights affiliated with your points.
73−
74−For the technical implementation details Azimuth, take a look at the
75−[Github repo](https://github.com/urbit/azimuth).
getting-started/_index.md−2
@@ -5,8 +5,6 @@ sort_by = "weight"
5template = "sections/docs/chapters.html"
5template = "sections/docs/chapters.html"
6+++
6+++
7
7
8−# Getting Started
9−
10Welcome to Urbit, a personal server. Urbit isn't ready for serious use yet, but it's available to try out. Follow this step-by-step guide to get an Azimuth point, install Urbit, and join the community.
8Welcome to Urbit, a personal server. Urbit isn't ready for serious use yet, but it's available to try out. Follow this step-by-step guide to get an Azimuth point, install Urbit, and join the community.
11
9
12### [Step 1: Using Bridge](using-bridge)
10### [Step 1: Using Bridge](using-bridge)
getting-started/using-bridge.md+1−1
@@ -40,7 +40,7 @@ If you already own a point, then click on the `Details ->` under your sigil in t
40
40
41If you just accepted a point, you'll be returned to your point screen. Notice that that links and buttons are now clickable. You now own this point!
41If you just accepted a point, you'll be returned to your point screen. Notice that that links and buttons are now clickable. You now own this point!
42
42
43−Click the link that says `Set Urbit networking keys`. The field that is presented in the resulting page expects a 32-byte hexadecimal string. If it's filled already, no action is required. If this is empty, you will need to generate such a string. You can generate this data any way you please, but in the terminal on MacOS or Linux, you can write
43+Click the link that says `Set network keys`. The field that is presented in the resulting page expects a 32-byte hexadecimal string. If it's filled already, no action is required. If this is empty, you will need to generate such a string. You can generate this data any way you please, but in the terminal on MacOS or Linux, you can write
44
44
45```
45```
46hexdump -n 32 -e '4/4 "%08X"' /dev/random
46hexdump -n 32 -e '4/4 "%08X"' /dev/random
learn/hoon/hoon-tutorial/gates.md+5−38
@@ -50,7 +50,7 @@ Like all arms, `$` is computed with its parent core as the subject. When `$` is
50Let's make a gate that takes any unsigned integer (i.e., an atom) as its sample and returns that value plus one as the product. To do this we'll use the `|=` rune. We'll bind this gate to the face `inc` for 'increment':
50Let's make a gate that takes any unsigned integer (i.e., an atom) as its sample and returns that value plus one as the product. To do this we'll use the `|=` rune. We'll bind this gate to the face `inc` for 'increment':
51
51
52```
52```
53−> =inc |=(a=@ +(a))
53+> =inc |=(a=@ (add 1 a))
54
54
55> (inc 1)
55> (inc 1)
562
562
@@ -66,13 +66,13 @@ The gate works as promised -- it takes any number `n` and returns `n + 1`. Let'
66
66
67### The `|=` Rune
67### The `|=` Rune
68
68
69−We typically use the `|=` rune to create a gate. In the expression above the `|=` is immediately followed by a set of parentheses containing two subexpressions: `a=@` and `+(a)`. The first defines the gate's sample (input value type), and the second defines the gate's product (value).
69+We typically use the `|=` rune to create a gate. In the expression above the `|=` is immediately followed by a set of parentheses containing two subexpressions: `a=@` and `(add 1 a)`. The first defines the gate's sample (input value type), and the second defines the gate's product (value).
70
70
71When we used the `|%` rune in the last lesson we didn't use parentheses because we were writing in "tall form" syntax, whereas here we are writing in "flat form" syntax. (The latter uses parentheses and is more suitable for shorter snippets of code.) We'll explain these concepts more thoroughly in lesson 2.2.
71When we used the `|%` rune in the last lesson we didn't use parentheses because we were writing in "tall form" syntax, whereas here we are writing in "flat form" syntax. (The latter uses parentheses and is more suitable for shorter snippets of code.) We'll explain these concepts more thoroughly in lesson 2.2.
72
72
73In the example gate above, `inc`, the sample is defined by `a=@`. This means that the sample is defined as an atom, `@`, meaning that the gate will take as input anything of that type. The sample is given the face `a`. With the face it's easier to refer to the sample in later code, if desired.
73In the example gate above, `inc`, the sample is defined by `a=@`. This means that the sample is defined as an atom, `@`, meaning that the gate will take as input anything of that type. The sample is given the face `a`. With the face it's easier to refer to the sample in later code, if desired.
74
74
75−In `inc`, the product is defined by `+(a)`. There's not much to it -- it returns the value of `a + 1`!
75+In `inc`, the product is defined by `(add 1 a)`. There's not much to it -- it returns the value of `a + 1`!
76
76
77The second subexpression after the `|=` rune is used to build the gate's `$` arm. That's where all the computations go.
77The second subexpression after the `|=` rune is used to build the gate's `$` arm. That's where all the computations go.
78
78
@@ -251,45 +251,12 @@ We can use `ten(b 25)` to produce a variant of `ten`. Calling this mutant versi
251175
251175
252```
252```
253
253
254−Let's unbind `ten`:
254+Before finishing the lesson let's unbind `ten`:
255
255
256```
256```
257> =ten
257> =ten
258```
258```
259
259
260−## Looping
261−
262−Let's examine a new gate.
263−
264−```
265−|= [a=@ud b=@ud]
266−=| c=@ud
267−|-
268−?: =(b 0)
269− c
270−$(c (add a c), b (dec b))
271−```
272−
273−This gate takes two arguments and multiplies them together using only `add` and `dec` This is an extremely naive way to do multiplication but let's examine it anyway.
274−
275−The first thing worth noticing is the new rune `|-` which you can think of as a looping structure. We're denoting some bit of code that we want to run multiple times. This is a lie but go with it for a moment.
276−
277−The next few lines should be pretty clear, if `b` is `0` we're going to return `c`.
278−When it isn't, we are going to use the irregular form of the `%=` rune, the wide form of this line would look like this.
279−
280−```
281−%=($ c (add a c), b (dec b))
282−```
283−
284−What this rune does is resolve a wing with changes. In this case, and in many you will see, the wing we want to resolve is `$` or the `|-` we are inside. The rest are a set of changes to make to the subject of that wing. We are going to add `a` to `c` and decrement `b` and then run the code again starting from `|-`.
285−
286−In the next lesson, we'll examine `|-` in more detail.
287−
288−### Jets
289−
290−Hoon code is compiled to Nock and Nock is extremely simple and naive in the way a number of things are done. For example, the only mathematical operation Nock has is increment. All other mathematical functions are built out of this. While this is conceptually doable, actually running this code could be unnecessarily slow. This is the reason for jets, a set of functionally identical code that could be run instead of the compiled Nock to speed up execution. To learn more about Jets see [jets doc].
291−
292−
293## Exercise 1.5.1 Solution
260## Exercise 1.5.1 Solution
294
261
295Write a gate that takes an atom, `a=@`, and which returns double the value of `a`. Bind this gate to `double` and test it in the dojo.
262Write a gate that takes an atom, `a=@`, and which returns double the value of `a`. Bind this gate to `double` and test it in the dojo.
@@ -304,4 +271,4 @@ Write a gate that takes an atom, `a=@`, and which returns double the value of `a
30450
27150
305```
272```
306
273
307−### [Recursion](../recursion)
274+### [Next Lesson: Multi-gate Cores and Doors](../multi-gate-cores-and-doors)
learn/hoon/hoon-tutorial/nouns.md+14−3
@@ -24,6 +24,18 @@ Here are some cells:
24
24
25All of the above are nouns.
25All of the above are nouns.
26
26
27+## Recursive Definitions
28+
29+You may or may not have noticed that the definition of 'noun' is [recursive](https://en.wikipedia.org/wiki/Recursion). Recursion is an important concept for functional programming, so it's worth taking a moment to understand it better.
30+
31+A recursive definition has three clauses: a base clause, a generating clause, and a closure clause. Let's say you want to use recursion to define some X. The definition should allow one to determine whether any given object is a member of X. The **base clause** of the recursive definition defines one or more objects as trivial members of X. The **generating clause** defines other objects as also being X by their relationship to previously established members of X. The **closure clause** asserts that nothing else is a member of X than what has been given in the first two clauses. Often the closure clause is not explicitly stated.
32+
33+For example, let's say you want to define the phrase 'ancestor of George Washington'. Which 'objects' are members of that set? The base clause is simple: the parents of George Washington are trivial ancestors of George Washington. The generating clause is: given that some x is an ancestor of George Washington, the parents of x are also ancestors of George Washington. The closure clause is: nothing else is an ancestor of George Washington. That's it!
34+
35+Let's restate the definition of **noun** in these terms. The base clause of the definition of a 'noun' is: all atoms are nouns (where an 'atom' is an unsigned integer). The generating clause is: if x and y are nouns, then the cell `[x y]` is also a noun. (A 'cell' is an ordered pair of nouns.). The closure clause is: nothing else is a noun.
36+
37+We belabor this point about recursion only because it's an important concept for having a firm grasp of functional programming. We'll talk more about recursion at various points in this series.
38+
27### Nouns as Binary Trees
39### Nouns as Binary Trees
28
40
29A [binary tree](https://en.wikipedia.org/wiki/Binary_tree) has a single base node, and each node of the tree may have up to two child nodes (but it need not have any). A node without children is a 'leaf'. You can think of a noun as a binary tree whose leaves are atoms, i.e., unsigned integers. All non-leaf nodes are cells. To visualize this, consider the following representation of the noun: `[12 [17 45]]`:
41A [binary tree](https://en.wikipedia.org/wiki/Binary_tree) has a single base node, and each node of the tree may have up to two child nodes (but it need not have any). A node without children is a 'leaf'. You can think of a noun as a binary tree whose leaves are atoms, i.e., unsigned integers. All non-leaf nodes are cells. To visualize this, consider the following representation of the noun: `[12 [17 45]]`:
@@ -51,7 +63,6 @@ Each number is an atom; each dot is a cell. Let's look at another example, this
51
63
52An atom is a trivial tree of just one node; e.g., `17`.
64An atom is a trivial tree of just one node; e.g., `17`.
53
65
54−
55## Atoms
66## Atoms
56
67
57Atoms are unsigned integers. These are often represented by the dojo as unsigned integers in decimal notation, e.g., `17`.
68Atoms are unsigned integers. These are often represented by the dojo as unsigned integers in decimal notation, e.g., `17`.
@@ -167,7 +178,7 @@ All of the above are atoms. The underlying noun of each is just an unsigned int
167313
178313
168```
179```
169
180
170−The `\`@\`` syntax is used to 'cast' a value to a raw atom, i.e., an atom without an aura. Don't worry about exactly what `\`@\`` means just yet. Casts will be explained in more detail in a later lesson. For now all you need to know is that a cast doesn't change the underlying value of the noun.
181+The `\`@\`` syntax is used to 'cast' a value to a raw atom, i.e., an atom without an aura. Don't worry about exactly what `\`@\`` means just yet. Casts will be explained in more detail in a later lesson. For now all you need to know is that a cast doesn't change the underlying value of the noun; it's used here only to change how the value is printed in the dojo output.
171
182
172#### Identities, Cords, and Terms
183#### Identities, Cords, and Terms
173
184
@@ -303,7 +314,7 @@ In this cell `32` is the head and `320` is the tail. Cells can contain cells, a
303[[%in 0xa] 'cell']
314[[%in 0xa] 'cell']
304```
315```
305
316
306−There isn't _much_ mystery about cells, but there is a little. So far whenever we've entered a cell into the dojo, it not only returned the same cell; the cell was printed in the same way it was entered. This doesn't always happen. The dojo is obligated to evaluate the input and return the correct answer, but it doesn't have to show the result in exactly the same way:
317+I said there isn't _much_ mystery about cells, but there is a little. So far whenever we've entered a cell into the dojo, it not only returned the same cell; the cell was printed in the same way it was entered. This doesn't always happen. The dojo is obligated to evaluate the input and return the correct answer, but it doesn't have to show the result in exactly the same way:
307
318
308```
319```
309> [6 [62 620]]
320> [6 [62 620]]
learn/hoon/hoon-tutorial/recursion.udondeleted−200
@@ -1,200 +0,0 @@
1−:- :~ navhome/'/docs/'
2− next/'true'
3− sort/'3'
4− title/'Recursion'
5− ==
6−;>
7−
8−# Recursion
9−
10−Recursion is a common pattern for solving certain problems in most programming
11−languages, and Hoon is no exception. One of the classically recursive problems
12−is that of factorial. The factorial of _n_ is the product of all positive
13−integers less than or equal to N. Thus the factorial of 5, denoted as _5!_,
14−would be:
15−
16−```
17−5 * 4 * 3 * 2 * 1 = 120
18−```
19−
20−### Factorial In Hoon
21−
22−Let's implement a factorial calculator in Hoon. To do so, we'll write a
23−recursive `gate` (Hoon's equivalent of a function) to perform the relevant
24−computation. Save the code below as `factorial.hoon` in your ship's `/gen`
25−directory.
26−
27−```
28−|= n=@ud
29−?: =(n 1)
30− 1
31−(mul n $(n (dec n)))
32−```
33−
34−Our `gate` takes one sample (argument) `n` that must nest inside `@ud`, the
35−unsigned-integer type.
36−
37−Next we check to see if `n` is `1`. If so, the result is just `1`, since
38−`1 * 1 = 1`.
39−
40−If, however, `n` is _not_ `1`, then we branch to the final line of the code,
41−`(mul n $(n (dec n)))`, where the recursion logic lives. Here, we multiply `n`
42−by the recursion of `n` minus `1`. `$` initiates recursion: it calls the gate
43−that we're already in, but replaces its sample.
44−
45−In our example, we multiply `n` with the product of this _entire gate
46−all over again_ with `$(n (dec n))`, except when that new gate has its sample
47−decremented by one. This works recursively because each new gate will, of
48−course, itself contain the code to call a further-decremented gate. Gates will
49−continue to call new, further-decremented gates until `n` is `1`, and that `1`
50−will be the final number to be multiplied by.
51−
52−Let's run the program in the Dojo:
53−
54−```
55−> +factorial 5
56−120
57−```
58−
59−It may help to visualize the operation of our example gate. The pseudo-Hoon below
60−illustrates what happens when we use it to find the factorial of 5:
61−
62−```
63−(factorial 5)
64−(mul 5 (factorial 4))
65−(mul 5 (mul 4 (factorial 3)))
66−(mul 5 (mul 4 (mul 3 (factorial 2))))
67−(mul 5 (mul 4 (mul 3 (mul 2 (factorial 1)))))
68−(mul 5 (mul 4 (mul 3 (mul 2 1))))
69−(mul 5 (mul 4 (mul 3 2)))
70−(mul 5 (mul 4 6))
71−(mul 5 24)
72−120
73−```
74−
75−It's easy to see how we're "floating" gate calls until we reach the final
76−iteration of such calls that only produces a value. The `mul n` component of the
77−gate leaves something like `mul 5`, waiting for the final series of terms
78−to be operated upon. The `$(n (dec n))` component is what expands out the
79−expression, as illustrated by `(factorial 4)`. Once the expression cannot be
80−expanded out further, the operations work backwards, successively feeding values
81−into the `mul` functions behind them.
82−
83−##### Tail-Call Optimization
84−
85−Our last example isn't a very efficient use computing resources. The
86−pyramid-shaped illustration approximates what's happening on the *call stack*, a
87−memory structure that tracks the instructions of the program. In our example
88−code, every time a parent gate calls another gate, the gate being called is
89−"pushed" to the top of the stack in the form of a frame. This process continues
90−until a value is produced instead of a function, completing the stack.
91−
92−```
93− Push order Pop order
94−(fifth frame) ^ |
95−(fourth frame) | |
96−(third frame) | |
97−(second frame) | |
98−(first frame) | V
99−```
100−
101−Once this stack of frames is completed, frames "pop" off the stack starting at
102−the top. When a frame is popped, it executes the contained gate and passes
103−produced data to the frame below it. This process continues until the stack
104−is empty, giving us the gate's output.
105−
106−When a program's final expression uses the stack in this way, it's considered to
107−be *not tail-recursive*. This usually happens when the last line of executable
108−code calls more than one gate, our example code's `(mul n $(n (dec n)))` being
109−such a case. That's because such an expression needs to hold each iteration of
110−`$(n (dec n)` in memory so that it can know what to run against the `mul`
111−function every time.
112−
113−To reiterate: if you have to manipulate the result of a recursion as the last
114−expression of your gate, as we did in our example, the function is not
115−tail-recursive, and therefore not very efficient with memory. A problem arises
116−when we try to recurse more times that we have space on the stack. This will
117−result in our computation failing and producing a stack overflow. If we tried
118−to find the factorial of `5.000.000`, for example, we would almost certainly
119−run out of stack space.
120−
121−But the Hoon compiler, like most compilers, is smart enough to notice when the
122−last statement of a parent can reuse the same frame instead of needing to
123−add new ones onto the stack. If we write our code properly, we can use a single
124−frame that simply has its values replaced with each recursion.
125−
126−##### A Tail-Recursive Gate
127−
128−With a bit of refactoring, we can write a version of our factorial gate that
129−_is_ tail-recursive and can take advantage of this feature:
130−
131−```
132−|= n=@ud
133−=/ t=@ud 1
134−|-
135−?: =(n 1)
136− t
137−$(n (dec n), t (mul t n))
138−```
139−
140−The above code should look familiar. We are still building a gate that
141−takes one argument `n`. This time, however, we are also putting a face on a
142−`@ud` and setting it's initial value to 1. The `|-` here is used to create a new
143−gate with one arm `$` and immediately call it. Think of `|-` as the recursion
144−point.
145−
146−We then evaluate `n` to see if it is 1. If it is we return the value of `t`. In
147−the case that `n` is anything other than 1, we perform our recursion:
148−
149−```
150−$(n (dec n), t (mul t n))
151−```
152−
153−All we are doing here is recursing our new gate and modifying the values of `n`
154−and `t`. `t` is used as an accumulator variable that we use to keep a running
155−total for the factorial computation.
156−
157−Let's use pseudo-Hoon to illustrate how the stack is working in this example for
158−factorial 5.
159−
160−```
161−(factorial 5)
162−(|- 5 1)
163−(|- 4 5)
164−(|- 3 20)
165−(|- 2 60)
166−(|- 1 120)
167−120
168−```
169−
170−We simply multiply `t` and `n` to produce the new value of `t`, and then
171−decrement `n` before repeating. Since this `$` call is the final and solitary
172−thing that is run in the default case and since we are doing all computation
173−before the call, this version is properly tail-recursive. We don't need to do
174−anything to the result of the recursion except recurse it again. That means that
175−each iteration can be replaced instead of held in memory.
176−
177−##### A Note on `$`
178−
179−`$` (pronounced "buc") is, in its use with recursion, a reference to the gate that we are inside
180−of. That's because a gate is just a core with a single arm named `$`. The
181−subject is searched depth-first, head before tail, with faces skipped, and
182−stopping on the first result. In other words, the first match found in the head
183−will be returned. If you wished to refer to the outer `$` in this context, the
184−idiomatic way would be to use [`^$`](/docs/reference/rune/ket). The `^` operator
185−skips the first match of a name.
186−
187−The syntax used is also the irregular form of the `%=` rune.
188−
189−### Exercises
190−
191−1. Write a recursive gate that produces the first _n_
192−[Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number)
193−
194−2. Write a recursive gate that produces a list of moves to solve the
195−[Tower of Hanoi problem](https://en.wikipedia.org/wiki/Tower_of_Hanoi).
196−Disks are stacked on a pole by decreasing order of size. Move all of the
197−disks from one pole to another with a third pole as a spare, moving one
198−disc at a time, without putting a larger disk on top of a smaller disk.
199−
200−### [Next Lesson: Multi-gate Cores and Doors](../multi-gate-cores-and-doors)
learn/hoon/workbook/even.md+3−3
@@ -25,7 +25,7 @@ The code above builds a gate. The gate's first argument is a cell provided by Do
25:- %noun
25:- %noun
26```
26```
27
27
28−This code is the third line of the `%say` "boilerplate, and it produces a `cask` with the head of `%noun`. We could use any `mark` here, but `%noun` is the most generic type, able to fit any data.
28+This code is the third line of the `%say` "boilerplate," and it produces a `cask` with the head of `%noun`. We could use any `mark` here, but `%noun` is the most generic type, able to fit any data.
29
29
30Below we'll examine the the series of `?` runes used.
30Below we'll examine the the series of `?` runes used.
31
31
@@ -41,7 +41,7 @@ The first expression is:
41=(0 (mod n 2))
41=(0 (mod n 2))
42```
42```
43
43
44−which simply asks if n is even or not.
44+which simply asks if `n` is even or not.
45
45
46The second expression is:
46The second expression is:
47
47
@@ -51,4 +51,4 @@ The second expression is:
51 ==
51 ==
52```
52```
53
53
54−Again we and two expressions with `?&` the first is just checking if n is greater than or equal to 1. The second we have artificially use the `?!` rune to demonstrate its use. `?!` is a logical NOT operation. We use that on the result of asking if n is greater than 100 to effectively ask if it is less than or equal to 100.
54+Again we use the "and" operator on two expressions with `?&` the first is just checking if n is greater than or equal to 1. The second we have artificially use the `?!` rune to demonstrate its use. `?!` is a logical NOT operation. We use that on the result of asking if n is greater than 100 to effectively ask if it is less than or equal to 100.
learn/hoon/workbook/fib.md+10−9
@@ -1,4 +1,4 @@
1−Write a generator that produce a list of Fibonacci numbers up to n.
1+In this example, we will write a generator that produces a list of Fibonacci numbers up to `n`.
2
2
3```
3```
4|= n=@ud
4|= n=@ud
@@ -14,32 +14,33 @@ Write a generator that produce a list of Fibonacci numbers up to n.
14==
14==
15```
15```
16
16
17−First we need to produce a gate which takes an `@ud` so we know when to stop producing the list.
17+On the first line, we use `|=` to produce a gate which takes an `@ud` that's stored in the face `n`. This `n` sample that we give our gate determines how long our Fibonacci sequence is. When the list that our program builds has `n` members, the program ends.
18
18
19```
19```
20%- flop
20%- flop
21```
21```
22+
23+In the line above, we use `flop` on the output of the rest of the program. `flop` is a standard library function to reverse a list.
24+
22−Next we're going to call `flop` on the output of the rest of the program. `flop` is a standard library function to reverse a list. Why are we using this instead of producing the list in the order we want it in the first place? With lists adding an element to the end is an expensive operation that gets more expensive the longer the list is. Adding an element to the front however is cheap. In Big O Notation, adding to the end of a list is O(n) and the front is O(1).
25+Why are we using this instead of just producing the list in the order we want it in the first place? Because with lists, adding an element to the end is a computationally expensive operation that gets more expensive the longer the list is, due to the fact that you need to traverse to the end of the tree. Adding an element to the front, however, is cheap. [In Big-O Notation](https://en.wikipedia.org/wiki/Big_O_notation), adding to the end of a list is O(n) and the front is O(1).
23
26
24```
27```
25=+ [i=0 p=0 q=1 r=*(list @ud)]
28=+ [i=0 p=0 q=1 r=*(list @ud)]
26```
29```
27
30
28−We are going to need several values throughout the execution of this task so we set them all up here. It's worth noticing that because the subject is searched head first, ignoring faces, we can define a number of faces at once by putting them in a tuple like this.
29−
30−The only one of these that is interesting is `r` We're using `*` to bunt, or get the default value for, the mold `(list @ud)`.
31+Here we declare several values that we are going to use the execution of our program. The only one of these that is noteworthy is `r`: we're using `*` to bunt, or get the default value for, the mold `(list @ud)`.
31
32
32```
33```
33|- ^+ r
34|- ^+ r
34```
35```
35
36
36−Next we define the trap that will contain the majority of our program. We also use `^+` to cast the output by example. This will result in the output being the same type as `r`, a list of `@ud`.
37+With this code, we define `|-`, the _trap_ that acts as a recursion point and contains the rest of our program. We also use `^+` to cast the output by example. This will result in the output being the same type as `r`, a list of `@ud`.
37
38
38```
39```
39?: =(i n) r
40?: =(i n) r
40```
41```
41
42
42−Here is our terminating case, if `i` and `n` are equal we produce `r` as the result.
43+In the code above, `?:` checks whether the first child, `=(i n)`, our terminating case, is true or false. If it is true, it branches to `r` and the program ends. If it is false, the program continues to the code below.
43
44
44```
45```
45%= $
46%= $
@@ -50,4 +51,4 @@ Here is our terminating case, if `i` and `n` are equal we produce `r` as the res
50==
51==
51```
52```
52
53
53−The final expression in our program calls the `$` arm of the trap we are in with some changes. We increment `i`, set `p` to be `q` and `q` becomes the sum of `q` and `q`. `r` becomes a cell of `q` and whatever `r` was previously. This is the list that will get flopped to produce the result at the end of the computation.
54+The final expression in our program calls the `$` arm of the trap we are but makes some changes: we increment `i`, set `p` to be `q` and `q` becomes the sum of `p` and `q`. `r` becomes a cell of `q` and whatever `r` was previously. The list built from this is the one that will get `flop`ped to produce the result at the end of the computation.
using/admin.md+2−5
@@ -120,9 +120,6 @@ our HTTPS isn't audited / battle tested, we just call it "secure" HTTPS.
120You can find that on `8443`. Or `8444` (and so on) if you're already
120You can find that on `8443`. Or `8444` (and so on) if you're already
121running something on `8443`.
121running something on `8443`.
122
122
123−A complete walkthrough of the Urbit web interface is
124−[here](../web/).
125−
126## Moons
123## Moons
127
124
128Urbit namespace is distributed by having parent nodes sign the keys for child
125Urbit namespace is distributed by having parent nodes sign the keys for child
@@ -166,8 +163,8 @@ moon: ~faswep-navred-sampel-palnet
166`<keyfile>` will be at `path/to/sampel-palnet/.urb/put/moon.key`
163`<keyfile>` will be at `path/to/sampel-palnet/.urb/put/moon.key`
167and does not need editing to be used with the `-k` option.
164and does not need editing to be used with the `-k` option.
168
165
169−You can use the resulting output in the same installation flow from
166+You can use the resulting output in the same installation flow from the
170−[install](../install) and [setup](../setup), following the same scheme as
167+[Booting a Ship](https://urbit.org/docs/getting-started/booting-a-ship/) guide, following the same scheme as
171for booting a planet. That scheme is:
168for booting a planet. That scheme is:
172
169
173```
170```
using/filesystem.md+1−1
@@ -1,5 +1,5 @@
1+++
1+++
2−title = "Introduction to the Filesystem"
2+title = "Filesystem"
3weight = 4
3weight = 4
4template = "doc.html"
4template = "doc.html"
5+++
5+++
getting-started/operating-a-star.md → using/operating-a-star.mdrenamed

The content is the same.

using/udon.md → using/sail-and-udon.mdrenamed+710−58
@@ -1,17 +1,698 @@
1+++
1+++
2−title = "Udon"
2+title = "Sail and Udon"
3−weight = 8
3+weight = 7
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6+
7+Sail is Hoon markup that’s used to render a web page with XML. But what makes it special is that you can run arbitrary Hoon code within such a web page without using a separate markup language.
8+
9+Udon is a way to write content for the web. It's a minimalist markup language for creating and rendering text documents, with a Markdown-inspired syntax. It's integrated with our Hoon programming language, allowing it to be used as standalone prose in its own file or embedded inside a Hoon source file, in which case it will be parsed into a tree of HTML nodes using Sail.
10+
11+This document will be divided into two main sections: the Sail guide and the Udon guide. The Udon guide has two sub-sections that each walk you through a practical example. Also, you're encouraged to read the Getting Started section below, which applies to both Udon and Sail.
12+
6## Table of Contents
13## Table of Contents
7
14
15+- #### [Sail: A Guide](#sail)
16+
8−- #### [Udon: A Guide](#guide)
17+- #### [Udon: A Guide](#udon)
18+
19+- #### [Udon: A Simple Blog](#blog)
20+
21+- #### [Udon: A Static Site](#static)
22+
23+## Getting Started
24+
25+Before starting with either Sail or Udon, make sure that your ship is
26+[mounted to Unix](https://urbit.org/docs/using/setup/)
27+
28+To host that output, your ship also has a web-server, called
29+[Eyre](https://urbit.org/docs/using/web/), that can be found at
30+`http://localhost:8080/` if it’s your first ship that’s running on the a
31+machine, `http://localhost:8081/` if it’s the second ship on that same machine,
32+and so on. In the startup messages, a ship will tell you which HTTP port it's
33+using.
34+
35+The `/web` directory of the `%home` desk is served by default. You can change
36+which desk you're serving by using the command `|serve` in the Dojo. If you
37+have already created and mounted a desk named `%sandbox`, for example, you can
38+switch to serving it with this command:
39+
40+```
41+|serve %sandbox
42+```
43+
44+The first time you serve a desk, `/web` will be included as default. After that,
45+you will need to explicitly append `/web` to the desk you're switching to --
46+otherwise, you'll need to write `http://localhost:8080/web` every time you
47+navigate to your web-server. Newly served desks not automatically having `/web`
48+as their root directory is a bug.
49+
50+To switch back to your `%home` desk and set `/web` as your root directory, run:
51+
52+```
53+|serve %/web
54+```
55+
56+We'll be serving the `%home` desk for the examples in this tutorial.
57+
58+### Rendering
59+
60+That server has access to source files located in `/<your-urbit>/home/web` and
61+any sub-folders thereof. For the purposes of this tutorial, we will only be
62+using files that are located in the `/<your-urbit>/home/web/pages` path.
63+
64+There is an important distinction between these two paths. According to
65+`/ren/urb.hoon`, any file inside of `/web` or any of its sub-directories
66+is put through a tree of renderers specified at `/ren/urb/tree.hoon`
67+-- _except_ for files inside of `/web/pages`. All of the files in `/web` and
68+its non-`/pages` children directories have various operations on files, such as
69+wrapping your Sail the `html`, `head`, and `body` nodes. This rendering tool,
70+called simply **Tree**, also adds certain formatting polish, such as a sidebar
71+that lists sibling files in the same directory.
72+
73+The `/web/pages` sub-directory is a unique case with its own rendering rules.
74+The Tree is not used when rendering files in this path. The existence of no tag
75+is inferred, and no special formatting is applied. Such simplicity is ideal for
76+introducing the basics of Sail. Any source file located in `/web/pages` must
77+produce a complete HTML node with "head" and "body" nodes as children.
78+
79+Understanding the details of the rendering pipeline is not necessary to complete
80+this tutorial. But, if you are curious, you might find it illuminating to
81+explore the contents of the `/ren` directory.
82+
83+So, if a Sail source file named `sailtest.hoon` is saved in your `/web/pages`
84+folder on your only running urbit process, you can view that source rendered
85+into a web-page at `localhost:8080/pages/sailtest/`.
86+
87+## <a name="sail"></a>Sail: A Guide
88+
89+It’s easy to see how Sail can directly translate to HTML:
90+
91+### Sail code
92+
93+```
94+;html
95+ ;head
96+ ;title: My first webpage
97+ ==
98+ ;body
99+ ;h1: Welcome!
100+ ; Hello, world!
101+ ; We're on the web.
102+ ;div;
103+ ;script@"http://unsafely.tracking.you/cookiemonster.js";
104+ ==
105+==
106+```
107+
108+### HTML code
109+
110+```
111+<html>
112+ <head>
113+ <title>My first webpage</title>
114+ </head>
115+ <body>
116+ <h1>Welcome!</h1>
117+ Hello, world!
118+ We’re on the web.
119+ <div></div>
120+ <script src="http://unsafely.tracking.you/cookiemonster.js"></script>
121+ </body>
122+</html>
123+```
124+
125+Save the above Sail code in `/home/web/pages/firstsail.hoon`, and the above
126+HTML code in `/home/web/pages/firsth.html`. Access the resulting pages by
127+navigating to `http://localhost:8080/pages/firstsail` and
128+`http://localhost:8080/pages/firsth.html`, respectively, in your browser. The
129+resulting pages should be identical!
130+
131+It shouldn't be hard to see the similarities here. So let's go into more
132+detail about what the differences are.
133+
134+### Tags and Closing
135+
136+In Sail, tag heads are written with the tag name prepended by `;`. Unlike in
137+HTML, there are different ways on closing tags, depending on the needs of the
138+tag. One of the nice things about Hoon is that you don’t have to be constantly
139+closing expressions; Sail inherits this convenience.
140+
141+#### Empty
142+
143+Empty tags are closed with a `;` following the tag. Example:
144+
145+```
146+;div;
147+```
148+
149+Equals:
150+
151+```
152+<div></div>
153+```
154+
155+#### Filled
156+
157+Filled tags are closed via line-break. To fill text inside, add `:` after the
158+tag name, then insert your plain text following a space. Example:
159+
160+```
161+;h1: The title
162+```
163+
164+Equals:
165+
166+```
167+<h1>The title</h1>
168+```
169+
170+#### Nested
171+
172+To nest tags, simply create a new line. Nested tags need to be closed
173+with `==`, because they expect a list of sub-tags. If we nest a line of plain
174+text with no tag, a `<p>` is prepended.
175+
176+Sail, like Hoon, is white-space sensitive. Unlike in Hoon, however, two spaces
177+(called a "gap") is not necessarily equivalent to a line-break in Sail.
178+
179+```
180+;body
181+ ;h1: Blog title
182+ This is some good content.
183+==
184+```
185+
186+Equals:
187+
188+```
189+<body>
190+ <h1>Blog title</h1>
191+ <p>This is some good content.</p>
192+</body>
193+```
194+
195+
196+Conversely, if we want to write a string with no tag at all, then we can prepend
197+those untagged lines with `;`.
198+
199+```
200+;body
201+ ;h1: Welcome!
202+ ; Hello, world!
203+ ; We’re on the web.
204+==
205+```
206+
207+Equals:
208+
209+```
210+<body>
211+ <h1>Welcome!</h1>
212+ Hello, world!
213+ We’re on the web.
214+</body>
215+```
216+
217+
218+#### Attributes
219+
220+Attributes are key-value pairs that go into an HTML node.
221+
222+Adding attributes is simple: just add the desired attribute between parentheses,
223+right after the tag name without a space. We separate different attributes of
224+the same node by using `,`.
225+
226+Attributes can be used in two forms: flat, which uses one line; and tall, which
227+uses multiple lines, when a single line would not be practical. Flat forms and
228+flat forms are two syntaxes of semantically equivalent expressions.
229+
230+
231+#### Generic
232+
233+The code below produces a “Submit” button on the page.
234+
235+Wide-form Sail:
236+
237+```
238+;input(type "submit", value "Submit");
239+```
240+
241+Tall-form Sail:
242+
243+```
244+;input
245+ =type "submit"
246+ =value "Submit";
247+==
248+```
249+
250+Equals:
251+
252+```
253+<input type="submit" value="Submit">`
254+```
255+
256+#### IDs
257+
258+```
259+;nav#header: Menu
260+```
261+
262+Equals:
263+
264+```
265+<nav id="header">Menu</nav>
266+```
267+
268+Add `#` after tag name to add an ID.
269+
270+#### Classes
271+
272+`;h1.text-blue: Title` equals `<h1 class="text-blue">Title</h1>`
273+
274+Add `.` after tag name to add a class. However, if you want a class name that
275+contains a space, you will need to use use the syntax of a generic attribute:
276+
277+`;div(class "logo inverse");` equals `<div class="logo inverse"></div>`
278+
279+
280+#### Image
281+
282+`;img@"example.png";`
283+
284+Equals
285+
286+`<img src="example.png"/>`
287+
288+Add `@` after the tag name to link your source.
289+
290+To add attributes to the image, like size specifications, add the
291+desired attribute after the `"` of the image name and before the final `;` of
292+the `img` tag.
293+
294+For example:
295+
296+`;img@"https://urbit.org/example.png"(width "100%");`
297+
298+#### Linking
299+
300+`;a/"urbit.org": A link to Urbit.org`
301+
302+Equals
303+
304+`<a href="urbit.org">A link to Urbit.org</a>`
305+
306+Add `/` after tag name to start an href.
307+
308+### Hoon in Sail
309+
310+Our first example is useful to understand how Sail syntax translates to HTML
311+syntax, but Sail finds its usefulness in the fact that it can be used seamlessly
312+with Hoon code.
313+
314+One place where Sail diverges from HTML is that it supports string
315+interpolation. In Sail, the contents of all tags are a string type called `tape`
316+unless otherwise designated. Tapes are delineated by the double quotes `""`.
317+That’s important, because tapes can be interpolated with Hoon expressions,
318+provided that those expressions produce something a tape as well. Interpolation
319+is done by wrapping the code to be inserted in `{}`. In your Dojo prompt, try
320+the command below (without the `>`):
321+
322+```
323+> "I am a l{(mul 3 11)}t Urbit user."
324+! exit
325+```
326+
327+Oh no! That command produced a nest-fail error, which indicates that there was
328+a problem related to Hoon type-system. We used the proper `{}` syntax for
329+interpolation, and we used the proper function-call syntax inside of it. So
330+what happened?
331+
332+Trying the `mul` function on its own will help answer this question. Try the
333+following command in your Dojo:
334+
335+```
336+> (mul 3 11)
337+33
338+```
339+
340+This should work, producing `33`, an atom. That’s our problem. The
341+interpolation expression expects a tape, but our first command tried to
342+interpolate with something that results in an atom. Try this now:
343+
344+```
345+> <(mul 3 11)>
346+"33"
347+```
348+
349+We get a similar result, but we know that it’s a tape because it’s wrapped in
350+`""`. Bingo! With this knowledge, let’s perform a successful interpolation:
351+
352+```
353+> "I am a l{<(mul 3 11)>}t Urbit user."
354+"I am a l33t Urbit user."
355+```
356+
357+Great!
358+
359+### The Subject
360+
361+The default subject of a Sail file is different from the subject that
362+expressions in the Dojo or a Hoon generator are evaluated against.
363+
364+To see this difference, first save the code below to a file at
365+`home/web/pages/sub.hoon` and view the rendering at
366+`http://localhost:8080/pages/sub`.
367+
368+```
369+;html
370+ ;head;
371+ ;body
372+ {<.>}
373+ ==
374+==
375+```
376+
377+Then enter the following command in the Dojo:
378+
379+```
380+> .
381+```
382+
383+You'll notice that the Sail subject is like a stripped-down version of the Dojo
384+subject. Its final line should match the Dojo subject.
385+
386+Now swap the code below into your Sail file.
387+
388+```
389+/= gas /$ fuel:html
390+;html
391+ ;head;
392+ ;body
393+ {<.>}
394+ ==
395+==
396+```
9
397
10−- #### [A Simple Udon Blog](#blog)
398+You'll find that the resulting Sail subject is much larger. If you look closely,
399+you'll see that there's some new similarities with the Dojo subject, such as
400+containing the name of your ship. There's also some new differences, since
401+`fuel:html` contains things that are specifically useful for performing
402+web-related operations.
403+
404+### A More Interesting Example
405+
406+Now let’s apply knowledge of string interpolation and the Sail subject in a Sail
407+source file. The following code produces more interesting things than the
408+example we saw before.
409+
410+```
411+/= gas /$ fuel:html
412+=/ show-list &
413+=+ wid=(met 3 p.bem.gas)
414+=/ what-kind
415+?: (lte wid 1) "galaxy"
416+?: =(2 wid) "star"
417+?: (lte wid 4) "planet"
418+?: (lte wid 8) "moon"
419+ "comet"
420+;html
421+ ;head
422+ ;meta(charset "utf-8");
423+ ;title: A more advanced page
424+ ==
425+ ;body
426+ ;h1: This is the Title
427+ ; This is a
428+ ;a/"http://urbit.org": link to Urbit.org.
429+ ;span: Check it out!
430+ ;+ ?: show-list
431+ ;ol
432+ ;li(style "color: green"): We're doing interesting stuff now.
433+ ;li: We're pretty-printing this sum with Hoon: {<(add 50 50)>}.
434+ ;li: The code above is shorthand for {(scow %ud (add 50 50))}.
435+ ;li: I am {(trip '~lodleb-ritrul')}.
436+ ;li: Actually, my name is {<p.bem.gas>}. I'm a {what-kind}.
437+ ==
438+ ;div: My name is {<p.bem.gas>}. I'm a {what-kind}.
439+ ==
440+==
441+```
442+
443+Save the above Sail code in to `home/web/pages/secondsail.hoon` and access the
444+resulting page by navigating to `http://localhost:8080/pages/secondsail` in
445+your browser.
446+
447+There are some interesting things here. Let’s go through this code piece by
448+piece.
449+
450+```
451+/= gas /$ fuel:html
452+```
453+
454+Later in this code we want produce the name of the ship is hosting it, something
455+that looks like ~lodleb-ritrul. In a generator, we could produce our ship name
456+by writing `our` -- try it in the Dojo. But remember that Sail is rendered
457+against its own subject, `our` is not part of the default subject. To augment
458+our subject with the information that we need, we use `/= gas /$ fuel:html`.
459+
460+The above expression uses two Ford runes, `/=` and `/$`, to add the relevant
461+information to the current subject. We can pull the ship’s name out of this
462+augmented subject later. It's important to note that these runes are not part of
463+Hoon. They are part of Ford, our build system.
464+
465+`/$` is used to get data from the environment, and `/=` adds that data to
466+subject in the face `gas`. The
467+[Ford user manual](https://urbit.org/docs/arvo/internals/ford/runes/) has
468+details on these and other Ford runes, but understanding these runes isn’t
469+necessary for the purposes of this tutorial.
470+
471+`fuel:html` gets extra data from your ship’s Eyre module, which handles all
472+things HTTP, and sticks it in the subject when Eyre renders a page. This
473+includes the name of the ship, which is what we look for in the next line, but
474+it includes much more.
475+
476+`p.bem.gas` is an expression that looks for `p` within `bem` within `gas`, the
477+face that we stored the above `fuel:html` expression in. That wing happens to
478+resolve to the name of the ship that is hosting the web-server. If we wanted to
479+access the current desk, we would use the wing expression `q.bem.gas`.
480+
481+You can take a look at what you can access by typing `fuel:html` in the Dojo,
482+and then explore it by modifying your wing expression in your Sail file
483+accordingly.
484+
485+```
486+=/ show-list &
487+```
488+
489+The above line of code stores a variable used later for a conditional. `&` means
490+`true`, meaning that any evaluation of `show-list` will be true until changed in
491+the source code.
492+
493+```
494+=+ wid=(met 3 p.bem.gas)
495+=/ what-kind
496+ ?: (lte wid 1) "galaxy"
497+ ?: =(2 wid) "star"
498+ ?: (lte wid 4) "planet"
499+ ?: (lte wid 8) "moon"
500+ "comet"
501+```
502+
503+This code chunk is a series of conditionals that checks the host ship’s name to
504+see what its value is.
505+
506+The first line, `=+ wid=(met 3 p.bem.gas)`, combines a new noun with the
507+subject and gives it the face `wid`. This noun is produced by the the
508+standard-library function [`met`](/docs/reference/library/2c), which measures the number of
509+[blocks](/docs/reference/library/1c/) of size `a` within `b`. Blocks are units that have a
510+bitwidth of `2^a`. So, in this case, it measures how many bytes (blocks of size
511+3 are bitwidths of 8; `2^3 = 8`) are fully contained in your ship's address.
512+
513+Galaxies contain zero to one 3-blocks; stars contain two 3-blocks; planets
514+contain three to four 3-blocks; moons contain five to eight 3-blocks; comets
515+contain nine to sixteen 3-blocks. Each test uses `lte`, the
516+less-than-or-equal-to function, to determine if `wid` is of a given size. The
517+result of this series of tests is added to the subject and given the face
518+`what-kind`.
519+
520+Ship names are simply another representation of atoms, and ship
521+categories are different ranges of possible atomic values. Because of this, we
522+perform less-than tests to see what kind of ship is running the web-server.
523+
524+```
525+;html
526+ ;head
527+ ;meta(charset "utf-8");
528+ ;title: A more advanced page
529+ ==
530+```
531+
532+Sail proper begins here. These four lines are four nodes. The `;html` node
533+indicates that the contained code should be rendered as HTML; this tag is closed
534+on the final line. The `;head` node contains metadata, and is closed three lines
535+later. The `;meta` node sets the character set to UTF-8, and the `;title` node
536+sets the title of the page that shows up in the browser tab.
537+
538+```
539+ ;body
540+ ;h1: This is the Title
541+ ; This is a
542+ ;a/"http://urbit.org": link to Urbit.org.
543+ ;span: Check it out!
544+```
11
545
12−- #### [A Static Site](#static)
546+The first line here opens, of course, the body node. The second line creates
547+header text.
13
548
549+The third, fourth, and fifth lines of code here construct a single line with an
550+inline link.
551+`; This is a` begins the rendered line with plain text.
552+
553+`;a/"http://urbit.org": link to Urbit.org.` continues that same rendered line,
554+and creates hyperlinked text out of `link to Urbit.org.`
555+
556+`;span: Check it out!` continues that same rendered line further. `;span:`
557+has the same use as `<span>` in HTML, and by following it with just a `:` and no
558+attributes, it continues the line without formatting. Following `;span:` with
559+**two** spaces causes there to be single space following the produced `<span>`
560+element, because one of those spaces is syntactically necessary.
561+
562+In the following lines, we beginning to use some Hoon expressions again.
563+
564+```
565+ ;+ ?: show-list
566+ ;ol
567+```
568+
569+In the top line in the chunk above, we use the `;+` Sail rune, which
570+resolves an expression to a single node. That expression, in this case, is
571+`?:`, which tests the truth value of `show-list`, which we assigned the value
572+`&` (meaning “true”) at the beginning of the program. It’s closed by the `==` on
573+the last line.
574+
575+Thus, this program resolves to the first child of `show-list`, the node `;ol`.
576+That node creates an ordered list, and the items contained within that node.
577+
578+```
579+ ;li(style "color: green"): We're doing more interesting stuff now.
580+```
581+
582+The line above is the only element of this list that does not use
583+Hoon proper. The line renders as green, as interpreted by the browser,
584+because of the Sail attribute.
585+
586+The next items in the list use `{}`. Recall that these braces, pronounced “lob”
587+and “rob” in Hoon-speak, allow for the interpolation of code within a string.
588+
589+```
590+ ;li: We're pretty-printing this sum with Hoon: {<(add 50 50)>}.
591+```
592+
593+The line above is interpolated with Hoon code that produces the sum of 50 plus
594+50, which is wrapped in `<>` to put the product in double quotes to make it a
595+tape, like the rest of the line.
596+
597+
598+```
599+ ;li: The code above is shorthand for {(scow %ud (add 50 50))}.
600+```
601+
602+The `{(scow %ud (add 50 50)}` on this line is just a different way
603+writing the `{<(add 50 50)>}` expression. `scow` is a Hoon function that turns a
604+noun into a `tape`, Hoon’s string type. `%ud` tells `scow` that its argument
605+should be displayed in the form of an unsigned decimal.
606+
607+
608+```
609+ ;li: I am {(trip '~lodleb-ritrul')}.
610+```
611+
612+`trip` is a function that takes a `cord` and produces a `tape`. A piece of
613+data of the cord type is one big atom formed from adjacent unicode bytes and
614+delineated by `''`. Remember that all text rendered in Sail is treated as a
615+tape. So, by converting `~lodleb-ritrul` to a tape, it can be included in the
616+tape that we are trying to insert it into without getting a type error.
617+
618+```
619+ ;li: Actually, my name is {<p.bem.gas>}. I'm a {what-kind}.
620+ ==
621+```
622+
623+The line above has interpolated code that uses a wing expression to access the
624+name of the host ship, and then accesses the face `what-kind` contains a string
625+describing what type of ship it is. We declared `gas` on the very first line so
626+that we could add that sort of information to the subject that our Sail is
627+rendered against. The wing expression `p.bem.gas` looks for `p` within `bem`
628+within `gas`, which happens to be where the name of the ship is located.
629+
630+Note that `{what-kind}` does not have a `<>` wrapper. Why do you think this is?
631+
632+```
633+ ;div; My name is {<p.bem.gas>}. I'm a {ship}.
634+ ==
635+==
636+```
637+
638+The `;div;` node above is only rendered, as an alternative to the above list,
639+if `show-list` is evaluated as true. This means it won’t be shown with your
640+default code. To show this line, change the `&` on line 2 to `|` (“false”).
641+
642+### Sail Runes
643+
644+In the previous example, we used a few special runes that aren’t used in typical
645+Hoon code. But there are others that are worth learning about at this point.
646+
647+`;+` is an expression that resolves to a single node. We saw this on line 20
648+in our Sail example above: `;+ ?: show-list` resolves to the node `;ol` and
649+all of that node’s children.
650+
651+`;*` is an expression that resolves to a list of nodes. If we want to render
652+multiple nodes side-by-side, and not just the children of a single node, this
653+is the expression that we use.
654+
655+`;=` turns a tuple of nodes into a list of nodes.
656+
657+
658+To see how these runes work, let’s take a chunk of our previous code starting at
659+line 20 and modify it a bit:
660+
661+```
662+ ;* ?: show-list
663+ ;=
664+ ;li: I am {(trip '~lodleb-ritrul')}.
665+ ;li: Actually, my name is {<p.bem.gas>}.
666+ ==
667+ ;=
668+ ;div: My name is {<p.bem.gas>}. I'm a {what-kind}.
669+ ;div: No list here!
670+ ==
671+ ==
672+```
673+
674+We changed the conditional branches so that each contains two Sail nodes,
675+side-by-side -- notice that the `;ol` is absent from the first branch.
676+
677+We begin with the `;*` rune, which resolves to a list of nodes, instead of the
678+`;+` rune, which only resolves to a single node.
679+
680+But that’s not enough on its own. `;*` needs to resolve to a list, and a few
681+Sail nodes aren’t lists until they are explicitly made into lists. Until we wrap
682+those nodes in `;=`, the nodes treated as mere tuples. All branches must be
683+valid lists for the `;* ?: show-list` expression to resolve.
684+
685+### Further Reading
686+
687+You should now have foundational knowledge for making web pages with Sail. There
688+is, of course, more to learn.
689+
690+The [Ford manual](https://urbit.org/docs/arvo/internals/ford/runes/)
691+can show you how to access various ship resources for user in your pages. To
692+learn more about how the renderer works, take a look at the
693+`/home/ren/urb.hoon` file inside your urbit.
694+
14−## A Guide
695+## <a name="udon"></a>Udon: A Guide
15
696
16Udon is a way to write content for the web. It's a minimalist
697Udon is a way to write content for the web. It's a minimalist
17markup language for creating and rendering text documents, with a
698markup language for creating and rendering text documents, with a
@@ -34,36 +715,7 @@ Markdown: some syntax errors will prevent the file from being parsed at all.
34We provide a few simple examples [here](#examples) of how to publish
715We provide a few simple examples [here](#examples) of how to publish
35Udon files using our web interface.
716Udon files using our web interface.
36
717
37−### Getting Started
38−
39−Before starting, make sure that your urbit is
40−[mounted to Unix](https://urbit.org/docs/using/setup/)
41−
42−To host Udon and other kinds of files, your ship also has a
43−web-server, called [Eyre](https://urbit.org/docs/using/web/), that can be found
44−at `http://localhost:8080/` if it’s your first ship that’s running on the
45−machine, `http://localhost:8081/` if it’s the second ship on that same machine,
46−and so on. If you can't find your ship on one of these for some reason, try the
47−next one. When a ship starts, it will print a message like
48−`http: live (insecure, public) on 8081` to let you know what port it's using.
49−
50−That server has access to source files located in `/<your-urbit>/home/web` and
51−any sub-folders thereof (except for `/home/web/pages`, which has special
52−rendering rules.) Your ship's `%home` desk is served by default. You can
53−[change](https://urbit.org/docs/using/web/) which desk you're serving, however.
54−
55−Everything in the `/<your-urbit>/home/web/` directory, with the exception of
56−`/home/web/pages`, knows how to interpret and files of `.udon` type. So, to
57−experiment with UM, create a `.udon` file in that path, and then try to access it
58−at `http://localhost:8080/<yourfile>` in your browser -- no `.udon` required in
59−the URL. It's a good idea to copy-paste the following examples into your file to
60−see how the code works.
61−
62−Make sure that you have proper syntax throughout, and check often that it
63−renders properly as you add more code. If you have parser-breaking syntax, then
64−the default renderer won't tell you much.
65−
66−## Syntax
718+## Udon Syntax
67
719
68### Front Matter
720### Front Matter
69
721
@@ -129,7 +781,7 @@ through `<h6>`. The header for this section is `### Headers`.
129
781
130##### Header (h5)
782##### Header (h5)
131```
783```
132−###### Produces:
784+**Produces:**
133
785
134#### Header (h4)
786#### Header (h4)
135
787
@@ -150,7 +802,7 @@ element.
150To get their *attention*, you need that _je ne sais quoi_.
802To get their *attention*, you need that _je ne sais quoi_.
151```
803```
152
804
153−###### Produces:
805+**Produces:**
154
806
155To get their **attention**, you need that _je ne sais quoi_.
807To get their **attention**, you need that _je ne sais quoi_.
156
808
@@ -170,7 +822,7 @@ This second line is separated by two newlines, so it's a separate paragraph.
170This line looks like a distinct paragraph, but...
822This line looks like a distinct paragraph, but...
171It's only separated by a single newline, so it's included in the same paragraph.
823It's only separated by a single newline, so it's included in the same paragraph.
172```
824```
173−###### Produces:
825+**Produces:**
174
826
175
827
176Here's the first line.
828Here's the first line.
@@ -192,7 +844,7 @@ I wonder how long each line
192will be if I put backslashes\
844will be if I put backslashes\
193at the ends of the lines.
845at the ends of the lines.
194```
846```
195−###### Produces:
847+**Produces:**
196
848
197I wonder how long each line
849I wonder how long each line
198will be if I put backslashes\
850will be if I put backslashes\
@@ -210,7 +862,7 @@ Here is some *bold* text.
210Here is some \*not bold* text.
862Here is some \*not bold* text.
211```
863```
212
864
213−###### Produces:
865+**Produces:**
214
866
215Here is some **bold** text.
867Here is some **bold** text.
216Here is some \*not bold* text.
868Here is some \*not bold* text.
@@ -318,7 +970,7 @@ destination.
318[I'm an inline-style link](https://www.urbit.org/docs/reference/shell)
970[I'm an inline-style link](https://www.urbit.org/docs/reference/shell)
319```
971```
320
972
321−###### Produces:
973+**Produces:**
322
974
323[I'm an inline-style link](https://www.urbit.org/docs/reference/shell)
975[I'm an inline-style link](https://www.urbit.org/docs/reference/shell)
324
976
@@ -332,7 +984,7 @@ the all of the URL that the destination has in common with the origin page.
332[I'm a reference-style link](../shell)
984[I'm a reference-style link](../shell)
333```
985```
334
986
335−###### Produces:
987+**Produces:**
336
988
337[I'm a reference-style link](../shell)
989[I'm a reference-style link](../shell)
338
990
@@ -349,7 +1001,7 @@ so we need to use some [Sail](#sail). If there are two or more anchors with
349the same `id` on the page, you will arrive at the earliest instance of the the
1001the same `id` on the page, you will arrive at the earliest instance of the the
350anchor.
1002anchor.
351
1003
352−###### Example:
1004+**Example:**
353
1005
354```
1006```
355Check out this [section](#the-destination) that we want to jump to.
1007Check out this [section](#the-destination) that we want to jump to.
@@ -361,7 +1013,7 @@ It was the best of times, it was the worst of times...
361## Here we are!
1013## Here we are!
362```
1014```
363
1015
364−###### Produces
1016+**Produces:**
365
1017
366Check out this [section](#the-destination) that we want to jump to.
1018Check out this [section](#the-destination) that we want to jump to.
367
1019
@@ -381,7 +1033,7 @@ opening and closing quotes -- that is, `“` and `”`.
381"Yes," he said. "That is the way with him."
1033"Yes," he said. "That is the way with him."
382```
1034```
383
1035
384−###### Produces:
1036+**Produces:**
385
1037
386"Yes," he said. "That is the way with him."
1038"Yes," he said. "That is the way with him."
387
1039
@@ -399,7 +1051,7 @@ bug.
399\
1051\
400```
1052```
401
1053
402−##### Inline Code Literal
1054+#### Inline Code Literal
403
1055
404Enclosing some text in
1056Enclosing some text in
405```
1057```
@@ -417,7 +1069,7 @@ throughout this guide to `format text` to distinguish code from prose.
417```
1069```
418`*[a 2 b c] -> *[*[a b] *[a c]]` is like lisp's `apply`.
1070`*[a 2 b c] -> *[*[a b] *[a c]]` is like lisp's `apply`.
419```
1071```
420−###### Produces:
1072+**Produces:**
421
1073
422`*[a 2 b c] -> *[*[a b] *[a c]]` is like lisp's `apply`.
1074`*[a 2 b c] -> *[*[a b] *[a c]]` is like lisp's `apply`.
423
1075
@@ -431,13 +1083,13 @@ Hoon.
431The ++add arm is used to sum two numbers.
1083The ++add arm is used to sum two numbers.
432```
1084```
433
1085
434−###### Produces:
1086+**Produces:**
435
1087
436The ++add arm is used to sum two numbers.
1088The ++add arm is used to sum two numbers.
437
1089
438#### Block Code Literal
1090#### Block Code Literal
439
1091
440−By enclosing a block of text in ``` on their own lines
1092+By enclosing a block of text in a tick on their own lines
441before and after the contained text, the text will be treated as a code block.
1093before and after the contained text, the text will be treated as a code block.
442
1094
443Most of our examples so far have used.
1095Most of our examples so far have used.
@@ -456,7 +1108,7 @@ Most of our examples so far have used.
456 ```
1108 ```
457```
1109```
458
1110
459−###### Produces:
1111+**Produces:**
460
1112
461```
1113```
462(def Y (fn [f]
1114(def Y (fn [f]
@@ -494,7 +1146,7 @@ Three or more hyphens, such as `---`, on their own line produce an `<hr>`
494element, the 'horizontal rule'. This is rendered as a horizontal line the
1146element, the 'horizontal rule'. This is rendered as a horizontal line the
495width of its containing paragraph.
1147width of its containing paragraph.
496
1148
497−###### Example:
1149+**Example:**
498
1150
499```
1151```
500Above the line
1152Above the line
@@ -504,7 +1156,7 @@ Below the line
504And below this line, too
1156And below this line, too
505```
1157```
506
1158
507−###### Produces:
1159+**Produces:**
508
1160
509
1161
510Above the line
1162Above the line
@@ -537,7 +1189,7 @@ Quote break.
537 He is pale and thin, he wears a thin and ragged linen shirt.
1189 He is pale and thin, he wears a thin and ragged linen shirt.
538```
1190```
539
1191
540−###### Produces:
1192+**Produces:**
541
1193
542> As Gregor Samsa awoke one morning from uneasy dreams
1194> As Gregor Samsa awoke one morning from uneasy dreams
543 he found himself transformed in his bed into a **monstrous** vermin.
1195 he found himself transformed in his bed into a **monstrous** vermin.
@@ -556,7 +1208,7 @@ normally in Udon, newlines are treated as spaces and do not create a
556new line of text. If you want to embed text where newlines are retained, then
1208new line of text. If you want to embed text where newlines are retained, then
557indent the text in question with **eight spaces**.
1209indent the text in question with **eight spaces**.
558
1210
559−###### Example:
1211+**Example:**
560
1212
561```
1213```
562 A shape with lion body and the head of a man,
1214 A shape with lion body and the head of a man,
@@ -564,7 +1216,7 @@ indent the text in question with **eight spaces**.
564 Is moving its slow thighs, while all about it
1216 Is moving its slow thighs, while all about it
565 Reel shadows of the indignant desert birds.
1217 Reel shadows of the indignant desert birds.
566```
1218```
567−###### Produces:
1219+**Produces:**
568
1220
569 A shape with lion body and the head of a man,
1221 A shape with lion body and the head of a man,
570 A gaze blank and pitiless as the sun,
1222 A gaze blank and pitiless as the sun,
@@ -607,7 +1259,7 @@ Produces:
607</p>
1259</p>
608
1260
609
1261
610−## A Simple Udon Blog
1262+## <a name="blog"></a>A Simple Udon Blog
611
1263
612Publishing using Udon is really easy. It uses the file extension `.udon`. Here we'll create a very simple blog and publish our first posts.
1264Publishing using Udon is really easy. It uses the file extension `.udon`. Here we'll create a very simple blog and publish our first posts.
613
1265
@@ -748,7 +1400,7 @@ Use `;join` to keep up with comments as they get posted:
748
1400
749That's it! Easy.
1401That's it! Easy.
750
1402
751−## A Static Site
1403+## <a name="static"></a>A Static Site
752
1404
753Hosting a static tree of content is easy. Let's put together a really
1405Hosting a static tree of content is easy. Let's put together a really
754simple site for an imaginary Urbit meetup group.
1406simple site for an imaginary Urbit meetup group.
using/sail.mddeleted−682
@@ -1,682 +0,0 @@
1−+++
2−title = "Sail"
3−weight = 7
4−template = "doc.html"
5−+++
6−Sail is Hoon markup that’s used to render a web page with XML. But what makes
7−it special is that you can run arbitrary Hoon code within such a web page
8−without using a separate markup language. In this tutorial, we will
9−be dealing with Sail as it renders to HTML, a subset of XML.
10−
11−### Getting Started
12−
13−Before starting, make sure that your urbit is
14−[mounted to Unix](https://urbit.org/docs/using/setup/)
15−
16−To host that output, your ship also has a web-server, called
17−[Eyre](https://urbit.org/docs/using/web/), that can be found at
18−`http://localhost:8080/` if it’s your first ship that’s running on the a
19−machine, `http://localhost:8081/` if it’s the second ship on that same machine,
20−and so on. In the startup messages, a ship will tell you which HTTP port it's
21−using.
22−
23−The `/web` directory of the `%home` desk is served by default. You can change
24−which desk you're serving by using the command `|serve` in the Dojo. If you
25−have already created and mounted a desk named `%sandbox`, for example, you can
26−switch to serving it with this command:
27−
28−```
29−|serve %sandbox
30−```
31−
32−The first time you serve a desk, `/web` will be included as default. After that,
33−you will need to explicitly append `/web` to the desk you're switching to --
34−otherwise, you'll need to write `http://localhost:8080/web` every time you
35−navigate to your web-server. Newly served desks not automatically having `/web`
36−as their root directory is a bug.
37−
38−To switch back to your `%home` desk and set `/web` as your root directory, run:
39−
40−```
41−|serve %/web
42−```
43−
44−We'll be serving the `%home` desk for the examples in this tutorial.
45−
46−#### Rendering
47−
48−That server has access to source files located in `/<your-urbit>/home/web` and
49−any sub-folders thereof. For the purposes of this tutorial, we will only be
50−using files that are located in the `/<your-urbit>/home/web/pages` path.
51−
52−There is an important distinction between these two paths. According to
53−`/ren/urb.hoon`, any file inside of `/web` or any of its sub-directories
54−is put through a tree of renderers specified at `/ren/urb/tree.hoon`
55−-- _except_ for files inside of `/web/pages`. All of the files in `/web` and
56−its non-`/pages` children directories have various operations on files, such as
57−wrapping your Sail the `html`, `head`, and `body` nodes. This rendering tool,
58−called simply **Tree**, also adds certain formatting polish, such as a sidebar
59−that lists sibling files in the same directory.
60−
61−The `/web/pages` sub-directory is a unique case with its own rendering rules.
62−The Tree is not used when rendering files in this path. The existence of no tag
63−is inferred, and no special formatting is applied. Such simplicity is ideal for
64−introducing the basics of Sail. Any source file located in `/web/pages` must
65−produce a complete HTML node with "head" and "body" nodes as children.
66−
67−Understanding the details of the rendering pipeline is not necessary to complete
68−this tutorial. But, if you are curious, you might find it illuminating to
69−explore the contents of the `/ren` directory.
70−
71−So, if a Sail source file named `sailtest.hoon` is saved in your `/web/pages`
72−folder on your only running urbit process, you can view that source rendered
73−into a web-page at `localhost:8080/pages/sailtest/`.
74−
75−### The Basics
76−
77−It’s easy to see how Sail can directly translate to HTML:
78−
79−#### Sail code
80−
81−```
82−;html
83− ;head
84− ;title: My first webpage
85− ==
86− ;body
87− ;h1: Welcome!
88− ; Hello, world!
89− ; We're on the web.
90− ;div;
91− ;script@"http://unsafely.tracking.you/cookiemonster.js";
92− ==
93−==
94−```
95−
96−#### HTML code
97−
98−```
99−<html>
100− <head>
101− <title>My first webpage</title>
102− </head>
103− <body>
104− <h1>Welcome!</h1>
105− Hello, world!
106− We’re on the web.
107− <div></div>
108− <script src="http://unsafely.tracking.you/cookiemonster.js"></script>
109− </body>
110−</html>
111−```
112−
113−Save the above Sail code in `/home/web/pages/firstsail.hoon`, and the above
114−HTML code in `/home/web/pages/firsth.html`. Access the resulting pages by
115−navigating to `http://localhost:8080/pages/firstsail` and
116−`http://localhost:8080/pages/firsth.html`, respectively, in your browser. The
117−resulting pages should be identical!
118−
119−It shouldn't be hard to see the similarities here. So let's go into more
120−detail about what the differences are.
121−
122−### Tags and Closing
123−
124−In Sail, tag heads are written with the tag name prepended by `;`. Unlike in
125−HTML, there are different ways on closing tags, depending on the needs of the
126−tag. One of the nice things about Hoon is that you don’t have to be constantly
127−closing expressions; Sail inherits this convenience.
128−
129−#### Empty
130−
131−Empty tags are closed with a `;` following the tag. Example:
132−
133−```
134−;div;
135−```
136−
137−Equals:
138−
139−```
140−<div></div>
141−```
142−
143−#### Filled
144−
145−Filled tags are closed via line-break. To fill text inside, add `:` after the
146−tag name, then insert your plain text following a space. Example:
147−
148−```
149−;h1: The title
150−```
151−
152−Equals:
153−
154−```
155−<h1>The title</h1>
156−```
157−
158−#### Nested
159−
160−To nest tags, simply create a new line. Nested tags need to be closed
161−with `==`, because they expect a list of sub-tags. If we nest a line of plain
162−text with no tag, a `<p>` is prepended.
163−
164−Sail, like Hoon, is white-space sensitive. Unlike in Hoon, however, two spaces
165−(called a "gap") is not necessarily equivalent to a line-break in Sail.
166−
167−```
168−;body
169− ;h1: Blog title
170− This is some good content.
171−==
172−```
173−
174−Equals:
175−
176−```
177−<body>
178− <h1>Blog title</h1>
179− <p>This is some good content.</p>
180−</body>
181−```
182−
183−
184−Conversely, if we want to write a string with no tag at all, then we can prepend
185−those untagged lines with `;`.
186−
187−```
188−;body
189− ;h1: Welcome!
190− ; Hello, world!
191− ; We’re on the web.
192−==
193−```
194−
195−Equals:
196−
197−```
198−<body>
199− <h1>Welcome!</h1>
200− Hello, world!
201− We’re on the web.
202−</body>
203−```
204−
205−
206−#### Attributes
207−
208−Attributes are key-value pairs that go into an HTML node.
209−
210−Adding attributes is simple: just add the desired attribute between parentheses,
211−right after the tag name without a space. We separate different attributes of
212−the same node by using `,`.
213−
214−Attributes can be used in two forms: flat, which uses one line; and tall, which
215−uses multiple lines, when a single line would not be practical. Flat forms and
216−flat forms are two syntaxes of semantically equivalent expressions.
217−
218−
219−#### Generic
220−
221−The code below produces a “Submit” button on the page.
222−
223−Wide-form Sail:
224−
225−```
226−;input(type "submit", value "Submit");
227−```
228−
229−Tall-form Sail:
230−
231−```
232−;input
233− =type "submit"
234− =value "Submit";
235−==
236−```
237−
238−Equals:
239−
240−```
241−<input type="submit" value="Submit">`
242−```
243−
244−#### IDs
245−
246−```
247−;nav#header: Menu
248−```
249−
250−Equals:
251−
252−```
253−<nav id="header">Menu</nav>
254−```
255−
256−Add `#` after tag name to add an ID.
257−
258−#### Classes
259−
260−`;h1.text-blue: Title` equals `<h1 class="text-blue">Title</h1>`
261−
262−Add `.` after tag name to add a class. However, if you want a class name that
263−contains a space, you will need to use use the syntax of a generic attribute:
264−
265−`;div(class "logo inverse");` equals `<div class="logo inverse"></div>`
266−
267−
268−#### Image
269−
270−`;img@"example.png";`
271−
272−Equals
273−
274−`<img src="example.png"/>`
275−
276−Add `@` after the tag name to link your source.
277−
278−To add attributes to the image, like size specifications, add the
279−desired attribute after the `"` of the image name and before the final `;` of
280−the `img` tag.
281−
282−For example:
283−
284−`;img@"https://urbit.org/example.png"(width "100%");`
285−
286−#### Linking
287−
288−`;a/"urbit.org": A link to Urbit.org`
289−
290−Equals
291−
292−`<a href="urbit.org">A link to Urbit.org</a>`
293−
294−Add `/` after tag name to start an href.
295−
296−### Hoon in Sail
297−
298−Our first example is useful to understand how Sail syntax translates to HTML
299−syntax, but Sail finds its usefulness in the fact that it can be used seamlessly
300−with Hoon code.
301−
302−One place where Sail diverges from HTML is that it supports string
303−interpolation. In Sail, the contents of all tags are a string type called `tape`
304−unless otherwise designated. Tapes are delineated by the double quotes `""`.
305−That’s important, because tapes can be interpolated with Hoon expressions,
306−provided that those expressions produce something a tape as well. Interpolation
307−is done by wrapping the code to be inserted in `{}`. In your Dojo prompt, try
308−the command below (without the `>`):
309−
310−```
311−> "I am a l{(mul 3 11)}t Urbit user."
312−! exit
313−```
314−
315−Oh no! That command produced a nest-fail error, which indicates that there was
316−a problem related to Hoon type-system. We used the proper `{}` syntax for
317−interpolation, and we used the proper function-call syntax inside of it. So
318−what happened?
319−
320−Trying the `mul` function on its own will help answer this question. Try the
321−following command in your Dojo:
322−
323−```
324−> (mul 3 11)
325−33
326−```
327−
328−This should work, producing `33`, an atom. That’s our problem. The
329−interpolation expression expects a tape, but our first command tried to
330−interpolate with something that results in an atom. Try this now:
331−
332−```
333−> <(mul 3 11)>
334−"33"
335−```
336−
337−We get a similar result, but we know that it’s a tape because it’s wrapped in
338−`""`. Bingo! With this knowledge, let’s perform a successful interpolation:
339−
340−```
341−> "I am a l{<(mul 3 11)>}t Urbit user."
342−"I am a l33t Urbit user."
343−```
344−
345−Great!
346−
347−### The Subject
348−
349−The default subject of a Sail file is different from the subject that
350−expressions in the Dojo or a Hoon generator are evaluated against.
351−
352−To see this difference, first save the code below to a file at
353−`home/web/pages/sub.hoon` and view the rendering at
354−`http://localhost:8080/pages/sub`.
355−
356−```
357−;html
358− ;head;
359− ;body
360− {<.>}
361− ==
362−==
363−```
364−
365−Then enter the following command in the Dojo:
366−
367−```
368−> .
369−```
370−
371−You'll notice that the Sail subject is like a stripped-down version of the Dojo
372−subject. Its final line should match the Dojo subject.
373−
374−Now swap the code below into your Sail file.
375−
376−```
377−/= gas /$ fuel:html
378−;html
379− ;head;
380− ;body
381− {<.>}
382− ==
383−==
384−```
385−
386−You'll find that the resulting Sail subject is much larger. If you look closely,
387−you'll see that there's some new similarities with the Dojo subject, such as
388−containing the name of your ship. There's also some new differences, since
389−`fuel:html` contains things that are specifically useful for performing
390−web-related operations.
391−
392−### A More Interesting Example
393−
394−Now let’s apply knowledge of string interpolation and the Sail subject in a Sail
395−source file. The following code produces more interesting things than the
396−example we saw before.
397−
398−```
399−/= gas /$ fuel:html
400−=/ show-list &
401−=+ wid=(met 3 p.bem.gas)
402−=/ what-kind
403−?: (lte wid 1) "galaxy"
404−?: =(2 wid) "star"
405−?: (lte wid 4) "planet"
406−?: (lte wid 8) "moon"
407− "comet"
408−;html
409− ;head
410− ;meta(charset "utf-8");
411− ;title: A more advanced page
412− ==
413− ;body
414− ;h1: This is the Title
415− ; This is a
416− ;a/"http://urbit.org": link to Urbit.org.
417− ;span: Check it out!
418− ;+ ?: show-list
419− ;ol
420− ;li(style "color: green"): We're doing interesting stuff now.
421− ;li: We're pretty-printing this sum with Hoon: {<(add 50 50)>}.
422− ;li: The code above is shorthand for {(scow %ud (add 50 50))}.
423− ;li: I am {(trip '~lodleb-ritrul')}.
424− ;li: Actually, my name is {<p.bem.gas>}. I'm a {what-kind}.
425− ==
426− ;div: My name is {<p.bem.gas>}. I'm a {what-kind}.
427− ==
428−==
429−```
430−
431−Save the above Sail code in to `home/web/pages/secondsail.hoon` and access the
432−resulting page by navigating to `http://localhost:8080/pages/secondsail` in
433−your browser.
434−
435−There are some interesting things here. Let’s go through this code piece by
436−piece.
437−
438−```
439−/= gas /$ fuel:html
440−```
441−
442−Later in this code we want produce the name of the ship is hosting it, something
443−that looks like ~lodleb-ritrul. In a generator, we could produce our ship name
444−by writing `our` -- try it in the Dojo. But remember that Sail is rendered
445−against its own subject, `our` is not part of the default subject. To augment
446−our subject with the information that we need, we use `/= gas /$ fuel:html`.
447−
448−The above expression uses two Ford runes, `/=` and `/$`, to add the relevant
449−information to the current subject. We can pull the ship’s name out of this
450−augmented subject later. It's important to note that these runes are not part of
451−Hoon. They are part of Ford, our build system.
452−
453−`/$` is used to get data from the environment, and `/=` adds that data to
454−subject in the face `gas`. The
455−[Ford user manual](https://urbit.org/docs/arvo/internals/ford/runes/) has
456−details on these and other Ford runes, but understanding these runes isn’t
457−necessary for the purposes of this tutorial.
458−
459−`fuel:html` gets extra data from your ship’s Eyre module, which handles all
460−things HTTP, and sticks it in the subject when Eyre renders a page. This
461−includes the name of the ship, which is what we look for in the next line, but
462−it includes much more.
463−
464−`p.bem.gas` is an expression that looks for `p` within `bem` within `gas`, the
465−face that we stored the above `fuel:html` expression in. That wing happens to
466−resolve to the name of the ship that is hosting the web-server. If we wanted to
467−access the current desk, we would use the wing expression `q.bem.gas`.
468−
469−You can take a look at what you can access by typing `fuel:html` in the Dojo,
470−and then explore it by modifying your wing expression in your Sail file
471−accordingly.
472−
473−```
474−=/ show-list &
475−```
476−
477−The above line of code stores a variable used later for a conditional. `&` means
478−`true`, meaning that any evaluation of `show-list` will be true until changed in
479−the source code.
480−
481−```
482−=+ wid=(met 3 p.bem.gas)
483−=/ what-kind
484− ?: (lte wid 1) "galaxy"
485− ?: =(2 wid) "star"
486− ?: (lte wid 4) "planet"
487− ?: (lte wid 8) "moon"
488− "comet"
489−```
490−
491−This code chunk is a series of conditionals that checks the host ship’s name to
492−see what its value is.
493−
494−The first line, `=+ wid=(met 3 p.bem.gas)`, combines a new noun with the
495−subject and gives it the face `wid`. This noun is produced by the the
496−standard-library function [`met`](/docs/reference/library/2c), which measures the number of
497−[blocks](/docs/reference/library/1c/) of size `a` within `b`. Blocks are units that have a
498−bitwidth of `2^a`. So, in this case, it measures how many bytes (blocks of size
499−3 are bitwidths of 8; `2^3 = 8`) are fully contained in your ship's address.
500−
501−Galaxies contain zero to one 3-blocks; stars contain two 3-blocks; planets
502−contain three to four 3-blocks; moons contain five to eight 3-blocks; comets
503−contain nine to sixteen 3-blocks. Each test uses `lte`, the
504−less-than-or-equal-to function, to determine if `wid` is of a given size. The
505−result of this series of tests is added to the subject and given the face
506−`what-kind`.
507−
508−Ship names are simply another representation of atoms, and ship
509−categories are different ranges of possible atomic values. Because of this, we
510−perform less-than tests to see what kind of ship is running the web-server.
511−
512−```
513−;html
514− ;head
515− ;meta(charset "utf-8");
516− ;title: A more advanced page
517− ==
518−```
519−
520−Sail proper begins here. These four lines are four nodes. The `;html` node
521−indicates that the contained code should be rendered as HTML; this tag is closed
522−on the final line. The `;head` node contains metadata, and is closed three lines
523−later. The `;meta` node sets the character set to UTF-8, and the `;title` node
524−sets the title of the page that shows up in the browser tab.
525−
526−```
527− ;body
528− ;h1: This is the Title
529− ; This is a
530− ;a/"http://urbit.org": link to Urbit.org.
531− ;span: Check it out!
532−```
533−
534−The first line here opens, of course, the body node. The second line creates
535−header text.
536−
537−The third, fourth, and fifth lines of code here construct a single line with an
538−inline link.
539−`; This is a` begins the rendered line with plain text.
540−
541−`;a/"http://urbit.org": link to Urbit.org.` continues that same rendered line,
542−and creates hyperlinked text out of `link to Urbit.org.`
543−
544−`;span: Check it out!` continues that same rendered line further. `;span:`
545−has the same use as `<span>` in HTML, and by following it with just a `:` and no
546−attributes, it continues the line without formatting. Following `;span:` with
547−**two** spaces causes there to be single space following the produced `<span>`
548−element, because one of those spaces is syntactically necessary.
549−
550−In the following lines, we beginning to use some Hoon expressions again.
551−
552−```
553− ;+ ?: show-list
554− ;ol
555−```
556−
557−In the top line in the chunk above, we use the `;+` Sail rune, which
558−resolves an expression to a single node. That expression, in this case, is
559−`?:`, which tests the truth value of `show-list`, which we assigned the value
560−`&` (meaning “true”) at the beginning of the program. It’s closed by the `==` on
561−the last line.
562−
563−Thus, this program resolves to the first child of `show-list`, the node `;ol`.
564−That node creates an ordered list, and the items contained within that node.
565−
566−```
567− ;li(style "color: green"): We're doing more interesting stuff now.
568−```
569−
570−The line above is the only element of this list that does not use
571−Hoon proper. The line renders as green, as interpreted by the browser,
572−because of the Sail attribute.
573−
574−The next items in the list use `{}`. Recall that these braces, pronounced “lob”
575−and “rob” in Hoon-speak, allow for the interpolation of code within a string.
576−
577−```
578− ;li: We're pretty-printing this sum with Hoon: {<(add 50 50)>}.
579−```
580−
581−The line above is interpolated with Hoon code that produces the sum of 50 plus
582−50, which is wrapped in `<>` to put the product in double quotes to make it a
583−tape, like the rest of the line.
584−
585−
586−```
587− ;li: The code above is shorthand for {(scow %ud (add 50 50))}.
588−```
589−
590−The `{(scow %ud (add 50 50)}` on this line is just a different way
591−writing the `{<(add 50 50)>}` expression. `scow` is a Hoon function that turns a
592−noun into a `tape`, Hoon’s string type. `%ud` tells `scow` that its argument
593−should be displayed in the form of an unsigned decimal.
594−
595−
596−```
597− ;li: I am {(trip '~lodleb-ritrul')}.
598−```
599−
600−`trip` is a function that takes a `cord` and produces a `tape`. A piece of
601−data of the cord type is one big atom formed from adjacent unicode bytes and
602−delineated by `''`. Remember that all text rendered in Sail is treated as a
603−tape. So, by converting `~lodleb-ritrul` to a tape, it can be included in the
604−tape that we are trying to insert it into without getting a type error.
605−
606−```
607− ;li: Actually, my name is {<p.bem.gas>}. I'm a {what-kind}.
608− ==
609−```
610−
611−The line above has interpolated code that uses a wing expression to access the
612−name of the host ship, and then accesses the face `what-kind` contains a string
613−describing what type of ship it is. We declared `gas` on the very first line so
614−that we could add that sort of information to the subject that our Sail is
615−rendered against. The wing expression `p.bem.gas` looks for `p` within `bem`
616−within `gas`, which happens to be where the name of the ship is located.
617−
618−Note that `{what-kind}` does not have a `<>` wrapper. Why do you think this is?
619−
620−```
621− ;div; My name is {<p.bem.gas>}. I'm a {ship}.
622− ==
623−==
624−```
625−
626−The `;div;` node above is only rendered, as an alternative to the above list,
627−if `show-list` is evaluated as true. This means it won’t be shown with your
628−default code. To show this line, change the `&` on line 2 to `|` (“false”).
629−
630−### Sail Runes
631−
632−In the previous example, we used a few special runes that aren’t used in typical
633−Hoon code. But there are others that are worth learning about at this point.
634−
635−`;+` is an expression that resolves to a single node. We saw this on line 20
636−in our Sail example above: `;+ ?: show-list` resolves to the node `;ol` and
637−all of that node’s children.
638−
639−`;*` is an expression that resolves to a list of nodes. If we want to render
640−multiple nodes side-by-side, and not just the children of a single node, this
641−is the expression that we use.
642−
643−`;=` turns a tuple of nodes into a list of nodes.
644−
645−
646−To see how these runes work, let’s take a chunk of our previous code starting at
647−line 20 and modify it a bit:
648−
649−```
650− ;* ?: show-list
651− ;=
652− ;li: I am {(trip '~lodleb-ritrul')}.
653− ;li: Actually, my name is {<p.bem.gas>}.
654− ==
655− ;=
656− ;div: My name is {<p.bem.gas>}. I'm a {what-kind}.
657− ;div: No list here!
658− ==
659− ==
660−```
661−
662−We changed the conditional branches so that each contains two Sail nodes,
663−side-by-side -- notice that the `;ol` is absent from the first branch.
664−
665−We begin with the `;*` rune, which resolves to a list of nodes, instead of the
666−`;+` rune, which only resolves to a single node.
667−
668−But that’s not enough on its own. `;*` needs to resolve to a list, and a few
669−Sail nodes aren’t lists until they are explicitly made into lists. Until we wrap
670−those nodes in `;=`, the nodes treated as mere tuples. All branches must be
671−valid lists for the `;* ?: show-list` expression to resolve.
672−
673−
674−### Conclusion
675−
676−You should now have foundational knowledge for making web pages with Sail. There
677−is, of course, more to learn. If you’re curious, there’s more advanced
678−resources out there.
679−The [Ford manual](https://urbit.org/docs/arvo/internals/ford/runes/)
680−can show you how to access various ship resources for user in your pages. To
681−learn more about how the renderer works, take a look at the
682−`/home/ren/urb.hoon` file inside your urbit.