Skip to content

API

ogygia

The runtime surface — Region, region(), script, preference, transport, context.

On this page

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 value
function 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 — an interaction island, 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
  • null on 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;