Minimal & Fast
Complete HTML from the server. No React runtime, no hydration waterfall — only the bytes a content page needs.
The journey of a request
No black box. Every step is readable, replaceable and understandable on its own.
Express 5 handles security headers, redirects and static files in a fixed order. The flow is visible and documented — there is no hidden magic.
On a hit the ready page returns instantly. If the TTL has expired the visitor still waits for nothing: the current HTML ships and the refresh starts behind it.
A plain async controller returns the view, the data and the metadata. Easy to read, with none of the framework ceremony.
EJS turns the body and the layout into complete HTML. Small function components can be reused on pages and inside fragments alike.
The browser downloads the module for the visible island and attaches its behaviour. Even if JavaScript never arrives, the content stays readable.
The island contract
The server completes the view. An island adds a small layer of behaviour. Even on a broken connection, the content stays in place.
<div
data-island="pricing-calculator"
data-island-props='{"currency":"USD"}'
>
<!-- the pricing table HTML came from the server -->
<table data-seats-table>...</table>
</div>
import { on, qs } from "jskelet/client";
export function mount(element, props) {
const input = qs(element, "[data-seats]");
return on(input, "input", () => {
// The table markup came from the server;
// the island only updates the number.
paint(element, Number(input.value), props.currency);
});
}
The payoff
Complete HTML from the server. No React runtime, no hydration waterfall — only the bytes a content page needs.
A menu, a counter or a chart lives in its own island. Its module downloads only when it becomes visible.
Plain async controllers, EJS templates and a small API. Readable without ceremony, replaceable without drama.