@@ -4,6 +4,8 @@ sort: 6
44title: Web Apps
55---
66
7+# Backend
8+
79We've done purely functional web pages as hook files, and we've
810done command line apps, so now let's interact with an app over
911the web. The fundamental concepts are no different than from the
@@ -14,26 +16,26 @@ javascript.
1416Let's create a small web app that counts the number of times you
1517poke it. There'll be a button to poke the app, and line of text
1618below it saying how many times the app has been poked. We can
17−update this by subscribing to that information from the app.
19+update this by subscribing our page to the relevant path on its app.
1820
19−Let's first write the app, `/ape/click.hoon`:
21+Let's first write the app, `/app/click.hoon`:
2022
2123```
2224/? 314
2325!:
2426|%
25−++ move ,[bone %diff %mark *]
27+++ move {bone $diff $mark *}
2628--
2729!:
28−|_ [hid=bowl clicks=@]
30+|_ {hid/bowl clicks/@}
2931++ poke-click
30− |= click=%click
32+ |= click/$click
3133 ~& [%poked +(clicks)]
3234 :_ +>.$(clicks +(clicks))
3335 %+ turn (prey /the-path hid)
34− |=([o=bone *] [o %diff %clicks +(clicks)])
36+ |=({o/bone *} [o %diff %clicks +(clicks)])
3537++ peer-the-path
36− |= pax=path
38+ |= pax/path
3739 [[[ost.hid %diff %clicks clicks] ~] +>.$]
3840--
3941```
@@ -48,12 +50,12 @@ number of clicks.
4850Let's take a look at the new marks. Here's `/mar/click.hoon`:
4951
5052```
51−|_ click=%click
53+|_ click/$click
5254++ grab
5355 |%
5456 ++ noun |=(* %click)
5557 ++ json
56− |= jon=^json
58+ |= jon/^json
5759 ?> =('click' (need (so:jo jon)))
5860 %click
5961 --
@@ -69,11 +71,10 @@ asserting the parsing succeeded with `need`, and asserting the
6971result was 'click' with `?>`, which asserts that its first child
7072is true.
7173
72−> Note the argument to `++json`is `jon=^json`. Why `^json`?
74+> Note the argument to `++json`is `jon/^json`. Why `^json`?
7375> `++json` shadows the type definition, so if we want to refer to
7476> the type, we have to prepend a `^`. This extends to multiple
75−> levels: `^^^foo` means "not the innermost `foo`, nor the next
76−> innermost, nor the next innermost, but the next innermost".
77+> levels: `^^^foo` means the fourth most innermost instance of `foo`.
7778
7879> `++jo` in `zuse` is a useful library for parsing complex json
7980> into hoon structures. In this case, the `:` between `so` and
@@ -81,7 +82,7 @@ is true.
8182> the core `jo`. Our case is actually simple enough that the
8283> `?>` line could have been `?> =([%s 'click'] jon)`.
8384
84−We can test this mark from the command line:
85+We can test this mark from the command line (don't forget to start your app with `|start %click`)
8586
8687```
8788~fintud-macrep:dojo> &click %click
@@ -99,7 +100,7 @@ ford: cast %click
99100And `/mar/clicks.hoon`:
100101
101102```
102−|_ clicks=@
103+|_ clicks/@
103104++ grow
104105 |%
105106 ++ json
@@ -117,7 +118,7 @@ object with a single field "clicks" with our value.
117118
118119```
119120~fintud-macrep:dojo> &json &clicks 6
120−[%o p={[p='clicks' q=[%n p=~.^]]}]
121+[%o p={[p='clicks' q=[%n p=~.6]]}]
121122~fintud-macrep:dojo> &mime &json &clicks 6
122123[[%text %json ~] p=12 q='{"clicks":6}']
123124```
@@ -143,14 +144,16 @@ the app from the command line.
143144 `:click` and print out the subscription updates on the command
144145 line.
145146
147+#Frontend
148+
146149That's all that's needed for the back end. The front end is just
147−some "sail" html and javascript. Here's `/pub/click/hymn.hook`:
150+some "sail" html (Hoon markup for XML) and javascript. Here's `/web/click.hoon`:
148151
149152```
150153;html
151154 ;head
152155 ;script(type "text/javascript", src "//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js");
153− ;script(type "text/javascript", src "/~~/~/at/home/lib/urb.js");
156+ ;script(type "text/javascript", src "/~/at/lib/js/urb.js");
154157 ;title: Clickety!
155158 ==
156159 ;body
@@ -159,7 +162,7 @@ some "sail" html and javascript. Here's `/pub/click/hymn.hook`:
159162 ;div#err(class "disabled");
160163 ;div#clicks;
161164 ==
162− ;script(type "text/javascript", src "click/main.js");
165+ ;script(type "text/javascript", src "/click/main.js");
163166 ==
164167==
165168```
@@ -168,10 +171,12 @@ You should recognize the sail syntax from an earlier chapter.
168171Aside from jquery, we also include `urb.js`, which is a framework
169172for interacting with urbit.
170173
174+To view the frontend, point your browser at `ship-name.urbit.org/~~/click` if you're on the live network. If you're running a fake galaxy, navigate to whatever port it's running on, which is usually: `https://localhost:8443/~~/click`.
175+
171176We have a button labeled "Poke!" and a div with id `clicks` where
172177we'll put the number of clicks. We also include a small
173178javascript file where the client-side application logic can be
174−found. It's in `/pub/click/main.js`:
179+found. It's in `/web/click/main.js`:
175180
176181```
177182$(function() {
@@ -208,14 +213,10 @@ $(function() {
208213})
209214```
210215
211−We first set the default application to "click". A page can, of
212−course, talk to multiple apps by specifying on each message which
213−app to talk to.
214−
215216We set up two event handlers. When we click the button, we run
216−`window.urb.send`, which sends a poke to an app. The arguments
217−are data, parameters, and callback. The data is the specific
218−data to send. The parameters are all optional, but here's a list
217+`window.urb.send`, which sends a poke to the app specified as the first argument, in this case our :click app. The arguments
218+are data, parameters, and the callback. The data is the specific
219+data we want to send. The parameters are all optional, but here's a list
219220of the available ones:
220221
221222- `ship`: target urbit. Defaults to `window.urb.ship`, which
@@ -231,15 +232,10 @@ In our case, we specify only that the mark is "click".
231232The callback funciton is called when we receive an
232233acknowledgment. If there was an error, we put it in the `err`
233234div that we defined above. Otherwise, we printf to the console a
234−message saying the poke succeeded. A common pattern is to gray
235−out a button when you click it and only reenable it when you get
236−the positive acknowledgment.
235+message saying the poke succeeded. As is common, we gray
236+out the button when it is clicked. It is only reenabled when positive acknowledgement is received.
237237
238−We also call `window.urb.bind`, which subscribes to a data stream
239−on an app. It also takes three arguments: path, parameters, and
240−callback. The path is the path on the app to subscribe to. The
241−parameters are all optional (inded, we omit them entirely here),
242−but are similar to those for `send`:
238+Our second event handler is `window.urb.bind`, which is called immediately when the page is loaded, subscribing the page to the specified data stream on the app set with `urb.appl` (which is, in this case, :click). It also takes three arguments: path, parameters, and callback. The path is the path on the app to subscribe to. The parameters are all optional (indeed, we omit them entirely here), but are similar to those for `send`:
243239
244240- `ship`: target urbit. Defaults to `window.urb.ship`, which
245241 defaults to the urbit which served the page.
@@ -255,10 +251,6 @@ The callback function here just updates the data in the `clicks`
255251div. A truly robust app would intelligently handle errors, of
256252course.
257253
258−This app can be tested from the web by going to
259−`/~~/home/pub/click` on your server. Usually, this is
260−`ship-name.urbit.org/~~/home/pub/click`.
261−
262254Note that the app doesn't have anything web-specific in itself.
263255As far as it knows, it's just receiving pokes and subscriptions.
264256The javascript is fairly pure as well, sending and receiving json