API
ogygia
The runtime surface — Region, region(), script, preference, transport, context.
On this page
- __tag_context
- createContext
- hydratedBy
- isRegion
- preference
- preload
- region
- script
- Context
- OgygiaBoundary
- Region
- ogygiaTransport
- Preference
- Preference.name
- Preference.values
- Preference.default
- Preference.attr
- Preference.head
- Preference.set
- Preference.get
- TransportCodec
- TransportCodec.encode
- TransportCodec.decode
- TransportCodec.id
- TransportCodec.merge
- AwaitableRegion
- DeferredRegion
- DualRegion
- Fallback
- InlineRegion
- PreferenceSpec
- RegionOptions
- RegionSchedule
- RegionValue
Auto-generated from the package’s own .d.ts on every build — signatures, JSDoc, and examples straight from the source.
import { … } from 'ogygia';Exports __tag_context · createContext · hydratedBy · isRegion · preference · preload · region · script · Context · OgygiaBoundary · Region · ogygiaTransport · Preference · TransportCodec · AwaitableRegion · DeferredRegion · DualRegion · Fallback · InlineRegion · PreferenceSpec · RegionOptions · RegionSchedule · RegionValue
__tag_context
function
Build-generated: bind a createContext() export to its stable module#export tag.
function __tag_context(tag: string, handle: unknown): void;createContext
function
Define a typed cross-island context. No string key — the build tags it by module#export, so
the provider and every consumer island agree on identity without a magic string.
// context.ts
export const cart = createContext<Cart>(); // get(): Cart | undefined
export const theme = createContext('light'); // get(): string (has a default)function createContext<T>(defaultValue: T): ContextHandle<T> & {
get(): T;
};
function createContext<T>(): ContextHandle<T>;hydratedBy
function
hydratedBy() — which schedule woke the hydration root this component is mounting under.
Call during component SETUP (like getContext): the runtime marks the region it is hydrating
(the same anchor cross-island context uses), and this reads that region's hydrate attribute.
Why you'd care: an interaction island's first event is a REPLAY — real interaction, but not a
trusted browser gesture (event.isTrusted === false), so gesture-gated APIs (window.open,
clipboard, fullscreen) will be blocked for it. A component that needs those can check hydratedBy() === 'interaction' and adapt (e.g. render the popup as a link the SECOND click
uses, or skip an entrance animation that assumes a fresh load).
Returns:
'load' | 'idle' | 'visible' | 'interaction'or a media-query string — the region's schedulenullon the server (SSR pass), and on csr=true pages where Kit (not ogygia) hydrates.
A nested island hydrates with its parent, so it reports the PARENT region's schedule — correct: that is the wake that ran its code.
function hydratedBy(): string | null;isRegion
function
True for any value produced by region (or decoded from the wire).
function isRegion(value: unknown): value is RegionValue;preference
function
const preference: typeof preference_impl & {
switch: typeof preference_switch;
}preload
function
function preload(region: unknown): void;region
function
Make a held region with type-checked props.
- A plain component import → an inline region (renders in this pass; can't cross the wire).
- A component imported
with { region: 'raw' }→ a dual region: inline where it's made, a signed ticket where it travels. Minting the marked form is server-only (the signer lives on the SSR leg) — call it in a load / remote / render context.
A dual region is awaitable. await region(Card, props) renders the component to HTML on
the server and bakes it into the ticket, so the client swaps it in with no extra request. In an
async generator (query.live) or an async remote, yield region(…) / return region(…) is
awaited by the language, so the HTML travels automatically — LiveView over the channel you already
have. A held region you don't await renders inline where it lands (first paint, same SSR pass).
function region<C extends Component<never>>(component: C, props: ComponentProps<C>, opts?: RegionSchedule<ComponentProps<C>>,
content_id?: string): AwaitableRegion;script
function
Serialize a self-contained function into a blocking inline <script> string.
csr=false apps routinely need a tiny script that runs BEFORE hydration and first paint — set the
theme so there's no dark-mode flash, kick off a deferred font, read an early flag. A normal client
import can't do it (islands hydrate later), so you hand-roll a <script> string — and a literal </script> inside a Svelte component prematurely closes the component's own script, which is why
people resort to String.fromCharCode(60) tricks. This removes all of that: pass a function, get
back a <script>…</script> string, and {@html} it wherever you want the tag to land — usually <svelte:head>, but it's just a string, so it's up to you.
The function is inlined via Function.prototype.toString, so it must be self-contained — only
browser globals, no imports and no closed-over variables (they won't exist at runtime). For values
you would otherwise close over (a hashed asset URL, a config flag), pass them as trailing args;
they are JSON-serialized and handed to the function as parameters.
function script<A extends unknown[]>(fn: (...args: A) => void, ...args: A): string;fn— A self-contained function run synchronously, before paint.args— Serializable values (string/number/boolean/null/plain JSON) passed tofnin order.
Returns A <script>…</script> string to {@html} wherever you want the tag.
No-flash theme (no args)
<svelte:head>
{@html script(() => {
try {
var t = localStorage.getItem('theme');
if (t === 'light' || t === 'dark') document.documentElement.setAttribute('data-theme', t);
} catch (e) {}
})}
</svelte:head>Deferred font loader (a URL passed as an arg)
<svelte:head>
{@html script((href) => {
addEventListener('load', () => {
var l = document.createElement('link'); l.rel = 'stylesheet'; l.href = href;
document.head.appendChild(l);
}, { once: true });
}, fontUrl)}
</svelte:head>Context
component
import Context from 'ogygia';OgygiaBoundary
component
import OgygiaBoundary from 'ogygia';Region
component
import Region from 'ogygia';ogygiaTransport
const
const ogygiaTransport: {
Region: {
encode(value: unknown): false | EncodedRegion;
decode(raw: EncodedRegion): {
html?: string;
hydrateMargin?: string;
hydrate?: string;
[REGION_BRAND]: boolean;
kind: "deferred";
id: string;
props: Record<string, unknown>;
url: string;
module: string;
};
};
}Preference
interface
A live preference handle — SSR head(), client get()/set(), and the attr CSS authors target.
interface Preference {/*…*/}Preference.name
readonly name: string;Preference.values
readonly values: readonly string[];Preference.default
readonly default: string;Preference.attr
The attribute set on <html>: data-pref-<name>. CSS targets :root[<attr>="<value>"].
readonly attr: string;Preference.head
No-flash inline <script> string — reads localStorage and applies the attr before paint. {@html} it once in <svelte:head>. Idempotent, so emitting it more than once is harmless.
head(): string;Preference.set
CLIENT: persist + apply a new value (wire a control's handler to this). No-op on the server.
set(value: string): void;Preference.get
CLIENT: the current value (from the applied attr), or the default. Returns the default on the server.
get(): string;TransportCodec
interface
The codec import.meta.og.wire({ … }) carries (or a static method returning it).
interface TransportCodec<T = unknown, D = unknown> {/*…*/}TransportCodec.encode
Sending side: turn the live instance into devalue-safe data.
encode: (value: T) => D;TransportCodec.decode
Receiving side: rebuild a live instance from that data.
decode: (data: D) => T;TransportCodec.id
CONTINUITY — a stable session name. Naming the codec promotes the instance from page lifetime to SESSION lifetime: it becomes a singleton in this browser tab, and a navigation reunites the next page's decode with the SAME live instance instead of rebuilding it. Tab- scoped only — the server stays per-request (never remembers), a reload starts fresh.
id?: string;TransportCodec.merge
Reconcile a navigation: the tab already holds the live named instance and the new page's
server snapshot just arrived (decoded as fresh). Apply whatever should carry over INTO live — its identity is preserved; fresh is discarded afterwards. Default: do nothing
(live wins — continuity is the point; a cart mid-edit beats a server re-read). Override to
pull server truth in (prices, stock, auth state).
merge?: (live: T, fresh: T) => void;AwaitableRegion
type
What region returns: a RegionValue you can render right now with <Region of={…} />,
AND a PromiseLike<Region> you can await to bake its server-rendered HTML into the ticket. In an
async generator (query.live) or async remote, yield / return awaits it for you.
type AwaitableRegion = RegionValue & PromiseLike<RegionValue>;DeferredRegion
type
A held region that arrived over the wire: a signed capability, no component.
type DeferredRegion = {
readonly [REGION_BRAND]: true;
readonly kind: 'deferred';
readonly id: string;
readonly props: Record<string, unknown>;
readonly url: string;
readonly module: string;
readonly hydrate?: string;
readonly hydrateMargin?: string;
readonly html?: string;
};DualRegion
type
A marked component: renders inline here, or becomes a signed ticket when it crosses the wire.
type DualRegion = {
readonly [REGION_BRAND]: true;
readonly kind: 'dual';
readonly component: AnyComponent;
readonly props: Record<string, unknown>;
readonly id: string;
readonly module: string;
readonly hydrate?: string;
readonly hydrateMargin?: string;
readonly sign: (id: string, props: Record<string, unknown>) => string;
readonly renderHtml?: (props: Record<string, unknown>) => string | Promise<string>;
readonly html?: string;
};Fallback
type
type Fallback<P = unknown> = P & {
ogygiaFallback?: import('svelte').Snippet;
};InlineRegion
type
A plain component. Renders in the current server pass; awaiting it bakes its SSR HTML so it can cross the wire as an HTML-only ticket (no chunk, no signer — nothing to fetch).
type InlineRegion = {
readonly [REGION_BRAND]: true;
readonly kind: 'inline';
readonly component: AnyComponent;
readonly props: Record<string, unknown>;
readonly html?: string;
readonly content_id?: string;
};PreferenceSpec
type
A preference declaration: its name, allowed values, and default (which must be one of the values).
type PreferenceSpec = {
name: string;
values: readonly string[];
default: string;
};RegionOptions
type
Schedule options for a held region. wake = when its JS runs; margin = IntersectionObserver
rootMargin for wake: 'visible'. Merged OVER the binding's baked schedule (from a wake: mark) —
anything set here WINS; a region: 'raw' binding bakes nothing, so this is the whole schedule.
type RegionOptions = {
wake?: string;
margin?: string;
};RegionSchedule
type
The region() schedule argument: a function handed the component's own props (its "generated
data") that returns the schedule. Always a function, never a bare object — the object case is the
baked wake: mark on the import. The function is for a registry of region: 'raw' components that
decides each one's timing from its data — e.g. region(block, data, (d) => ({ wake: d.interactive ? 'load' : undefined })).
type RegionSchedule<P = Record<string, unknown>> = (data: P) => RegionOptions;RegionValue
type
type RegionValue = InlineRegion | DualRegion | DeferredRegion;