Skip to content

The journey of a request

From the server to the screen, five clear stops.

No black box. Every step is readable, replaceable and understandable on its own.

  1. The request comes in

    Express 5 handles security headers, redirects and static files in a fixed order. The flow is visible and documented — there is no hidden magic.

  2. Warm HTML is looked up

    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.

  3. Data is gathered in one place

    A plain async controller returns the view, the data and the metadata. Easy to read, with none of the framework ceremony.

  4. The page is assembled

    EJS turns the body and the layout into complete HTML. Small function components can be reused on pages and inside fragments alike.

  5. Only the needed part comes alive

    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

Bring the piece that needs it to life, not the whole page.

The server completes the view. An island adds a small layer of behaviour. Even on a broken connection, the content stays in place.

  • The default strategy is visibility: the observer starts loading 200px early.
  • One attribute makes an island eager for global behaviour, another defers it until the browser is idle.
  • Props travel as JSON in the markup, so server data is never fetched twice.
  • A mount function may return a cleanup function.
views/pages/pricing.ejs
<div
  data-island="pricing-calculator"
  data-island-props='{"currency":"USD"}'
>
  <!-- the pricing table HTML came from the server -->
  <table data-seats-table>...</table>
</div>
client/islands/pricing-calculator.js
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

What these three decisions buy you

Minimal & Fast

Complete HTML from the server. No React runtime, no hydration waterfall — only the bytes a content page needs.

Modular

A menu, a counter or a chart lives in its own island. Its module downloads only when it becomes visible.

Developer First

Plain async controllers, EJS templates and a small API. Readable without ceremony, replaceable without drama.