taragen static sites from one binary

Extra outputs per page

An output is another file made from each page, next to it: a plain-text version, a JSON summary, a share card image. Outputs are defined by templates in an _outputs/ folder.

Defining an output

An output template is _outputs/<name>.jsx. The output's name is the first word of the file name, and everything after the first . (before .jsx) is the URL suffix:

File Name Suffix URL for /articles/2021/ngrok
_outputs/txt.jsx txt .txt /articles/2021/ngrok.txt
_outputs/json.jsx json .json /articles/2021/ngrok.json
_outputs/card.png.jsx card .card.png /articles/2021/ngrok.card.png

A name is a lowercase word of letters and digits, starting with a letter. The root page uses index: /index.txt, /index.card.png.

build writes the output beside the page's folder: _public/articles/2021/ngrok.txt sits next to _public/articles/2021/ngrok/index.html. Static hosts serve both without any setup.

A plain-text version of every page:

// _outputs/txt.jsx
data({ contentType: "text/plain; charset=utf-8" });
`${page.title ?? page.date}\n\n${page.src}`

What an output template sees

  • page is the page's data, including src (the raw source) and body (the rendered body before layouts).
  • All the page's globals, as for a layout.
  • Layouts are not applied.

The template's last expression is the result. If it's a function, it's called with no arguments. The result can be:

  • a string, written exactly as is, with no escaping or formatting; or
  • an element, serialized like a page.

Output templates are the only JSX files that may return a bare string.

data() in an output template sets the output's own settings, not the page's data:

Key Meaning
contentType The Content-Type in serve. Defaults to the type for the suffix's last extension (text/plain; charset=utf-8 for .txt, image/png for .png), or application/octet-stream if unknown.
preamble Text written before the output. Defaults to none, even for HTML.
scale For PNG outputs only; see Share cards.

An output with contentType: text/html is formatted like an HTML page.

Which pages get outputs

Every page that has a source and is text/html gets every output in scope. Grouping nodes and non-HTML pages like feed.xml.jsx get none. A draft's outputs are drafts too.

Output templates are scoped like layouts: one in _outputs/ applies to pages in that folder and below, and for each name, the nearest template wins. So logs/_outputs/card.png.jsx replaces the root _outputs/card.png.jsx for pages under logs/. If the nearer template has a different suffix, those pages get the nearer suffix.

Turning outputs off

Set outputs in a page's data:

outputs: { card: false }   # no share card for this page
outputs: false             # no outputs at all

Names that don't apply to the page are ignored. Since this is ordinary page data, a _defaults.jsx can turn an output off for a whole section:

// notes/_defaults.jsx
outputs = { txt: false };

page.outputs

Taragen replaces outputs in every page's data with a map from output name to URL, for the outputs that apply and weren't turned off:

page.outputs // { txt: "/articles/2021/ngrok.txt", card: "/articles/2021/ngrok.card.png" }

The map is complete before any page renders, so layouts, page bodies, and pages() results can all link to outputs:

// in _layout.jsx
{page.outputs?.txt && <link rel="alternate" type="text/plain" href={page.outputs.txt} />}

Note that a page that turned an output off never sees its false in page.outputs; the name is simply missing.

Errors

An output template that throws fails the build, and in serve returns a 500 with the error. If an output's URL is the same as another page, output, static file, alias, or redirect, the build fails naming both. For example, a static notes.txt next to a page notes with a txt output is a collision.

[ txt · edit on github · card ]