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
-
pageis the page's data, includingsrc(the raw source) andbody(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.