Skip to content

The Architecture: A Deep Dive into Instant Rendering

Welcome to the engine room.

This documentation is not a step-by-step tutorial, but an analysis of the architecture that allows this application to achieve near-instant loading performance on page reloads, even on throttled 3G networks.

The fundamental principle is simple, but its implementation is a precise choreography between three actors: the Build Process, the Service Worker (SW), and the Server (Nitro v2) (yes, I've created a JS backend for you, although my personal preference is Kotlin).

The Contract: site.json

The cornerstone of the system is a site.json file generated during the build process. This file is the "contract" that all actors understand and respect. Instead of calculating offsets at runtime, the build process analyzes the static HTML files and pre-calculates the exact byte offsets for each "slice" of the page.

Example site.json (simplified):

json
{
  "pages": {
    "/": {
      "link": "<...>; rel=preload; as=script...",
      "critical": { "start": 0, "end": 34567 },
      "head": { "start": 34621, "end": 65432 }
    }
  }
}

This manifest gives the server the precise information to read file chunks without loading them entirely into memory. The build also generates Gzip and Brotli compressed variants of the HTML files. The site.json contains only the byte offsets for the original, uncompressed HTML; the Nitro backend will handle serving the correct compressed file using the Content-Encoding and Vary headers based on the Accept-Encoding of the incoming request. The uncompressed HTML is only served on the first visit (before the SW is active) and when the SW itself precaches its assets.

The Rendering Flow (SW Active)

When a user with an active Service Worker reloads the page, the following sequence occurs:

  1. The Request: The browser requests a page.
  2. The Interception: The streaming-sw.ts catches the navigation request.
  3. Parallel Tasks: The SW fires two promises simultaneously using Promise.allSettled:
    • Load the HTML "shell" (without data) from its local cache.
    • Fetch the JSON state from a /state-api endpoint on the network.
  4. The Assembly: The SW analyzes the results. If the API call is successful and returns JSON, it "stitches" that JSON into the HTML stream it's serving from the cache. If the API call fails or returns a redirect, it serves that server response directly, always respecting its authority.

The Counterpart: The Nitro Backend

The backend is designed to be the perfect dance partner for this SW. Its two key responsibilities are:

  1. Serve Full HTML (SSR Fallback): For a user's first visit, the server serves the complete page with the state injected. For bots or for the SW precache, it serves the same page but without state.
  2. Serve JSON Only: When it receives a request with the X-APP-STATE header (sent by the Service Worker), the same endpoint serves only the data in JSON format via the /state-api.

The streaming logic in Nitro uses a single file descriptor (fs.promises.open) to read the HTML slices based on the offsets from site.json, ensuring maximum efficiency.

Released under the MIT License.