Expand description
View Transitions API + lazy navigation (issue #547).
Opt-in via transitions = true in ssg.toml. When enabled, the
plugin:
- Writes
_transitions/ssg-transitions.jsto the site dir — a tiny (~3 KB) client script that:- Intercepts same-origin
<a>clicks - Fetches the next page, swaps its
<main>content - Wraps the swap in
document.startViewTransition(...)where supported (Chromium + Safari 18+ as of 2026-06) - Falls back to the browser’s default full-reload navigation in non-supporting browsers (Firefox stable as of 2026-06)
- Skips cross-origin links, modified clicks
(
ctrl/cmd/shift/alt), non-GETtargets and any link that opts out viadata-no-transitionortarget="_blank"
- Intercepts same-origin
- Injects a
<script type="module" defer>tag and a tiny<style>block that namesheaderandfooteras persistent transition roots (so they don’t animate across navigations — AC6). - Dispatches a
ssg:after-swapCustomEventafter each swap so the islands loader (and any other listener) can re-hydrate components on the new page.
§Architecture
Builds on:
<ssg-island>(crate::plugins::islands) — exposesconnectedCallback/disconnectedCallback, so swapping<main>detaches old islands’ listeners cleanly (AC5).LiveReloadPlugin(crate::server::livereload) — in dev mode, the reload handler is upgraded to wraplocation.reload()instartViewTransition()when structural changes occur (AC7).
§Bundle size budget
The injected script must stay ≤ 5 KB uncompressed. Verified by a unit test in this file.
Structs§
- View
Transitions Plugin - Plugin that injects the View Transitions API client + style hooks.
Constants§
- VIEW_
TRANSITIONS_ JS - The injected client script. Kept ≤ 5 KB — verified by a unit test.