on ece6841 help sign in
326 lines 13 kB history raw
1:- :~ navhome/'/docs/'
2 navuptwo/'true'
3 next/'true'
4 sort/'8'
5 title/'Web (Eyre)'
6 ==
7;>
9# Web (Eyre)
11;div(class "row")
12 ;div(class "col-md-8")
14Your Urbit runs its own webserver, Eyre, that handles all things HTTP. Here we'll cover the features of Eyre that most resemble a traditional web server.
16By default Eyre uses Tree, which is sort of like a combination of [Jekyll](https://jekyllrb.com/) or [Kirby](https://getkirby.com/) and Finder on OSX. Tree is a simple ui for browsing the contents of the filesystem, statically publishing a blog or any kind of content and for running single-page apps.
18Tree was built primarily to display both our documentation and the contents of `urbit.org`. We provide a few simple examples [here](#-examples) of how to publish using Tree. If you're interested in doing anything complex it's worth checking out the [docs source](https://github.com/urbit/docs) and the [urbit.org](https://github.com/urbit/urbit.org) source.
20We ship `tree` as compiled JavaScript on your Urbit, but the source lives in its own repo [here](https://github.com/urbit/tree).
22 ==
23==
25## Quickstart
27Your Urbit runs a web server and can be found at either `http://localhost:8080/` (or `8081` if you're running other processes that might be occupying `8080`, you can determine which port your urbit is on by looking at your boot sequence — it's specified there), or `http://your-urbit.urbit.org/`.
29;span(class "red")
30; (Make sure you have a desk mounted to unix, as covered in the [filesystem walkthrough](/docs/using/filesystem)).
31==
33To switch the desk you're serving from:
35```
36|serve %sandbox
37```
39To host a file on the web try putting the following in `/sandbox/web/test.umd` (from Unix):
41```
42# Hello
44This is a simple Urbit markdown file.
45```
47Create the directory `/sandbox/web/test/` and add two more Urbit markdown files in it.
49NOTE: Due to a bug in Urbit you may have to create the directory and the file in it in rapid succession using something like `mkdir sandbox/web/test && touch sandbox/web/test/first.md`.
51Now modify `/sandbox/web/test.umd` to list the children using `;list;`:
53```
54# Hello
56This is a simple markdown file.
58;list;
59```
61To view your file rendered using tree:
63```
64http://localhost:8080/test/
65```
67To view your file as raw `umd`:
69```
70http://localhost:8080/test.umd
71```
73To view your file as raw `html`:
75```
76http://localhost:8080/test.html
77```
79You may have noticed that we just created both `test.umd` and `test/`. In Urbit, there is no distinction between a directory and a file. So, if you're adding files directly from unix, simply `mkdir test` and Urbit will treat the file and directory as the same entity.
81You can use this feature to change your homepage at `your-urbit.urbit.org` with the page `/home/web.umd`, where `home` is the current mounted desk. By default, `web.umd` will display some info about your urbit, but you can customize it to your heart's content.
83## Examples
85We've created a few simple examples of how to get set up publishing content from your Urbit. Feel free to ask questions in the comments.
87;list;
89## Manual
91## `/web`
93This is the equivalent of a `public_html` directory. Your Urbit looks in this directory to serve content to the world. You can change what desk you're serving from using `|serve`.
95Switch to the `%sandbox` desk:
97```
98|serve %sandbox
99```
101Let's quickly step through the default contents of `web/`:
103- `404.hoon` - The default 404 page.
104- `dojo.hoon` - Page body that loads the `dojo` React module.
105- `lib/css/bootstrap.css` - The Urbit-flavored bootstrap
106- `lib/css/codemirror.css` - Syntax highlighting
107- `lib/css/fonts.css` - The Urbit custom fonts
108- `lib/js/hoon.js` - Hoon syntax highlighting
109- `lib/js/sole.js` - `dojo` operational transformation JS
110- `lib/js/urb.js` - Base Urbit JS library. Handles AJAX and polling.
111- `static.umd` - Sample static file
112- `talk/` - Talk compiled JS / CSS
113- `talk.hoon` - Page body that loads the `talk` React module.
114- `tree/` - Tree compiled JS / CSS
115- `tree.hoon` - Page body that loads the `tree` React module.
117## Tree
119Tree is a simple publishing tool for files that live on your Urbit. You're probably reading this file using Tree right now. The main driving use-case for Tree has been for us to host our own documentation and the surrounding discussion. Tree remains a pretty simple and flexible tool for getting content online. We think it's pretty great.
121Tree is a simple static publishing tool and the basic UI for browsing the filesystem. We take it one step further and make it possible to write modules (tiny little apps), like Talk and Dojo, that can be run directly inside of Tree.
123In the browser Tree is a [React](https://facebook.github.io/react/) / [Flux](https://facebook.github.io/react/blog/2014/05/06/flux.html) app that uses a slightly modifed version of [Bootstrap](http://getbootstrap.com/). On your Urbit Tree is a renderer that translates data in `%clay`, our filesystem, into JSON / JSX that can be read by the client.
125Your Urbit comes with a pre-built copy of the tree (as a single `.js` file). If you're interested in helping to develop tree or learning about how it works, it has its own GitHub repo [here](https://github.com/urbit/tree). We have our own fork of Bootstrap, which lives [here](https://github.com/urbit/bootstrap).
127## `/web/pages`
129To render content without the Tree put it in `/web/pages`. Files in this directory aren't wrapped by Tree. For some examples check out [`web/` in the examples repo](https://github.com/urbit/examples/tree/master/web).
131## Publishing files
133Publishing files in Tree is simple. Try dropping a file in `/web` (as covered in the Quickstart) and navigating to it.
135The best example of more complicated usage of Tree is covered by the Urbit docs themselves. See anything while perusing the docs that you'd like to use yourself? The docs are all on GitHub [here](https://github.com/urbit/docs).
137## Frontmatter
139Most `.umd` files begin with some frontmatter, which determines the title and other settings for rendering the file correctly. E.g.:
141```
142:- :~ navhome/'/home/'
143 next/'true'
144 sort/'1'
145 title/'Example Frontmatter Title'
146 ==
147;>
148```
150Here are the fields we support:
152### `title`
154String. Example: `title/'Tree manual'`.
156This sets the title in the nav or in lists as distinct from the filename.
158### `next`
160Boolean. Example: `next/'true'`
162Adds a 'next' link at the bottom of the page that links to the next item as decided by the sort order.
164### `sort`
166Integer. Example: `sort/'7'`
168User-defined sort. Indicates the sort order as distinct from alphabetical sort. These numbers should not be overlapping.
170### `hide`
172Boolean. Example: `hide/'true'`
174Whether or not to hide the item from the tree.
176### `date`
178Urbit date. Example: `date/'~2016.2.22'`
180Used for sorting posts by date.
182## Using components
184Tree is built using React with a small library of components that you can add to your pages using [JSX](https://facebook.github.io/jsx/) tags.
186If you don't know anything about JSX that's okay: basically we just give you a few custom HTML tags that you can use to create components on the page.
188For those familiar with React / Flux each JSX tag corresponds to a component in [the source](https://github.com/urbit/tree/tree/master/js/components).
190### `<list>`
192Example: `<list src="/posts" titlesOnly="true" />`
194Creates a list of children at a path. Defaults to the current path.
196Optional properties:
198- `src`: Path to load kids from.
199- `titlesOnly`: Only show the 'title' which is either the filename or the first h1.
200- `sortBy`: Can be `date` if items have a `date` YAML.
201- `className`: Class to be assigned to the container.
203### `<kids>`
205Example: `<kids src="/posts" />`
207Includes all the children at the specified path separated by `<hr>` tags.
209Optional properties:
211- `src`: Path to load kids from.
212- `className`: Class to be assigned to the container.
214### `<toc>`
216Example: `<toc noHeader="true" />`
218Creates a table of contents from the `h1` - `h6` tags on the page.
220Optional properties:
222- `match`: Tag name to match. If you wanted to only match `h2` tags it could be `match="h2"`
223- `noHeader`: By default we add a 'Table of Contents' header to the top. Remove it with `noHeader="true"`.
225## Implementation
227On the frontend Tree is mostly just a standard Flux app: components generate actions that get dispatched to stores which are picked up by components. If you're not familiar with Flux, [this overview](https://facebook.github.io/flux/docs/overview.html) is a good place to start.
229As a file browser Tree does a simple job: it fetches data and keeps a cache of what it has seen. To do this simple job we do three fancy things: `manx` to JSON encoding, the Async component and Modules.
231### `manx` to JSON format
233Since we want to use React to manage our DOM lifecycle we actually transfer the DOM structure of each page as JSON over the wire, and 'reactify' it on the client side.
235On the Urbit side we have a type for html: `++manx`. Our wire format for sending HTML as JSON is really similar to a `++manx`. If you're not interested here's what the json looks like:
237```
238"string" || {gn:"string", ga:{key:"string", [...]}, c:[...]}
239```
241To make this clearer let's look at some HTML and its JSON representation:
243```
244<div class="blue">
245 <h1>Title</h1>
246</div>
247```
249```
250{gn:"div", ga:{className:"blue"}, [
251 {gn:"h1", ga:null, "Title"}
252]}
253```
255To see the mechanics of how this is handled on the frontend, checkout `components/Reactify.coffee` in the `urbit/tree` repo.
257### Async component
259Each of our components (even those we fetched from the server) can depend on data that may not exist in our stores, so we wrap our components in a general-purpose Async component. You can find the component in `components/Async.coffee` in the `urbit/tree` repo.
261When we say that we just fetch HTML as JSON it's actually slightly more complicated. When we fetch a node in the filesystem we might not want to fetch its entire contents. Sometimes we just get the title as a part of a list of children, sometimes we might get a snippet (in a list with previews), and sometimes we get the whole thing. On the Urbit side these results are provided by `ren/tree/json`.
263From the perspective of the frontend we just send queries on a path that obey a simple API. To see this in action, here's our `BodyComponent`:
265```
266query {
267 body:'r'
268 name:'t'
269 path:'t'
270 meta:'j'
271 sein:'t'
273```
275Here we're asking for the body, name, path, metadata and parent of the current path. When it loads that data gets passed to our component as props.
277### Module basics
279A module is a special component that can kind of 'take over' the page. It can change properties of the nav bar as well as load custom scripts / css.
281Talk, for example, looks like this:
283```
284<module nav_title="Talk" nav_no-dpad="" nav_no-sibs="" nav_subnav="talk-station">
285 <script src="/~~/~/at/lib/js/urb.js" />
286 <script src="/talk/main.js" />
287 <link href="/talk/main.css" rel="stylesheet" />
288 <talk />
289</module>
290```
292A module will first download all the scripts and styles that it specifies before trying to load any contained components. This means that you can define React components in external scripts and a module can be entirely self contained. The `<talk>` component isn't a part of Tree — it's loaded first before it's executed.
294If you're interested in seeing how a module works you can check out the source for Talk [here](https://github.com/urbit/talk). Dojo also ships on your Urbit, its source is [here](https://github.com/urbit/sole).
296## `urb.js`
298The most basic interface between your browser and your Urbit is `urb.js`. This small library provides the basic utilities for sending and receiving messages from an Urbit.
300### `window.urb.appl`
302Each JSON message sent to your Urbit needs an app endpoint. Can be set as a global `window.urb.appl` or set on a per-request basis in the payload to `send()`.
304### `window.urb.oryx`
306CSRF token. Written to the page by Eyre, our webserver, when logged in. Required part of any authenticated request and included by default.
308### `window.urb.req(method,url,params,json,cb)`
310Our basic request wrapper. You can see here how a request needs to be packaged to be properly understood by your Urbit.
312### `window.urb.subscribe({path:"string"})`
314Subscribe to an endpoint. Subscription data is returned through the continuous long poll.
316### `window.urb.unsubscribe({path:"string"})`
318Close subscription on specified path.
320### `window.urb.poll()`
322Mechanics of the continuous long poll. Used mostly internally.
324### `window.urb.util`
326Library of utility and helper functions.