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/.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: ```jsx // _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](/docs/manual/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: ```yaml outputs: { card: false } # no share card for this page ``` ```yaml 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: ```js // 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: ```js 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: ```jsx // in _layout.jsx {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.