taragen static sites from one binary

Writing JSX

Taragen's JSX is a server-side template language. Elements turn straight into HTML strings; there is no React, no components with state, no hooks, and nothing runs in the browser. Write class, not className.

Pages, data, and multiple roots

A JSX page can have several root elements, or start with an expression:

data({ title: "Home" });
<h1>Welcome</h1>
<p>Latest posts:</p>
{partial("_partials/latest")}

A data({...}) call at the very top of the file (after whitespace and comments) sets page data. The trailing ; is optional. data() merges its object into both page and the page's data, so later code in the file and the layouts see it. In a generated page template, a params(...) call can sit alongside data() in these leading statements.

Values in JSX

Children can be elements, strings, numbers, or arrays (flattened, so .map(...) works). null, undefined, true, and false render nothing, so conditionals work:

{page.draft && <span class="badge">Draft</span>}
{page.tags?.map(t => <a href={`/tags/${t}`}>{t}</a>)}

Attribute values can be:

Value Result
string name="value"; an empty string omits the attribute
number Printed as JS prints it
true / false Bare attribute (<input disabled>) / omitted
object Serialized as a style string: style={{ color: "red", "font-size": "2em" }}
null / undefined Omitted

Anything else, such as an object as a child or a function as an attribute, throws a TypeError and fails the render.

Attributes are written in the order you wrote them, and the output is identical on every build, so diffs of _public/ show only real changes. Void elements like <img>, <meta>, and <br> are self-closed.

Escaping and raw()

Text and attribute values are escaped, so a title with & or " is safe anywhere, including in attributes and XML feeds. Text inside <script> and <style> is written as is.

To insert HTML you trust, use raw():

<div class="post">{raw(post.body)}</div>

You need raw() for any HTML string, such as body from pages() results or page.body. You don't need it for partial() results or a layout's content, which are already HTML.

Whitespace and <pre>

JSX normally collapses whitespace, but newlines inside <pre> blocks are kept, so code samples written in JSX keep their lines.

Output formatting

HTML output (text/html) is passed through an HTML formatter that normalizes indentation. Other content types are written exactly as rendered.

[ txt · edit on github · card ]