A modern re-creation of YouTube's
SPF ("Structured Page Fragments") — a
lightweight, zero-dependency, framework-agnostic library for fast same-origin
navigation: clicking an spf-link fetches only the fragments that change
(JSON), never the whole page. Built on 2026 browser technology — the
Navigation API (Baseline January 2026), view transitions, streaming
responses, speculation rules, ES modules and the Cache API. Evergreen
browsers only, no polyfills.
- A browser with the Navigation API — latest + 1–2 of Chrome/Edge/Firefox/Safari
- Zero runtime dependencies, zero polyfills
npm install @imsus/modern-spfScript tag (IIFE build, global spf):
<script src="node_modules/modern-spf/dist/index.iife.js"></script>
<a class="spf-link" href="/destination">Go!</a>
<script>
spf.init();
</script>ES module:
import { init, navigate } from '@imsus/modern-spf';
init();
navigate('/destination');The server detects the SPF URL identifier (?spf=navigate, configurable) and
responds with either a single JSON object or an NDJSON stream of
parts (see the wire protocol). The client swaps only the
changed fragments into the page:
click .spf-link
→ spfclick → spfrequest
→ cache lookup → fetch (single JSON or NDJSON stream)
→ spfprocess → apply: title → url → head → attr → body → foot
→ spfdone
Every step is cancellable and observable through Promise-aware spf* events
(spfrequest, spfprocess, spfdone, spfpartprocess, spfpartdone, …):
spf.event.on('spfdone', ({ url, transitioned }) => {
console.log('navigated to', url, 'transitioned:', transitioned);
});Back/forward navigations to visited SPF pages are restored from cache —
an in-memory LRU plus the Cache API durable tier — with no network request.
View transitions wrap the swap by default (prefers-reduced-motion and
spf-no-transition respected), and failures fall back to a full browser
navigation (spferror/spfreload).
- Fragment-only navigation —
spf.init/navigate/load/process/prefetch, concept-compatible with SPF - Streaming — NDJSON parts, processed event-wise as they arrive
- Hybrid response cache — in-memory LRU + Cache API; new/history eligibility split
- ESM-native resources —
spf.script(import-map driven) andspf.style(constructable stylesheets) - Prefetch —
spf.prefetch, in-viewport observation, speculation rules (prefetch/prerender) - View transitions — default-on, reduced-motion aware, per-link opt-out
The wire contract is language-agnostic: ?spf=navigate|prefetch|load plus
Accept: application/x-spf+json, application/x-spf+ndjson;q=0.9. See
docs/protocol.md for the request/response shapes,
streaming parts, caching hints and failure semantics. Working implementations
ship with the repo as demos.
- Docs site — https://imsus.github.io/modern-spfjs/ (Vitepress: guides + hand-maintained API reference)
docs/protocol.md— the wire protocoldocs/design.md— the agreed design (shared-understanding record)docs/adr/— architecture decision recordsdocs/glossary.md— the domain glossary
| Demo | Stack | What it shows |
|---|---|---|
demo/hono |
Hono (Node), TS run natively | Full feature tour: navigation, streaming, caching, resources, prefetch, transitions, events, forms, failure fallbacks |
demo/laravel |
Laravel (PHP) | Single JSON + NDJSON streaming responses, spf-link views |
The project uses the Vite+ toolchain (vp) with pnpm and
TypeScript 7 (the native compiler):
pnpm install
pnpm check # vp check — format + lint + typecheck
pnpm test # unit tests (Vitest)
pnpm test:e2e # Playwright E2E (8 specs)
pnpm build # vp pack — ESM + CJS + IIFE (global `spf`) + .d.ts via TS7
pnpm docs:dev # vitepress dev server
pnpm check:publish # build + publint + arethetypeswrong (packaged-output checks)CI runs check, unit tests, the library and docs builds, publish checks and
the Playwright suite on every push; semantic-release publishes on main when
conventional commits land.
A modern re-creation of SPFJS ("Structured Page Fragments"), originally built by YouTube and open-sourced by Google:
The ?spf= identifier, JSON field names, spf* event names and the
spf-link class are inherited from the original for concept compatibility
(see ADR 0001).
MIT — see LICENSE.