API
ogygia
The runtime surface — Region, region(), script, preference, transport, context.
On this page
- __tag_context
- createContext
- getContext
- hydratedBy
- isOgygiaPage
- isRegion
- keepFallback
- og_derived
- preference
- preload
- region
- requestEvent
- script
- setContext
- OgygiaBoundary
- Provide
- Region
- SharedState
- SharedState.current
- SharedState.current
- 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 · getContext · hydratedBy · isOgygiaPage · isRegion · keepFallback · og_derived · preference · preload · region · requestEvent · script · setContext · OgygiaBoundary · Provide · Region · SharedState · Preference · TransportCodec · AwaitableRegion · DeferredRegion · DualRegion · Fallback · InlineRegion · PreferenceSpec · RegionOptions · RegionSchedule · RegionValue
__tag_context
function
Kept for ABI: the build still emits a registration call for each createContext(...) export (that
used to tag keyless handles by module#export). Keys are explicit now, so this is a no-op.
function __tag_context(): void;createContext
function
Typed sugar over a string context key, shared with plain getContext. Callable to produce a <Provide> entry, .get() to read (typed). The key is the same string plain getContext uses, so
typed and untyped code read the same context. An optional default is returned when nothing is
provided above.
export const theme = createContext<'light' | 'dark'>('theme', 'light');
// provide: <Provide values={[ theme('dark') ]}>…</Provide>
// read: theme.get() // typed
// getContext('theme') // untyped — same key, same valuefunction createContext<T>(key: string, defaultValue?: T): Context<T>;getContext
function
Retrieves the context that belongs to the closest parent component with the specified key.
Must be called during component initialisation.
createContext is a type-safe alternative.
function getContext<T>(key: any): 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: when a visitor's input woke the island, its 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, and a guard that ignores untrusted
clicks ignores 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:
'interaction'when a visitor's input woke it — aninteractionisland, and a scheduled one pressed before its schedule made it live (its click is replayed too)- else
'load' | 'idle' | 'visible'or a media-query string — the region's schedule nullon 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;isOgygiaPage
function
PUBLIC: is the current page an ogygia page (csr=false), as opposed to a csr=true page Kit hydrates
whole? The inverse of documentIsCsrTrue, so it answers on BOTH legs with no requestEvent
handling on the caller's side — server reads the request's route against the build-time csr set,
client reads Kit's bootstrap. Meant for shared code (a store, a helper) that must branch on which
world it runs in. Off-request on the server (a module init, a prerender helper with no page) there
is no document to speak of, so it returns false.
function isOgygiaPage(): boolean;isRegion
function
True for any value produced by region (or decoded from the wire).
function isRegion(value: unknown): value is RegionValue;keepFallback
function
End this server island's render: the page's fallback is the right content for this visitor. Called from a server island rendering INLINE (nested in an island — the deferred mark is ignored there), the signal would escape to Kit's error page: fail with the reason instead.
function keepFallback(): never;og_derived
function
A derived that CROSSES boundaries ALIVE — resumability for the reactive graph.
Svelte's derived is a live computation: sources + a formula. The value can serialize; the
computation can't — so a plain derived crosses as a FROZEN seed (the classifier warns). This
primitive remembers its RECIPE, and the recipe is made of exactly the two things the seam
already carries: sources are STORES (they reunify to one live instance per island page) and
the formula is a FUNCTION (mark it with import.meta.og.$ so it travels as a fn ref).
const doubled = og_derived(tally, import.meta.og.$((n) => n * 2));Locally it IS svelte/store's derived — same laziness, same semantics. At a boundary the
derived kind ships { sources, formula, seed }; the island decodes by re-deriving against
the REUNIFIED sources with the REBOUND formula: bump the source in any island and every
island's derived follows. The seed rides along only for exactness of the first paint.
An UNMARKED formula still works same-tree, but the derived then can't cross (the fn ref can't be built) — the boundary explains this at the seam rather than freezing silently.
function og_derived<T>(sources: AnyStore | AnyStore[], fn: (...vals: never[]) => T, initial?: T): {
subscribe: (run: (v: T) => void) => () => void;
};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<P extends Record<string, unknown>>(component: Component<P>, props: P, opts?: RegionSchedule<P>,
content_id?: string): AwaitableRegion;requestEvent
function
function requestEvent<E = unknown>(): E | null;script
function
An inline <script> tag. Pass a function and its args (shortcut for { run: fn, args }) or one
options object; see
the module doc. Throws on an object with no payload or more than one, and on an attribute name
that is not one.
function script<A extends unknown[]>(run: (...args: A) => unknown, ...args: ScriptArgs<A>): string;
function script<A extends unknown[]>(options: ClassicScript<A> | ModuleScript<A>): string;
function script<I extends Record<string, string>, A extends unknown[] = []>(options: ModuleImportsScript<I, A>): string;
function script(options: JsonScript | LdScript | ImportMapScript | SpeculationScript): string;setContext
function
Drop-in setContext — swap import { setContext } from 'svelte' for from 'ogygia' and an
existing csr=false layout's context reaches child islands with NO other change.
It does exactly what Svelte's does (sets context for same-root descendants + the SSR-nested tree),
AND on the server records the value so the handle can emit one page-level marker every island seeds
from — closing the gap where a plain setContext shows up on the server but is gone on the client
(child islands are separate hydration roots). Only string keys bridge (they must serialize and be
read by getContext('key')); a symbol key is Svelte-only, same-root, no bridge.
GRANULARITY: the optional third argument is the explicit marker — { islands: false } keeps a key
host-native (same-root context works, nothing serializes). The default bridges: a missing key in an
island is a broken app, extra bytes are not. Ogygia never infers readership from getContext call
sites (aliased imports and wrapper modules would make any scan miss reads — the fatal direction).
This is the FLAT page root: every island on the page inherits it. For scoped/shadowed context use <Provide>, which wraps its subtree and beats the root on the same key.
function setContext<T>(key: unknown, value: T, opts?: SetContextOptions): T;OgygiaBoundary
component
import OgygiaBoundary from 'ogygia';Provide
component
import Provide from 'ogygia';Region
component
import Region from 'ogygia';SharedState
class
class SharedState<T extends object> {/*…*/}SharedState.current
The value — reactive wherever Svelte is watching, plain everywhere else.
get current(): T;SharedState.current
The value — reactive wherever Svelte is watching, plain everywhere else.
set current(v: T);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;