Vector Template Engine

The Vector Template Engine is the heart of InertJS. It parses tagged template literals and compiles them dynamically. Since it runs natively in Node.js, there is no build step.

The Anatomy of a View

Every page requires two exports: flux() for server-side logic and data fetching, and render() for generating the HTML.

import { vec } from 'inertjs-vector'; // 1. Fetch data on the server export async function flux() { const name = 'John Doe'; return { name }; } // 2. Render the template export function render({ data }) { return vec` <div class="container"> <h1>Hello, ${data.name}</h1> </div> `; }

Out-of-order Streaming

Vector's superpower is "Flash Mode". If your flux() function takes a long time (e.g., fetching from a slow database), Vector immediately sends the HTML skeleton to the browser, and injects the dynamic data directly into the DOM as soon as the promise resolves!

Deferred Fragments & Error Boundaries

Interpolate a Promise (or async iterable) directly and Vector opens a streaming slot for it. Wrap it in defer() to attach a skeleton and a per-fragment error boundary:

import { vec, defer } from 'inertjs-vector'; export function render({ params }) { return vec` <section> ${defer(() => loadReviews(params.id), { fallback: vec`<div class="skeleton"></div>`, error: (err) => vec`<p class="err">Reviews are unavailable.</p>` })} </section> `; }

By the time a fragment settles, the shell — and the HTTP status line — are already on the wire, so a rejection cannot retroactively become a 500. Instead InertJS isolates the failure to that one slot and keeps every sibling fragment streaming. Concretely, a rejected fragment:

  • patches its slot with the error boundary (or empties the skeleton) — a failed fragment never leaves a spinner hanging;
  • fires inert:fragment:error on window and increments window.__inert.fragmentErrors;
  • invokes the server-side onError hook for logging and telemetry.
// Server: observe post-flush fragment failures import { renderToStream } from 'inertjs-vector/src/stream.js'; renderToStream(view, nonce, { onError(err, { slot }) { logger.warn(`fragment ${slot} failed`, err); } }); // Client: react to a fragment that errored window.addEventListener('inert:fragment:error', (e) => { toast(`Section ${e.detail.slot} could not load`); });

Trusted content

fallback and error markup is treated as trusted HTML, just like raw(). Route any untrusted value (including err.message) through vec`` first — as the example above does.

🚀 Currently in Public Beta (v1.0.0-beta.4) - Help us improve by reporting issues on GitHub.