Skip to main content

Prerender API

The CLI covers the common case. When you need to drive rendering from your own build script – a different template per page, a computed output path, content fetched before the render – import prerender directly.

import { prerender } from "nodality/ssg";

await prerender({
template: "src/index.html",
output: "upload/index.html",
build: async () => {
const elements = [{ type: "h1", text: "Hello" }];
const nodes = [{ op: "blast" }];

new Des()
.nodes(nodes)
.add(elements)
.set({ mount: "#mount" });
}
});

template, output and build are required; build must be an async function. The rest have defaults.

Options

OptionDefaultMeaning
templateHTML shell to render into. Required
outputWhere to write the result. Required
buildAsync function that constructs the page. Required
mount"#mount"Selector the rendered tree replaces
url"http://localhost/"Document URL seen by the page
viewport{ width: 390, height: 844 }Size reported to responsive code
localeLocale for this render
localStorageKey"h7lang"Key the page reads its locale from
htmlLanglang attribute on <html>
canonicalCanonical URL for this page
alternateshreflang alternates

viewport matters more than it looks. Responsive code branches on width at build time, so a page prerendered at the default 390px ships its mobile layout as the pre-JavaScript HTML. Set it to match the layout you want crawlers and the first paint to see.

Multiple locales

prerenderEachLocale renders the same page once per locale, with the locale set before build runs.

import { prerenderEachLocale } from "nodality/ssg";

Whole sites

prerenderSite takes one config and renders every page, in every locale, and writes a sitemap.

import { prerenderSite } from "nodality/ssg-site";

await prerenderSite({
origin: "https://example.com",
uploadDir: "upload",
pages: [
{ html: "index.html", entry: "pages/index.js" },
{ html: "about.html", entry: "pages/about.js" }
],
locales: ["en", "cs"],
defaultLocale: "en"
});

origin, uploadDir and pages are required, and every page needs both html and entry. Omit locales and it renders a single unlocalised pass.

Each locale runs in its own subprocess. That is deliberate: a page's module-level state – a cached translation table, a memoised layout – would otherwise leak from one locale's render into the next, and the second language would come out subtly wrong in ways that only show up in production.

Node caveat

The browser bundle touches window when it is imported, so require("nodality") throws in bare Node. The ssg entry points are built for a build script and install their own DOM; if you want to import the library itself outside a browser, provide a DOM first.