The same 3-page hiking-trail guide, built six times — identical content, identical visual design, identical four features (routing/transitions, a reusable trail card, shared state, a validated form with drag-to-reorder) — to compare what a framework actually buys you against doing it with nothing but the browser.
Real separate .html files, full page loads. localStorage + the storage event for shared state. A Web Component for the trail card. Zero dependencies, zero build step.
One index.html shell. A ~20-line History API router with native View Transitions, the same Web Component, an in-memory pub/sub store persisted to localStorage.
The same vanilla JS/CSS layer, served through a minimal Rust (Axum) server with a {{HEADER}}/{{CONTENT}}/{{FOOTER}} templating engine + page front matter, real server-rendered content, and generated sitemap.xml/robots.txt/llms.txt.
Vite + React Router (data router) + Context/useReducer. NavLink's viewTransition prop drives the native View Transitions API; aria-current comes for free.
Vite + Vue Router + Pinia. Vue's own <Transition> handles page transitions instead of the native API — the framework's idiomatic mechanism.
Angular CLI (standalone components) + Router + a signals-based injectable service. withViewTransitions() wires the router straight into the native API.