Universal rendering

The browser, server, hydration, streaming, and static entry points share the same public template and component model. Request-local Router, Store, application, and effect ownership prevents cross-request state reuse.

Render safe HTML and state

ts
import { html } from '@gluonjs/core';
import { renderToString, serializeSsrState } from '@gluonjs/ssr';

const state = { route: '/products/orbit-lamp', bag: [] };
const rendered = await renderToString(html`<main><h1>Orbit Lamp</h1></main>`);

export const responseBody = `<!doctype html>
<main id="app">${rendered}</main>
<script type="application/json" data-gluon-state>${serializeSsrState(state)}</script>`;

renderToString() escapes ordinary child and attribute values. State transport accepts finite JSON values and escapes HTML-significant characters. Dynamic raw HTML and unsafe URLs require visibly unsafe APIs and reviewed inputs.

Hydration and static output

The server emits deterministic hydration markers and validated style carriers. The browser restores Router and Store snapshots before hydrateApplication(). Static generation prerenders explicit public URLs and records dynamic fallbacks without forking application modules.

Read the hydration guide and deployment guide for the complete handoff.