Hello, world

The concepts that make Origami unique

The Origami language lets you concisely define the structure of a website. This page introduces the three key concepts — trees, scope, and maps — and a template system that make the language unique. If you prefer a hands-on approach, start with the tutorial.

A tiny site

HTML and CSS define the content inside web pages — but not how those pages are structured into an overall hierarchy your users can browse. That’s what the Origami language is for.

The following Origami file defines a tiny site:

{
  index.html = "Hello, world!"
}

Everything between the { } curly braces creates a site tree with just one branch:

g index.html Hello, world! ->index.html index.html

Some terminology: The root of this tree is the circle on the left. The branch has a label or name, which we’ll call a key, and that leads to a node or value. In cases like this, the key “index.html” is a text string, but a key could be a number or something else. The value here (“Hello, world!”) also happens to be a string, but values can be anything: an image, a data file, etc.

File names often contain periods so, unlike many programming languages, Origami lets you include periods in a key like index.html.

The Origami server lets you immediately browse this tree. The server can produce the kind of diagram shown above so you can confirm your site’s structure and explore what you’re building.

Key points: An Origami file provides a concise way to define a site. You can interact with your site immediately and view it as an interactive diagram.

Websites as trees

We often design and browse websites a single page at a time, but you can step back and consider all the pages on a site as a tree of pages and other resources.

Example: the small About Us site defines has the following pages:

You can think about this set of pages as a tree:

g index.html <h1>About Us</h1> ->index.html index.html team ->team team team/Alice.html <h1>Alice</h1> team->team/Alice.html Alice.html team/Bob.html <h1>Bob</h1> team->team/Bob.html Bob.html team/Carol.html <h1>Carol</h1> team->team/Carol.html Carol.html

Website creators refer to URLs as routes: when you navigate to a URL like team/Alice.html, you’re picking one particular route through this site’s tree. Conceptually speaking, the web server starts at the tree’s root on the left and then follows the keys team and Alice.html to find the web page it will send to your browser.

The site’s complete tree is a little bigger than what’s shown above, because it also includes CSS stylesheets, image files, or other resources referenced by the HTML:

g index.html <h1>About Us</h1> ->index.html index.html team ->team team assets ->assets assets images ->images images thumbnails ->thumbnails thumbnails team/Alice.html <h1>Alice</h1> team->team/Alice.html Alice.html team/Bob.html <h1>Bob</h1> team->team/Bob.html Bob.html team/Carol.html <h1>Carol</h1> team->team/Carol.html Carol.html assets/personIcon.svg <svg … assets->assets/personIcon.svg personIcon.svg assets/styles.css body { color: … assets->assets/styles.css styles.css images/kingfisher.jpg [binary data] images->images/kingfisher.jpg kingfisher.jpg images/van.jpg [binary data] images->images/van.jpg van.jpg images/venice.jpg [binary data] images->images/venice.jpg venice.jpg thumbnails/kingfisher.jpg [binary data] thumbnails->thumbnails/kingfisher.jpg kingfisher.jpg thumbnails/van.jpg [binary data] thumbnails->thumbnails/van.jpg van.jpg thumbnails/venice.jpg [binary data] thumbnails->thumbnails/venice.jpg venice.jpg

This conceptual tree can help you envision and build a site. The structure you pick determines the routes that will be used to access each page and resource.

How your users navigate and experience your site is a separate decision. The designs you choose for each page — the links each page offers, and how those links create a flow — determine the experiences your users will have.

Most web systems don’t give you a way to directly edit or visualize a site’s tree. In Origami you directly construct your site’s tree, combining branches defined in different ways.

Tree scope

A formula you write in Origami defines a key and a value, like the index.html and text above. Those formulas can refer to other values.

Origami determines the meaning of those references by defining a scope: the set of all the names available for use. As a trivial example, you can recreate the “Hello, world!” page above by defining the “name” as a separate value:

{
  name = "world"
  index.html = `Hello, ${ name }!`
}

The text enclosed by backtick characters constructs a text string. Origami evaluates the name reference inside the ${ } placeholder. Origami finds the nearby name key, so incorporates the corresponding value into the final text.

g name world ->name name index.html Hello, world! ->index.html index.html

Key point: The scope available to an Origami expression is determined by the tree structure containing the expression.

Tree scope is hierarchical

Origami resolves a reference like name by searching from the location of the reference towards the tree’s root (left, in these diagrams). As soon as Origami finds a matching key, it uses that value.

We can observe tree scope in action by adding a level to our little tree, making the index page available at about/index.html:

{
  name = "world"
  about = {
    index.html = `Hello, ${ name }!`
  }
}
g name world ->name name about ->about about about/index.html Hello, world! about->about/index.html index.html

This produces the same “Hello, world!” message as before. When Origami sees name in the index.html formula, it searches the local about area of the tree for name. It doesn’t see a name there, so moves up to the tree’s top level, where it does find a name.

Key point: Tree scoping in Origami works like block scoping in many programming languages.

Referencing a local file

You can view many of the things you work with, such as folders and files or data in data files, as trees too. For example, the tree you define in an Origami file is considered to be part of the larger file system tree, so those surrounding files are also in scope.

Let’s say we have a folder called myProject that contains:

myProject/
  name
  site.ori

Here site.ori is an Origami file (indicated by the .ori extension) that contains:

{
  index.html = `Hello, ${ name }!`
}

And the separate name file contains a bit of plain text:

world

Given this arrangement, the site.ori file produces the same tiny site shown before:

g index.html Hello, world! ->index.html index.html

Here, when Origami looks for name, it doesn’t find a name key in the Origami file, so it moves up into the surrounding folder. It finds the little name text file there, so uses that file’s contents as the name.

By default, Origami will continue searching up the folder hierarchy, looking for name, until it reaches the directory where the Origami server was started. The folders and files in your project are available in the scope of your Origami formulas. In most programming languages, you must first “import” or otherwise explicitly load files from the file system.

Key points: Origami expressions can directly reference files in your project, making it easy for you to incorporate files into your site.

Data can be a tree too

You can view hierarchical data as a tree too. Suppose our project has a data file called data.json:

myProject/
  data.json
  site.ori

and this data.json file contains:

{
  "name": "world"
}

The Origami file can incorporate that data into the index.html page with:

{
  index.html = `Hello, ${ data.json/name }!`
}

This uses Origami’s tree scoping to directly reference a file. In this case, we’re using a slash-separated path data.json/name to extract the name value from that data file. This produces the same result as before:

g index.html Hello, world! ->index.html index.html

Many programming languages require you to parse data in formats like JSON. Origami includes built-in parsing for JSON and YAML files. You can drop in support for other parsers.

Key point: Origami lets you easily read data from a data file. You can treat hierarchical data like any tree and get things out of it with slash-separated paths.

Including a file folder in a tree

You can incorporate folders from your project into your site. Suppose your project looks like:

myProject/
  images/
    image1.jpg
    image2.jpg
    image3.jpg
  site.ori

You can reference this images folder name in the Origami file, and Origami will find it using the tree scoping described above:

{
  images
}

This creates a site that looks like:

g images ->images images images/image1.jpg [binary data] images->images/image1.jpg image1.jpg images/image2.jpg [binary data] images->images/image2.jpg image2.jpg images/image3.jpg [binary data] images->images/image3.jpg image3.jpg

All these images are available at URLs like images/image1.jpg.

Key point: You can quickly incorporate folders of resources like images, stylesheets, and JavaScript files into your site with a folder name.

Turning a tree of stuff into something else

You may often find yourself creating content in one form — text, images, etc. — that you want to process into some other form before publishing it on your site.

For instance, you might want to write your site content in a folder of markdown files that you will convert to HTML. You can visualize that markdown folder as a tree:

g markdown ->markdown markdown markdown/Alice.md Hello, **Alice**! markdown->markdown/Alice.md Alice.md markdown/Bob.md Hello, **Bob**! markdown->markdown/Bob.md Bob.md markdown/Carol.md Hello, **Carol**! markdown->markdown/Carol.md Carol.md

You can transform that tree of markdown files into a corresponding tree of HTML files. Origami includes a markdown-to-HTML command called @mdHtml. That command works on a single file, so you can use it to turn a single markdown file into HTML.

{
  Alice.html = @mdHtml(markdown/Alice.md)
}
g Alice.html Hello, <strong>Alice</strong>! ->Alice.html Alice.html

Instead of translating just one file a time, you can transform all the files in the markdown folder with one instruction using the @map command:

{
  html = @map(markdown, @mdHtml)
}

This turns the tree of markdown files into a tree of HTML pages:

g Alice.md Hello, <strong>Alice</strong>! ->Alice.md Alice.md Bob.md Hello, <strong>Bob</strong>! ->Bob.md Bob.md Carol.md Hello, <strong>Carol</strong>! ->Carol.md Carol.md

This isn’t quite what’s wanted — the values are HTML, but the keys (file names) still end in .md. A slightly longer @map expression can change both the keys and the values:

{
  html = @map(markdown, { extensions: "md->html", valueMap: @mdHtml })
}

which gives

g html ->html html html/Alice.html Hello, <strong>Alice</strong>! html->html/Alice.html Alice.html html/Bob.html Hello, <strong>Bob</strong>! html->html/Bob.html Bob.html html/Carol.html Hello, <strong>Carol</strong>! html->html/Carol.html Carol.html

You can browse the transformed HTML immediately. Other programming environments have maps too, but Origami’s are “lazy”, meaning they don’t do work to create something until you ask for it. They can also work on deep trees, not just flat arrays, and can be applied equally to any data source.

If you wanted the mapped HTML pages to be the entire site instead of just the html area, you could update site.ori to return the map itself:

  @map(markdown, { extensions: "md->html", valueMap: @mdHtml })

which puts all the transformed HTML pages at the top level:

g Alice.html Hello, <strong>Alice</strong>! ->Alice.html Alice.html Bob.html Hello, <strong>Bob</strong>! ->Bob.html Bob.html Carol.html Hello, <strong>Carol</strong>! ->Carol.html Carol.html

Key point: You can use Origami maps to efficiently transform collections of content in bulk.

Templates

Many website creation tools use templates: text documents with placeholders to indicate where data should go. You can use any template system with Origami, but Origami also comes with a built-in template system that understands trees of files and data.

An Origami project for a blog might have a structure like:

myProject/
  posts/
    post1.html
    post2.html
  src/
    index.ori
    post.ori
    site.ori

where each post contains some HTML and some data at the top.

---
title: My first post
---
Here's my first post!

The post.ori file contains an Origami template that mixes HTML with ${ } placeholders to incorporate data:

=`<html>
  <head>
    <title>${ _/title }</title>
  </head>
  <body>
    ${ _/@text }
  </body>
</html>
`

You can apply this template as a function to a single post. The _/title expression will extract the title from whatever input you give to the template. The _/@text expression will incorporate the body of the input document.

You can call this template in the site.ori file:

{
  firstPost.html = page.ori(posts/post1.html)
}

This produces a site with one page:

g firstPost.html <html><head><title>My First Post</title>… ->firstPost.html firstPost.html

where the firstPost.html page contains:

<html>
  <head>
    <title>My First Post</title>
  </head>
  <body>
    Here's my first post!
  </body>
</html>

You can apply a page template in a map to process all your posts at once:

{
  pages = @map(posts, page.ori)
}

This produces:

g pages ->pages pages pages/post1.html …<title>My First Post</title>… pages->pages/post1.html post1.html pages/post2.html …<title>My Second Post</title>… pages->pages/post2.html post2.html

Key point: You can use template systems in Origami to turn files and data into text. Origami comes with a built-in template system.

Using a map in a template

A unique feature of Origami templates is that you can use maps inside them to process a collection of documents or data into HTML. You can use this to make page elements for navigation that reflect the structure of the original content.

Continuing the blog example above, you can define an index.ori template that will create links for each post:

<html>
  <head>
    <title>Posts</title>
  </head>
  <body>
    <ul>
      {{ @map(posts, (post, fileName) => `
      <li><a href="pages/${ fileName }}">{{ post/title }</a></li>
      `) }}
    </ul>
  </body>
</html>

Origami looks up references like posts inside the template using the same tree scope discussed earlier. Inside the @map, the fileName reference returns the name of the page file like “post1.html”.

Tree scope erases the boundary between the files outside the template and the HTML and instructions inside the template, letting you generate HTML that reflects the contents of the original posts folder.

Invoke this template to create the index page:

{
  index.html = index.ori()
  pages = @map(posts, page.ori)
}

The site looks like:

g index.html …<title>Posts</title>… ->index.html index.html pages ->pages pages pages/post1.html …<title>My First Post</title>… pages->pages/post1.html post1.html pages/post2.html …<title>My Second Post</title>… pages->pages/post2.html post2.html

and the index page will link to all the posts:

<html>
  <head>
    <title>Posts</title>
  </head>
  <body>
    <ul>
      <li><a href="pages/post1.html">My First Post</a></li>
      <li><a href="pages/post2.html">My Second Post</a></li>
    </ul>
  </body>
</html>

Key points: Origami’s built-in template system lets you create navigation elements and other parts of web pages that are based on collections of things.

That’s basically it

This covers the key unique concepts in Origami. The examples shown here are very basic, but you can apply these to create real sites.

If you’d like to try building a simple site this way, try the tutorial. If you’d like to try Origami on your own machine, copy the origami-start project.