Start
Releases
Each release of ogygia, newest first.
On this page
- 0.8.6
- Fixed
- 0.8.5
- Changed
- Fixed
- 0.8.4
- Fixed
- 0.8.3
- Added
- Changed
- Fixed
- 0.8.2
- Changed
- Fixed
- 0.8.1
- Fixed
- 0.8.0
- Breaking changes
- Added
- Changed
- Fixed
- Internal
- 0.7.0
- Breaking changes
- Added
- Fixed
- Internal
- 0.6.6
- Fixed
- 0.6.5
- Removed
- Fixed
- 0.6.4
- Added
- Fixed
- 0.6.3
- Fixed
- 0.6.2
- Fixed
- 0.6.1
- Fixed
- 0.6.0
- Breaking changes
- Added
- Changed
- Fixed
- Security
- 0.5.1
- Fixed
- 0.5.0
- Breaking changes
- Added
- Changed
- Fixed
- 0.4.3
- Fixed
- 0.4.0
- Breaking changes
- Changed
- Removed
- 0.3.5
- Fixed
- 0.3.4
- Added
- Changed
- 0.3.3
- Changed
- 0.3.2
- Changed
- Fixed
- 0.3.1
- Fixed
- 0.3.0
- Changed
- Fixed
All notable changes to ogygia are documented in this file.
The format is based on Keep a Changelog. This project follows Semantic Versioning.
0.8.6
Fixed
- A hole created fresh in the browser (Kit remounting a page whose hydration failed, or an island re-creating a snippet) renders its fallback again, so an on-demand hole whose fallback is its trigger can still be woken (it came back empty in 0.8.5).
- A hole in a live snippet that an island re-creates fetches again by its identity on any page, not only on a Kit-hydrated one.
0.8.5
Changed
- An island inside a live snippet an island renders follows the nested rule: it renders inline and hydrates with that island.
- An island sets
data-hydratedand firesogygia:hydratedonce the live snippets it renders have hydrated too. - A hole nested in an island renders inline as static HTML, like a lake: its component never ships to the browser, and an island inside it wakes on its own.
Fixed
- A hole inside a live snippet an island renders stays deferred: it ships its fallback, loads on its schedule and is never bundled into the island (it never loaded before).
- A live snippet that renders a template-root snippet, or reads a
<script module>import or value, an exported declaration or a$:declaration, no longer throwsReferenceErrorat render. - A lake inside a live snippet an island renders keeps its frozen region, so the island inside it wakes and the lake’s HTML is no longer discarded beside other snippet content.
- A live snippet an island renders reads the page’s contexts on the server and in the browser, as the island does.
- An island inside a frozen snippet wakes on its own.
- A snippet passed to an island on a Kit-hydrated page no longer causes a hydration mismatch.
- A hole on a Kit-hydrated page keeps its address and its landed HTML through Kit’s hydration (a hole inside an island could go empty).
- With an app transform, a router navigation no longer leaves a web component’s server tree in the light DOM of a live host its own runtime already unpacked (a site nav collapsed to one unstyled item): a page the router fetches is rendered as an answer, every host restored before the swap.
- A first-load copy of a transformed page that reaches the router (a frozen page, a prerender, a cache that ignores
Vary) is loaded instead of swapped in; transformed documents vary onx-ogygia-spa. - A link inside a web component’s shadow tree honors the
data-sveltekit-reloadaround the component.
0.8.4
Fixed
- ogygia always uses the app’s SvelteKit: a second copy resolved from ogygia’s own location (a linked ogygia whose peer resolved another Kit) left the devtools’ server events, the freeze verdict and the page seed without their request.
- A hole’s answer morphed into a custom element with a shadow root keeps the answer’s order: a reordered or newly shown child no longer stays in or lands at the wrong place.
- A baked held region on a Kit-hydrated page no longer throws a hydration mismatch that emptied it: the region element is adopted as it stands, like a lake’s.
- Islands inside a baked held region on a Kit-hydrated page wake on the runtime instead of being left to Kit, which never hydrates them.
- Custom elements inside a baked held region keep what the server’s transform wrote (a closed dropdown no longer loses
hiddenand shifts the page).
0.8.3
Added
ogygia/testing:record(actions, { blockNavigation: true })holds back any document load the actions cause, keeps the page and lists each innavigationswith what started it, seen as it began (the link, form or input being handled;approxwhere the browser cannot say).ogygia/testing:compare()andtoMarkdown()also report hydration per island instance, session counts (errors, shifts, slow interactions, blocked navigations, CLS) and vitals past a noise threshold (compare(base, head, { noise })), and take several runs a side ({ test, runs }): load signals by median, session signals only when every head run has them and no base run does.ogygia/testing: eachhydration()island has akeyper instance (Name#nin page order, or theislandKeyattribute on it or its nearest ancestor, across shadow roots) and its wake times (t0,done); session findings carrynames; a session’scounts.clsis a number, andtoMeetBudget({ cls })reads it.ogygia/testing:playwrightDriver(page, { onNavigationHeld })andturnOnDevtools(page, baseURL), the fixture’s own pieces, for a test that holds its pages itself.ogygia/testing: every report names the page’s testing engine (engine.version,engine.lean); against a site on an older ogygia,record()fills innavigationsfrom the loads it held, and one warning per site is logged for the whole run.ogygia/testing: achangedisland says whether only attributes differ (attributesOnly, with each inattributes) and whether input landed on it while it hydrated (inputDuringHydration);ignoreAttributesleaves chosen attribute changes out, andtoHydrateCleanly({ allowAttributeChanges, allowInput })lets them through.ogygia/testing:page().selfsays what measuring cost the page (script_ms, the testing engine’sbytes), and lean testing (lean: true, theog_testing=leancookie) runs the testing API and nothing else of devtools, so the page loads what a visitor’s does.ogygia/testing:page().route(the SvelteKit route id),cpuFunctionsfor more than 15 ofpage().cpu.fns, and a session’sfailedrequests and slowest interaction per element (by_element).- Profiler:
record(…, { server: true })works across the instances of a serverless deployment: the window’s signed id rides each of the session’s requests, every instance writes them to the profiler store, and stop on any instance gathers them (window.instances); a window that fails leaves the session whole withserver: { error }. - Profiler: the JSON report names its
engine.version;?fields=(profile(path, { fields })) answers only the sections asked for;?weigh=fullweighs every file with no time budget, and each file it could not weigh says why (assets.missed_why). - A page with devtools switched on is sent
Document-Policy: js-profiling, so the browser’s CPU sampler can run on it.
Changed
OgygiaDriver.evaluateis loosely typed, so a driver’spage.evaluatefits without a cast.- A pkg.pr.new preview is versioned
<next patch>-next.<commit>, never the release it was built after.
Fixed
record()whose page left for another document now says so, with the actions’ own error ascause, instead of “serve with devtools”.withOgygiaturns devtools on for the first page a test opens when there is nobaseURL; before, it was silently left off.- A page with devtools switched on is sent
private, no-storewithVary: Cookieand is never frozen, so a shared cache cannot hand its events to other visitors; a profiler beacon page too. - A hole’s
Server-Timingreaches a browser that switched devtools on (it checked an old cookie value). - A profiler window whose stop never came frees its instance at its 60 s cap; before, that instance refused every later window.
- A file the profiler failed to weigh by a timeout is weighed again on the next profile; before, it stayed a miss for the life of the instance.
- Devtools’ Page and Timeline tabs, and
page(), stay on the page after a router navigation that never swapped it (handed to the browser and held back, or overtaken); before, they reported no islands. - On Windows, ogygia knows its own files again: builds no longer register its devtools and profiler components as app modules or warn that its own marks are ignored.
- The dev dependency scan no longer fails when the profiler is on, so dependencies pre-bundle again;
devalueis now named through ogygia, so pnpm apps stop warning that it can’t be resolved. - A click on a
load,idle,visibleor media island before it is live is no longer lost: the island wakes at once and the click is replayed when it is live, as on aninteractionisland;hydratedBy()then says'interaction'. - A Ctrl/Cmd/Shift- or middle-click on a link in an island that is not live yet opens the link as the browser would; before, it was canceled and replayed, and the replay could not open it.
0.8.2
Changed
- In a build with devtools, the launcher stays hidden until a browser turns devtools on (
?og-devtools=on, orogygia.devtools.on()in the console);?og-devtools=off,ogygia.devtools.off()or hide in the dock turn it off. The dev server is unchanged.
Fixed
- A hole’s CSS now carries components taken through a package (its
exports, a TypeScript entry included) or a barrel — only the names imported — and an island inside a hole brings its own CSS, so what it renders after a click is styled.
0.8.1
Fixed
handle({ endpoint })now moves every hole and live-region URL a page mints, not only the handler; before, every hole asked the old/__ogygia__path and stayed empty.
0.8.0
The passage release: the runtime and the compiler rebuilt on one identity primitive, regions that move instead of reset across navigations, a standalone compiler, a production SSR profiler, a devtools dock, a typed router, frozen pages and fragment federation. Underneath, one load scheduler, one DOM ownership model and one page model replace per-path rules.
Breaking changes
- Flags and experiments collapse onto one primitive,
flag();experiment,layer,allowOverrides,onExposure,batchExposures,.bucket,.onandroutes({ experiments })are removed. Declare with a shape (flag('x'),flag('x', 10),flag('x', fn),flag('x', { control: 80, bold: 20 })), read by calling it (checkout(c)), branch withflag.pick(map)/flag.pick(c, map), read payloads withflag.value(c), configure once withdecide({ source, overrides, exposure, batch }), and pre-decide in a route-only shell withroutes({ flags: [...] }). kitMountis nowmount.kit.ogygia/rewriteis nowogygia/markup(no alias; change the import).transformHoleis removed;ogygia.handle({ transform })covers region answers and documents alike.regionTtlis nowregions: { ttl }.regions.preloadis removed; each island’s whole graph preloads at its wake.
Added
- One load scheduler for every download ogygia starts: island code and background work wait for the page’s
fetchpriority="high"resources (or the first input, or a 2.5 s cap), so islands no longer compete with the hero image. - Holes and regions a remote
query/commandrenders see their page’spage.url, route, params and server-loadpage.data(looked up through Kit, only when read), so a server-rendered header can refresh in place (“A lake that can refresh”). - One DOM ownership model for every ogygia DOM writer — who writes inside an element, its attributes, its children’s order and their existence — so a web component’s own DOM survives repairs, hole answers and navigations.
- SvelteKit 3 support, on the APIs late Kit 2 and Kit 3 share.
- The SSR profiler,
ogygia({ profiler }): CPU, network, heap and the browser half of a visit, with a 0–100 page score and on-demand mode (profiler: { onDemand: true }). - Devtools,
ogygia({ devtools }): an island-graph dock with Page, Hydration, Record, Bytes and Profiler tabs, every vital explained down to the island and line responsible. ogygia/testing: the devtools and the profiler as test primitives.ogygia/router: Kit’s routing, programmatic and fully typed;document()renders a complete page from a handle.ogygia/internal/compiler: the compiler as a standalone, bundler-agnostic engine.- Frozen pages,
ogygia({ freeze: true }): a page renders once on write and is served as stored bytes until a publish thaws it (with edge stitching for per-visitor holes). - Fragment federation: one
federate(), a remote fragment is a region, and a publish thaws it everywhere. - The Ref hub: one identity layer for live classes, stores, functions, snippets and held regions that cross an island boundary.
- Transportable values: everything devalue rejects now crosses through one serialization seam; unbridgeable values fail at discovery, not in production.
- A navigation moves regions instead of resetting them (state-delta reconciler); opt-in server-delta navigation renders only what changed (
router: { serverDelta: true }). ogygia.handle({ transform }): server transforms that may reshape Svelte-owned markup, restored in the browser before hydration.ogygia/markupandscanRegions(html): the region round trip for an app that runs a third-party SSR pass over the page.- On-demand server islands:
render: 'deferred'+wake: 'interaction'fetch nothing until the visitor shows intent. prefetchwarms a deferred hole’s HTML before it swaps.keepFallback(): a server island’s answer that keeps the page’s fallback.requestEvent(): Kit’sRequestEventinside a server island.isOgygiaPage(): tells shared code which world it runs in.- A lake survives Kit hydration on a
csr = truepage. ogygia({ barrels }): barrel imports become leaf imports at transform time.- Zero-config library islands: a dependency declares its island roots in its own
package.json. - The app’s
hooks.client.tsinitruns oncsr = falsepages. - Server islands ship their component tree’s CSS; region CSS obeys Kit’s
inlineStyleThreshold. - Lazy islands download at background priority, so they never fight the first paint.
- Accessible SPA navigation (focus, announcements) and a reason on every page fetch.
when(): flags gate routes, andpickchooses infrastructure; OpenFeature interop (ogygia/flag/openfeature).- The build warns when island code reads a context nothing bridges.
- A recovered or healed island says why, and the discard warning names what Svelte threw.
- The ogygia MCP server grows to eleven tools, and the bundled AI skill is rewritten.
Changed
- A
<Region of={promise}>waits where the render can: awaited in the server render under Svelte’s async mode, streamed as a late region on the server router, or resolved after hydration otherwise. - Islands inside a region’s HTML always wake on the runtime,
csr = truepages included. - The page seed ships only when an island reads it, and only the
page.datakeys the page’s islands read. - The remote seed ships only for remotes an island on the page can call.
- Island props reference the page seed instead of copying it, and ride at the end of the body with the module-preload hints.
- Island hints are
fetchpriority="low"; island wakes start after the page has painted. - The boot never loads Svelte and is four files fetched in one round trip; the runtime goes right before the page’s own JavaScript.
- Duplicate stylesheet links are dropped.
- HTML is byte-identical across renders (window-aligned capability expiry, per-request slot ids).
- The server request path is one request store, one document pass and one walk, and stops allocating per item.
- A slow or hung page can no longer wedge the profiler or the site, and recordings coordinate across processes.
- The Vite plugin is a compiler, and region rendering is region-granular.
rolldownis no longer a dependency: the compiler parses and bundles through the app’s Vite, keeping its 16 MB native binary out of production installs.
Fixed
- Island entries on pages below the root no longer 404 in builds (Kit’s
asset()form comes from the build’s Kit version). - A region moved by another script keeps its in-flight fetch and its woken island.
- Restored shadow roots keep their sheets across a router navigation.
- A preloaded
loadhole stays out of the batch instead of downloading twice. - Region URLs are pinned to their page, there is one region per hole across path depths, and a navigated island arrives whole in one swap.
- A registry’s plain imports keep their CSS on
csr = falsepages; an island inside an island links its own CSS; held regions keep inline sheets. - A kept island adopts its server DOM instead of discarding it on every load.
- An island with children has the same fingerprint and bytes on every render.
- An island edited while it slept hydrates from its own server markup instead of re-rendering.
- A hole answer that is not the region’s (a redirect, a whole document) is refused.
- A deferred hole survives Kit rebuilding a client-on document, and outlives a CDN-cached document.
- A hole’s answer morphs over its fallback on every schedule, keeping a web component’s attributes and state, unfocused edited fields, and focus visible to assistive tech.
- Region and hole HTML is parsed aware of declarative shadow DOM.
- A lake with no island host survives Kit giving up on the document, and a lake’s island with props hydrates on a
csr = truepage. - An error page under a
csr = falsepage renders as the Kit-hydrated document it is. - A
csr = trueroute that imports a block registry no longer links every block’s CSS and chunk, and acsr = falsepage links only the island CSS it renders. - Island entries and the runtime are content-hashed, so a deploy never runs the last build’s island code.
- The runtime’s hash module is no longer named
fingerprint.js, which ad blockers blocked. - A
visibleisland’s code waits for the viewport, and a scroll-woken island no longer waits on the scheduler. - An island of ours on a Kit document waits until Kit has applied its page;
requestEvent()answers under Kit’s own render too. goto()from an island on a Kit-booted page navigates through Kit, and a script module reached through an app alias gets the island’s page.- The router keeps a destination page’s inline
<style>sheets, followsdata-sveltekit-reload’s grammar, navigates links inside web components in place, corrects the address bar after a server redirect, and keeps the live<body>on a fallback swap. - An unkeyed wrapper around an island survives a sibling inserted above it, and lakes restore by DOM position.
- A layout’s csr world derives from the pages it serves, and a
csr = truepage under acsr = falselayout keeps the layout’s chrome. kit.files.routes,kit.outDir,appDirandpaths.baseare honoured everywhere, and route walkers follow symlinks.- Island chunks are emitted only for islands the server bundle can reach.
- Region fingerprints no longer cost 20 ms per island; the profiler is free when it is not profiling.
$app/stores$pageworks inside every ogygia render root, and a server island’spage.urlis the referring page.- On a
csr = truepage a server island keeps its server-minted endpoint through Kit’s hydration, and server-island HTML is absolutized for nested paths. wake: 'interaction'replays the waking click on the next frame, into the deepest target.- A
wake: 'none'lake in a+layout.svelteships its scoped CSS, a lake’s or island’s scoped CSS keeps its Svelte hash, and the fouc-css fallback ships valid CSS. - An island inside a server island’s
ogygiaFallbackstays a region, andkeepFallback()from an inline-rendered server island fails with the reason. - A relative
with { wake }import inside a{#snippet}, a forwarded snippet opening with{@const}, and a raw<style lang="scss">no longer break or silently skip a component. - A portable snippet carries its host’s style scope, a branded snippet runs in place, and store auto-subscriptions in crossing snippets hoist as snapshots.
- An island’s
<svelte:head>survives a head other scripts edited, and an island’s page seed follows dynamic imports. - The compiler registers only wired transportable classes, and a byte-order-marked source is edited at the right offsets.
- Freeze: a root prefix clears shared stores, and tag sets keep their longest lifetime.
- Dev: CSS authored in holes, regions, islands and frozen snippets applies on first load.
- Dev: every island is a crawl root for Vite’s dep scanner, so nothing is discovered late on a cold server.
- Dev: an installed ogygia runs as one copy in the browser.
- Dev: a dep re-optimization no longer strands the islands on an open tab.
- Dev: server islands keep working after an HMR edit of their host file.
- Dev: toggling a route’s
csrexport refreshes the server’s route set. - Dev: the nested-island warning no longer crashes SSR.
- Devtools: the dock is styled in a build and under a CSP that refuses inline styles; a wait for a failing first-screen island is not blamed on ogygia.
- Profiler: a page that leaks never takes the server down.
- Profiler: page profiling survives serverless timeouts, and network capture is reliable.
- Profiler: its renders ask as a page navigation, so streamed pages profile as visitors get them.
- Profiler: login survives a large cookie jar, and the dev server runs one live profiler per process.
- Profiler: beacon visits over 64 KB are sent, one beacon per Kit page.
- Profiler: JSON and
.cpuprofilelinks download, a.ogpmoved between machines imports, and the UI ships TS-free templates.
Internal
- Full TypeScript
strictat the library level, withsvelte-checkin the library check and zero explicitany. - oxfmt is the workspace formatter.
- The per-host csr context cascade is one per-document signal (
documentIsCsrTrue()). - The on-demand-hole browser tests no longer depend on where the runner’s pointer rests, and the weekly upstream watcher gained a baseline leg.
0.7.0
Breaking changes
- Unified cross-island context:
<Context of={ctx} value={v}>andctx.get()are replaced by Svelte’s ownsetContext/getContext, bridged across islands.
Added
$page.data(withform,error,status) works inside islands oncsr = falsepages, streamed load promises included.- Drop-in
setContext: adopt cross-island context with an import swap. - A
.tsregistrywith { wake }binding is mountable. import.meta.og.asRegion(Comp, options): the barrel escape hatch for regions.
Fixed
- A
csr = falsesubtree under acsr = trueancestor layout islands correctly, also next to a commented-outcsrexport. - ogygia’s own injected imports resolve to ogygia’s own files, and its components compile under SSR when the app externalizes it.
- A plain function passed as an island prop errors as a function, not as a snippet.
- The runtime chunk URL busts on the feature set, not only on source.
region()recognizes awake:attach binding, andkeepsplits the region dedupe key.- Two lakes of the same component restore to the right boxes.
- A held-region import that is only text (a comment, a template literal) is left alone.
Internal
- One shared region-option parser, one emitter per region kind, and side-channel emits centralized.
0.6.6
Fixed
- A
{#snippet}forwarded into an island no longer emits duplicate imports.
0.6.5
Removed
- The profiler dashboard’s live-server recording mode.
Fixed
ogygia/profileris in the published export map.
0.6.4
Added
- Profiler:
×Ncall counts and a per-call column, waiting by function, per-caller network attribution, and a serverless dump / upload.
Fixed
- Profiler: native runtime frames are named instead of rendering as ”—“.
0.6.3
Fixed
- A
DocsShellsidebar no longer drowns its own page cross-fade.
0.6.2
Fixed
- A content body’s scoped
<style>no longer vanishes on acsr = falsepage. - A static server island no longer 404s a bare region id on navigation.
- A page transition between different shells no longer stutters.
0.6.1
Fixed
- Placed client-island CSS no longer vanishes in a production build.
0.6.0
Breaking changes
- Transportable codecs are declared with the
wiremacro (static [ogygia.wire] = …). - The Vite peer is
^7 || ^8(5 and 6 dropped). - Island facades are emitted as
og-region.<hash>.js. continuity.speculateis removed; SPA mode never emits speculation rules.
Added
- The config surface: one grammar per
ogygia()subsystem. - The site layer,
site()inogygia/content, with shells and bricks (Frame,DocsShell). - The
import.meta.og.*compile-macro family. - Region snippets,
region.snippet(): a snippet that crosses the island boundary. - Awaitable regions:
await region(Component, props)bakes the SSR HTML into the ticket. preference()/preference.switch(): site-wide, no-flash visitor preferences.- A Markdown authoring dialect with VitePress-compatible containers.
- MPA-mode native speculation rules with
router: false. - Dev guards: mutating a captured host snapshot inside an island warns.
ogygia/profiler: a drop-in SSR profiler.
Changed
- Schema layers merge instead of chaining.
- Preloading is render-gated end to end.
svelte/serverand the codec graph no longer reach the client.- Router prefetch also warms the incoming page’s island modules.
Fixed
- A directly used
<Region>on acsr = truepage renders inline in the Kit tree. - An island reading
$app/stores/$app/stateno longer bundles Kit’s real client store. - Dev soft-CSS HMR is scoped to the page’s own sub-app.
csr = falseapps no longer need a tokencsr = trueroute.folder()collections no longer come up empty on the dev server.- Childless islands no longer serialize a phantom
childrenslot. - Nested islands no longer compile in O(2^depth).
import.meta.og.code()in a.sveltehost is no longer discarded.- An interrupted navigation no longer logs an unhandled “Transition was skipped” rejection.
ogygia/content/slotresolves.- Shell reactivity and accessibility fixes (version switcher, element overrides, tab groups).
Security
- A dev-server path traversal in the FOUC CSS virtual is closed.
- The region batch endpoint rejects oversized bodies (413) before reading them.
- A full audit of the signed-capability pipeline.
0.5.1
Fixed
- Published
exportsresolve todist, notsrc. - The browser runtime no longer disappears to tree-shaking.
0.5.0
Breaking changes
- The SPA router is global; the
<Router/>component is removed. - Content
render()andrenderHtml()are replaced by the entry’sbody(a region) withget()+<Region>. OgygiaBoundaryis nowBoundary.ogygiaHandleis nowhandle, exported fromogygia/server(ogygia/hooksstays as an alias).- The default island endpoint is
/🏝️. - Presets speak the
render/wakegrammar. @ogygia/contentis merged into ogygia.
Added
- Live regions: LiveView over
query.live. - Streaming server islands (opt-in,
ogygia({ stream: true })). - Regions:
region(Component, props), a server-chosen renderable placed like data, with dual-face regions andogygia.transport. contentis part of ogygia (ogygia/content).- One config surface in
ogygia({ … }), and a namespace API (import * as ogygia from 'ogygia'). npx ogygia initwires a SvelteKit project in one step.- Async regions:
<Region of={promise}>owns the full wait. blocks.resolve(tree, registry)resolves a data tree to regions.- Per-hole browser cache,
maxAge. ogygia.script(): an inline<script>from one plain object.- The
Fallback<P>type for a deferred island’s fallback slot. ogygia/internal/compiler: the pure transform engine.- Zero-file all-
csr = falseapps.
Changed
- Deferred holes are dynamic by default (
Cache-Control: no-store). ogygia.preprocess()is synchronous.- Content sources are trimmed; the mdsvex source is
markdown(). - The island endpoint is matched independently of
paths.base.
Fixed
- Router back/forward swaps the page, and prefetched pages are used on click.
- The
$app/statepage snapshot reaches islands, and updates after SPA navigation in dev. - Lakes survive client hydration.
- Content-page islands build, and a standalone client build keeps SSR island registrations.
- Deferred regions hydrate on
csr = truepages. - Phantom modulepreload chunks are dropped.
- Island hydration adopts SSR roots in place (no “hero bounce” reflow).
- No FOUC on the first navigation after a deploy.
- Held-region CSS styles the page, in dev and on serverless adapters.
- A live command refresh with only refresh keys works.
- The morph keeps form state with a keyed diff.
0.4.3
Fixed
invalidateAllis a soft seed refresh, not a body swap and view transition.csr = falseFOUC CSS no longer double-owns island component JS, and client stubs keep the entry import that carries island CSS.
0.4.0
Breaking changes
- Portable island bindings: a marked import rewrites the binding itself to an island wrapper, so
<A />, dynamic components and{#each}lists of components work; host children on island call sites are a build error (exceptogygiaFallback).
Changed
- Dedupe is identity-based: the same component and options make one wrapper and one client entry, however many call sites.
csr = falseclient hosts no longer pull island wrappers into Kit’s client graph.- The plugin uses
build.rolldownOptionson Vite 8. - Props are real Svelte props into the wrapper, and
ogygiaFallbackis a normal snippet prop. - Lakes are portable wrappers too.
Removed
- The static-tag-only requirement, and the tag-hoist virtual modules.
0.3.5
Fixed
- Nested server and deferred-client islands keep their authored attributes.
0.3.4
Added
- Deferred client islands:
with { defer, hydrate }fetch signed HTML on one schedule and hydrate it on another (matching schedules coalesce).
Changed
defer+hydrateis no longer a build error;hydrate: 'none'+deferwarns in dev and is treated as defer-only.
0.3.3
Changed
hydrate: 'load'also modulepreloads the island’s dependency chunks.
0.3.2
Changed
- One runtime bootstrap per page, and
loadpreload hints hoisted to the head.
Fixed
- Relative island entries on nested routes resolve against the document, not the runtime module.
0.3.1
Fixed
- The client build no longer emits thin island entry facades.
0.3.0
Changed
- A hydrate island’s
entryis an importable module URL in production, and the runtime no longer embeds an app-wide regions map. - Each hydrate island is emitted at a deterministic
ogygia-island.<id>.js, and SSR renders the same virtual island module the client hydrates.
Fixed
- Dev:
asset()no longer rewrites Vite/@id/…URLs, and props stay the region’s immediate sibling. - SSR and the client share one virtual tree, ending hydration mismatches on captured props.