API
ogygia/content
Collections, sources, the site layer, shells.
On this page
- blocks
- build_docs
- content
- create_search
- date_of
- dated
- defineSource
- dimensions
- enrich
- folder
- get_shell_context
- glob
- href_of
- is_dimensioned
- json
- links
- mapRaw
- markdown
- mountBase
- numbered
- orama_engine
- order_of
- outline
- parseSchema
- pick
- roving
- search
- site
- split_sections
- strip_order_prefix
- strip_prose
- title_case
- toRawSource
- BlogList
- BlogPost
- BlogShell
- BottomBar
- CodeChrome
- Doc
- Frame
- Link
- OnThisPage
- Pager
- Search
- SearchPage
- Sheet
- Sidebar
- SiteSlot
- Tab
- TabGroup
- ThemeToggle
- fields
- ContentHandle
- ContentHandle.refs
- ContentHandle.get
- ContentHandle.groups
- Convention
- Convention.segment
- Convention.label
- Convention.verify
- Dimensioned
- Dimensioned.axes
- Dimensioned.tree
- Dimensioned.coordinateOf
- Dimensioned.canonicalAddresses
- Dimensioned.switcher
- Dimensioned.fallbackOf
- Outline
- Outline.tree
- Outline.resolve
- Outline.addresses
- Outline.neighbors
- Outline.slug_for
- Outline.alias
- Outline.aliases
- RovingOptions
- RovingOptions.selector
- RovingOptions.orientation
- RovingOptions.loop
- Site
- Site.outline
- Site.data
- Site.components
- Site.load
- Site.entries
- Site.nav
- Site.switcher
- Site.meta
- Site.page
- Site.check
- Site.search
- Site.emit
- WithRemotes
- WithRemotes.refs
- WithRemotes.get
- WithRemotes.list
- WithRemotes.live
- Axis
- BaseOption
- BlockNode
- BlockRegistry
- BlockSchedule
- BlockSource
- BlogPostRef
- ChangeFields
- Check
- CheckContext
- Collection
- ContentEntry
- ContentMode
- ContentOptions
- ContentRef
- ContentRelations
- Coordinate
- Crumb
- DimensionsSpec
- EmitHandler
- EmitOptions
- Entry
- EntryParts
- Fallback
- Finding
- FolderOptions
- Format
- GetRemote
- GlobMap
- GroupMeta
- GroupSpec
- Heading
- LinkOptions
- LinkRef
- LinkSpec
- ListRemote
- LlmsEmitOptions
- MarkdownMeta
- MetaDecoration
- NavGroup
- NavItem
- NavLeaf
- NavLink
- NavRef
- NavTree
- NumberedOptions
- OutlineNode
- OutlineOptions
- OutlineSpec
- OutlineThunk
- PageFields
- PageView
- PostFields
- PrevNext
- RawEmit
- RawRecord
- RawSource
- ReadContext
- RefEntry
- Resolved
- ResolvedBlockNode
- SchemaLike
- SearchBrain
- SearchClient
- SearchClientOptions
- SearchDoc
- SearchEngine
- SearchHit
- SearchIndex
- SearchOptions
- Selection
- Severity
- ShellContext
- SiteData
- SiteMeta
- SiteOptions
- Source
- SourceChanges
- SourceEntry
- SourceRef
- Switcher
- SwitcherAxis
- TrailScope
Auto-generated from the package’s own .d.ts on every build — signatures, JSDoc, and examples straight from the source.
import { … } from 'ogygia/content';Exports blocks · build_docs · content · create_search · date_of · dated · defineSource · dimensions · enrich · folder · get_shell_context · glob · href_of · is_dimensioned · json · links · mapRaw · markdown · mountBase · numbered · orama_engine · order_of · outline · parseSchema · pick · roving · search · site · split_sections · strip_order_prefix · strip_prose · title_case · toRawSource · BlogList · BlogPost · BlogShell · BottomBar · CodeChrome · Doc · Frame · Link · OnThisPage · Pager · Search · SearchPage · Sheet · Sidebar · SiteSlot · Tab · TabGroup · ThemeToggle · fields · ContentHandle · Convention · Dimensioned · Outline · RovingOptions · Site · WithRemotes · Axis · BaseOption · BlockNode · BlockRegistry · BlockSchedule · BlockSource · BlogPostRef · ChangeFields · Check · CheckContext · Collection · ContentEntry · ContentMode · ContentOptions · ContentRef · ContentRelations · Coordinate · Crumb · DimensionsSpec · EmitHandler · EmitOptions · Entry · EntryParts · Fallback · Finding · FolderOptions · Format · GetRemote · GlobMap · GroupMeta · GroupSpec · Heading · LinkOptions · LinkRef · LinkSpec · ListRemote · LlmsEmitOptions · MarkdownMeta · MetaDecoration · NavGroup · NavItem · NavLeaf · NavLink · NavRef · NavTree · NumberedOptions · OutlineNode · OutlineOptions · OutlineSpec · OutlineThunk · PageFields · PageView · PostFields · PrevNext · RawEmit · RawRecord · RawSource · ReadContext · RefEntry · Resolved · ResolvedBlockNode · SchemaLike · SearchBrain · SearchClient · SearchClientOptions · SearchDoc · SearchEngine · SearchHit · SearchIndex · SearchOptions · Selection · Severity · ShellContext · SiteData · SiteMeta · SiteOptions · Source · SourceChanges · SourceEntry · SourceRef · Switcher · SwitcherAxis · TrailScope
blocks
function
Build a blocks source. The registry is resolved into regions AT MINT (blocks.resolve), so an
entry's body is a clean tree of regions — the registry never rides along. data carries any meta frontmatter the page declared. The body renders through an internal recomposer, the same one the
no-collection recipe reproduces in ten lines.
function blocks(input: GlobMap | RawSource<unknown>, registry: BlockRegistry, opts?: {
id?: (key: string) => string;
schedule?: BlockSchedule;
}): Source;build_docs
function
Build every searchable document for the outline's leaves (optionally scoped to collections).
function build_docs(ol: Outline, only?: Collection[]): Promise<SearchDoc[]>;content
function
function content<Meta = Record<string, never>, Schema extends SchemaInput | undefined = undefined, Data extends Record<string, unknown> = Schema extends SchemaInput ? LayeredData<Schema> extends Record<string, unknown> ? LayeredData<Schema> : Record<string, unknown> : Record<string, unknown>>(opts: {
loader: Source<Meta>;
schema?: Schema;
filter?: (entry: ContentRef<Data, Meta>, ctx: ReadContext) => boolean;
relations?: (self: ContentHandle<Data, Meta>) => ContentRelations;
}): ContentHandle<Data, Meta>;create_search
function
Create site.search. The index builds on first query (single-flight), from ALL leaves (or the
scoped subset — each distinct scope gets its own memoized index). Rebuilds when any contributing
collection's catalog version changes (live sources).
function create_search(ol: Outline, engine: SearchEngine): SearchBrain;date_of
function
Read the date prefix off one segment as ISO YYYY-MM-DD (whatever the authored format), or null
when the segment isn't date-prefixed / the date is impossible. Exported so an app can recover the
date for DISPLAY from filePath — the convention strips it from the slug.
function date_of(segment: string, format?: string): string | null;dated
function
The dated convention: date-prefixed segments order siblings chronologically (order = days since
epoch, so refs() come back oldest→newest; a blog index reverses). The date is stripped from the
slug — URLs stay /blog/release, not /blog/2026-08-13-release — and recoverable for display
via date_of on the entry's filePath. Undated segments (directories, one-off pages) pass
through unordered. Verification is deliberately loose: only an UNPARSEABLE date-looking prefix is
an error — mixing dated posts with undated pages is normal for a blog.
function dated(opts?: DatedOptions): Convention;defineSource
function
Compose a raw source + a format into a finished Source. Threads init/live/groups.
function defineSource<V, Meta = Record<string, never>>(raw: RawSource<V>, format: Format<V, Meta>, extra?: {
init?: () => Promise<void>;
groups?: () => Promise<Map<string, GroupMeta>>;
}): Source<Meta>;dimensions
function
Mint a dimensioned outline — the i18n/versioning wrapper site() consumes like any outline.
function dimensions(spec: DimensionsSpec): Dimensioned;enrich
function
Enrich every entry's meta with derived facts — SOURCE middleware, the read-side sibling of mapRaw. The enricher sees the finished ref (id, data, meta, filePath) and returns extra
meta merged over it, on refs() and get() alike. Loader-agnostic: git_meta() / reading_time() style values work over folder() and a CMS the same way (a CMS that already has the fact simply
ships it in data and skips the enricher).
content({ loader: enrich(folder(map), reading_time()) })
function enrich<Meta, Extra extends Record<string, unknown>>(src: Source<Meta>, fn: (ref: SourceRef<Meta>) => Extra | Promise<Extra>): Source<Meta & Extra>;folder
function
function folder<Meta = Record<string, never>>(map: GlobMap, opts?: FolderOptions<Meta>): Source<Meta>;get_shell_context
function
function get_shell_context(): ShellContext | undefined;glob
function
Wrap an import.meta.glob(...) map as a raw source: ids are the (prefix-stripped, extension-less)
keys, get(id) loads ONE module, refs() loads all. Lazy globs load a module only when read — so get(id) on a big local collection touches one file, not the whole set.
function glob<V = unknown>(globMap: GlobMap, opts?: {
id?: (key: string) => string;
}): RawSource<V>;href_of
function
Compose the mount base and a slug into an href. Links bypass this.
function href_of(base: string, slug: string): string;is_dimensioned
function
Narrow an unknown to a Dimensioned outline.
function is_dimensioned(x: unknown): x is Dimensioned;json
function
JSON modules — a plain object, or { default: object }. Data-only (no body).
function json(input: Input<unknown>, opts?: BuilderOpts): Source;links
function
The link audit as a check value. Validates each page's in-prose markdown links (meta.links,
collected by the markdown format) against the site's own address space — missing pages, missing
anchors, and stale redirect links. A blocks/CMS corpus that collects no meta.links is warned
about once (dev), then passes (any format can fill meta.links to opt in).
site({ outline: docs, checks: [links()] }) site({ outline: docs, checks: [links({ anchors: false, redirected: 'error' })] })
function links(opts?: LinkOptions): Check;mapRaw
function
Transform every raw record's value through fn — raw-source middleware for building custom loaders
(e.g. a CMS adapter that maps its JSON shape to what blocks()/markdown() expect). Threads init/live/groups through unchanged.
function mapRaw<A, B>(src: RawSource<A>, fn: (value: A) => B): RawSource<B>;markdown
function
.svx / .md content compiled by the markdown pipeline — body is the component, meta has headings.
function markdown(input: Input<unknown>, opts?: BuilderOpts): Source<MarkdownMeta>;mountBase
function
Derive the mount prefix by subtraction: the catch-all's url.pathname minus its matched slug is
the group's base. Call it once in the layout — the one place guaranteed to hold the request. Root
mount → ''; a (docs) group at /docs → '/docs'. Composes with paths.base (already in the
pathname). No global config, no registry.
function mountBase(url: URL | string | {
pathname: string;
}, slug: string): string;numbered
function
The BLESSED convention: NN- prefixes order siblings, stripped from slugs, labels title-cased.
Its verify makes the convention self-checking wherever it is actually in use — a directory with
NO prefixed children is simply not ordered (fine); one prefixed child means ALL siblings commit.
A directory's +meta.json { "ordered": false } exempts it entirely.
function numbered(opts?: NumberedOptions): Convention;orama_engine
function
The default engine — Orama over the section documents, title/heading boosted.
function orama_engine(): SearchEngine;order_of
function
Read a leading NN- prefix as a number; missing prefix sorts last. 00-start → 0.
function order_of(segment: string): number;outline
function
Weave any number of collections + an arrangement into one derived Outline.
function outline(spec: OutlineSpec, opts?: OutlineOptions): Outline;parseSchema
function
function parseSchema(schema: SchemaLike | undefined, data: unknown, label: string): Promise<Record<string, unknown>>;pick
function
pick(collection, ...patterns) — a subset in pattern order (exact ids or */** globs).
function pick(collection: Collection, ...patterns: string[]): Selection;roving
function
Attach roving-tabindex behavior to container. The entry tab stop is the CURRENT item (or the first
if none); arrows/Home/End move focus and carry the single tabindex="0" with it.
function roving(opts: RovingOptions): (container: HTMLElement) => () => void;search
function
The headless search handle for bespoke chrome — const s = search({ base: '/docs' }), then s.query(q). One argument, convention-first. (The <Search> brick uses this internally; inside a <Shell> it needs no arguments at all.)
function search(opts?: SearchClientOptions): SearchClient;site
function
Mint the site brains. site({ outline }) is the only required key; a bare collection auto-arranges.
function site(opts: SiteOptions): Site;split_sections
function
Split a page's source into { heading, text } chunks aligned to its collected headings.
function split_sections(source: string, headings: Heading[]): {
heading: Heading | null;
text: string;
}[];strip_order_prefix
function
Strip a leading NN- ordering prefix from one path segment. 00-start → start.
function strip_order_prefix(segment: string): string;strip_prose
function
Light markdown/svx strip for index text: fences, tags, inline markers. Not a parser — good enough for tokenization.
function strip_prose(src: string): string;title_case
function
data-state → Data State. The default label when no +meta.json overrides it.
function title_case(slug: string): string;toRawSource
function
Turn a source builder's input (a glob map, or a raw source you wrote) into a raw source.
function toRawSource<V>(input: GlobMap | RawSource<V>, opts?: {
id?: (key: string) => string;
}): RawSource<V>;BlogList
component
import BlogList from 'ogygia/content';BlogPost
component
import BlogPost from 'ogygia/content';BlogShell
component
import BlogShell from 'ogygia/content';BottomBar
component
import BottomBar from 'ogygia/content';CodeChrome
component
import CodeChrome from 'ogygia/content';Doc
component
import Doc from 'ogygia/content';Frame
component
import Frame from 'ogygia/content';Link
component
import Link from 'ogygia/content';OnThisPage
component
import OnThisPage from 'ogygia/content';Pager
component
import Pager from 'ogygia/content';Search
component
import Search from 'ogygia/content';SearchPage
component
import SearchPage from 'ogygia/content';Sheet
component
import Sheet from 'ogygia/content';Sidebar
component
import Sidebar from 'ogygia/content';SiteSlot
component
import SiteSlot from 'ogygia/content';Tab
component
import Tab from 'ogygia/content';TabGroup
component
import TabGroup from 'ogygia/content';ThemeToggle
component
import ThemeToggle from 'ogygia/content';fields
const
The blessed schema family. page is the universal base; post / change are pre-layered genre
stacks (base + genre extras) consumed by content({ schema }), which merges array layers left→right.
const fields: {
page: SchemaLike & {
readonly "~standard": {
types?: {
output: PageFields;
};
};
};
post: [typeof page, typeof post_only];
change: [typeof page, typeof change_only];
}ContentHandle
interface
The browser-safe handle content() returns (read paths + graph; remotes come from withRemotes()).
interface ContentHandle<Data extends Record<string, unknown> = Record<string, unknown>, Meta = Record<string, never>> {/*…*/}ContentHandle.refs
The corpus as metadata — all visible REFS (each with rel / backlinks), never bodies. ctx threads into the collection filter (preview, roles); default {} = the public projection.
refs(ctx?: ReadContext): Promise<ContentRef<Data, Meta>[]>;ContentHandle.get
Resolve one entry to { id, data, meta, body, source, rel, backlinks } for rendering. body is
an inline <Region>. Unknown / filtered-out id → null (the caller decides the 404).
get(id: string, ctx?: ReadContext): Promise<Entry<Data, Meta> | null>;ContentHandle.groups
Directory/section decoration the source exposes (folder() from +meta.json, a CMS from folders).
groups(): Promise<Map<string, GroupMeta>>;Convention
interface
The pluggable filename convention. folder() uses the blessed numbered instance unless you
hand it your own — pass a partial to keep the blessed behavior for the pieces you don't override.
interface Convention {/*…*/}Convention.segment
One raw source segment → its structural meaning. Blessed: 02-data-state → slug + order 2.
segment(raw: string): {
slug: string;
order: number;
};Convention.label
Default label for a clean slug (a +meta.json label still overrides).
label(slug: string): string;Convention.verify
Verify one directory's SIBLING segments (raw, as authored). Runs once per directory during the
folder scan; returned strings become named BUILD errors. dir is the clean path ('' = root); meta is the directory's own +meta.json, so { "ordered": false } can exempt a directory.
verify(dir: string, segments: string[], meta: MetaDecoration | undefined): string[];Dimensioned
interface
An Outline with the coordinate extras site() surfaces (switcher, fallback, coordinate).
interface Dimensioned extends Outline {/*…*/}Dimensioned.axes
axes: Record<string, Axis>;Dimensioned.tree
The nav tree for coord (default coordinate when omitted), hrefs baked for base, read context ctx.
tree(base?: string, coord?: Coordinate, ctx?: ReadContext): Promise<NavTree>;Dimensioned.coordinateOf
The coordinate encoded in a full slug (defaults filled for absent axes).
coordinateOf(slug: string): Coordinate;Dimensioned.canonicalAddresses
The DEFAULT coordinate's bare addresses — the canonical set to index for search (so fallback pages under other coordinates don't show as duplicate hits).
canonicalAddresses(ctx?: ReadContext): Promise<string[]>;Dimensioned.switcher
The switcher for the coordinate in slug, hrefs baked for base.
switcher(slug: string, base?: string, ctx?: ReadContext): Promise<Switcher>;Dimensioned.fallbackOf
Which axis (if any) fell back resolving slug.
fallbackOf(slug: string, ctx?: ReadContext): Promise<Fallback>;Outline
interface
The public Outline — collection-like over arrangement. Mostly consumed through pharos().
interface Outline {/*…*/}Outline.tree
The full nav tree, hrefs resolved for base (default ''), in read context ctx (default public).
tree(base?: string, ctx?: ReadContext): Promise<NavTree>;Outline.resolve
Resolve a slug to its collection + entry + placement, or null.
resolve(slug: string, ctx?: ReadContext): Promise<{
record: Resolved;
collection: Collection;
} | null>;Outline.addresses
Every leaf slug, in reading order — the prerender source (public projection by default).
addresses(ctx?: ReadContext): Promise<string[]>;Outline.neighbors
Reading-order neighbors of a slug, as refs for base (default ''). scope: 'group' bounds
prev/next to the top-level section.
neighbors(slug: string, base?: string, ctx?: ReadContext, scope?: TrailScope): Promise<{
prev?: NavRef;
next?: NavRef;
}>;Outline.slug_for
Map an entry id (within a collection) to its slug — for resolving graph relations.
slug_for(collection: Collection, entryId: string, ctx?: ReadContext): Promise<string | undefined>;Outline.alias
Canonical slug for a declared old address (redirect history), or undefined.
alias(slug: string, ctx?: ReadContext): Promise<string | undefined>;Outline.aliases
The whole redirect map: old slug → canonical slug.
aliases(ctx?: ReadContext): Promise<Map<string, string>>;RovingOptions
interface
interface RovingOptions {/*…*/}RovingOptions.selector
Which descendants are the roving items (e.g. .og-nav-link).
selector: string;RovingOptions.orientation
Arrow axis. Nav rails are 'vertical' (Up/Down); a tab bar is 'horizontal' (Left/Right).
orientation?: 'vertical' | 'horizontal';RovingOptions.loop
Wrap past the ends (default true).
loop?: boolean;Site
interface
The site brains. All data-returning, all browser-safe.
interface Site {/*…*/}Site.outline
The underlying outline, for tier-2 chrome that wants the raw tree/resolver.
outline: Outline;Site.data
Site facts (title/description/origin), or undefined if none were declared. Shells read title.
data?: SiteData;Site.components
The element-override component map (user overrides; SiteSlot adds the a → Link default). Shell provides this via context; tier-2 renders can provide it themselves.
components: Record<string, Component<Record<string, unknown>>>;Site.load
SvelteKit load — the 404 guard, alias 308s, and (when enabled) the per-page link audit.
load: (event: LoadLike) => Promise<void>;Site.entries
SvelteKit entries — every leaf slug PLUS declared old addresses (so redirect stubs bake).
entries: () => Promise<Array<{
slug: string;
}>>;Site.nav
The sidebar tree, hrefs resolved for base (default ''). On a dimensions() site pass the
current slug so the tree reflects that coordinate; ignored otherwise.
nav: (opts?: BaseOption & {
slug?: string;
context?: ReadContext;
}) => Promise<NavTree>;Site.switcher
On a dimensions() site: the version/locale switcher for the coordinate in slug (hrefs baked
for base). null on a plain site. Serializable — the shell renders a <select>.
switcher: (slug: string, opts?: BaseOption & {
context?: ReadContext;
}) => Promise<Switcher | null>;Site.meta
The whole SHELL bundle in one browser-safe call: { nav, switcher, data } for a slug. Feed it
to <Shell {meta}> so the corpus stays server-only — this is what a meta remote returns.
meta: (opts?: BaseOption & {
slug?: string;
context?: ReadContext;
}) => Promise<SiteMeta>;Site.page
Everything one page position needs, or null for an unknown slug. Call in the page component.
Pass context (e.g. { preview: true }) to see the same projection the load guard used.
page: <Data extends Record<string, unknown> = Record<string, unknown>, Meta = unknown>(slug: string, opts?: BaseOption & {
context?: ReadContext;
}) => Promise<PageView<Data, Meta> | null>;Site.check
Run all checks over the whole corpus as plain data (never throws) — for vitest/CI, and for
dynamic sites where the prerender crawler never runs.
check: (opts?: {
base?: string;
context?: ReadContext;
}) => Promise<Finding[]>;Site.search
Full-text search brain — lazy in-memory index over the collections' section documents. Query
from a server load / remote; scope with { in: [collection] }. Server-side (or the worker over
the emitted index); do not call over a glob collection in the browser.
search: SearchBrain;Site.emit
Machine-facing serializations — each mints a GET handler for a +server.ts.
emit: {
sitemap: (opts?: EmitOptions) => EmitHandler;
llms: (opts?: LlmsEmitOptions) => EmitHandler;
raw: (opts?: {
frontmatter?: 'keep' | 'strip';
}) => RawEmit;
search: (opts?: EmitOptions) => EmitHandler;
rss: (opts: RssEmitOptions) => EmitHandler;
};WithRemotes
interface
The server-side handle withRemotes() returns: the collection's read paths + its remotes.
interface WithRemotes<T extends Record<string, unknown>> {/*…*/}WithRemotes.refs
refs(): Promise<ContentRef<T>[]>;WithRemotes.get
get(id: string): Promise<Entry<T> | null>;WithRemotes.list
Prerendered/query remote over the corpus refs (wire-safe metadata).
list<Out = {
id: string;
data: T;
}>(options?: RefsOptions<T, Out>): ListRemote<Out>;WithRemotes.live
live: {
list<Out = {
id: string;
data: T;
}>(options?: LiveRefsOptions<T, Out>): ListRemote<Out>;
get<Out = {
id: string;
data: T;
} | null>(options?: LiveGetOptions<T, Out>): GetRemote<Out>;
};Axis
type
One axis of the content matrix.
type Axis = {
values: string[];
default?: string;
fallback?: boolean;
label?: string;
};BaseOption
type
Per-render href option — the mount prefix the outline is served under.
type BaseOption = {
base?: string;
};BlockNode
type
One node in a block tree: a type naming a registered block, its props, and nested children.
A block's wake schedule is baked into its registry import (with { wake: 'load' }) or decided by a schedule resolver passed to <Blocks> — not carried on the node.
type BlockNode = {
type: string;
id?: string;
props?: Record<string, unknown>;
children?: BlockNode[];
};BlockRegistry
type
Map from a block type name to the component it renders — a with { region: 'raw' } import.
type BlockRegistry = Record<string, unknown>;BlockSchedule
type
The schedule resolver for a tree: (node.props) => { wake?, margin? }, forwarded to region().
type BlockSchedule = RegionSchedule<Record<string, unknown>>;BlockSource
type
A block source: an array of nodes, a single node, or { blocks, meta } (frontmatter in meta).
type BlockSource = BlockNode | BlockNode[] | {
blocks: BlockNode[];
meta?: Record<string, unknown>;
};BlogPostRef
type
A post as the blog INDEX lists it (<BlogList posts>): the display fields + its href. Map a
collection's refs to this over the wire so the corpus stays server-side.
type BlogPostRef = {
href: string;
title: string;
date: string;
summary?: string;
author?: string;
tags?: string[];
};ChangeFields
type
Extra fields a changelog entry carries beyond a page.
type ChangeFields = {
version: string;
date: string;
};Check
type
A content check. Implement page (per-page, runs in load), site (whole-corpus), or both. A
check with only page gets a default site that runs page over every address.
type Check = {
name: string;
page?: (slug: string, cx: CheckContext) => Finding[] | Promise<Finding[]>;
site?: (cx: CheckContext) => Finding[] | Promise<Finding[]>;
};CheckContext
type
What a check is handed: the address space + the current read context + the mount base.
type CheckContext = {
outline: Outline;
base: string;
ctx: ReadContext;
};Collection
type
A content collection, as the outline consumes it (the browser-safe content() handle).
type Collection = ContentHandle<Record<string, unknown>, unknown>;ContentEntry
type
::: warning Deprecated
Old name for ContentRef. A ref never carries a body; use Entry (from get()) for that.
:::
type ContentEntry<Data = Record<string, unknown>, Meta = Record<string, never>> = ContentRef<Data, Meta>;ContentMode
type
type ContentMode = 'prerender' | 'query';ContentOptions
type
Options for a content collection (kept for reference; content() infers these in place).
type ContentOptions<Data extends Record<string, unknown> = Record<string, unknown>, Meta = Record<string, never>> = {
loader: Source<Meta>;
schema?: SchemaInput;
filter?: (entry: ContentRef<Data, Meta>, ctx: ReadContext) => boolean;
relations?: (self: ContentHandle<Data, Meta>) => ContentRelations;
};ContentRef
type
A content REF — the shallow face of an entry, what refs() yields and the catalog holds: identity
- validated
data(+ source-derivedmeta, structuralorder,filePath, and graph fields). NO body, NO source text — those are heavy faces that live only onEntry, fetched byget(). "Refs are what a corpus admits to having; an entry is what one page pays for."
type ContentRef<Data = Record<string, unknown>, Meta = Record<string, never>> = {
id: string;
data: Data;
meta: Meta;
order?: number[];
filePath?: string;
rel?: Record<string, RefEntry | RefEntry[] | null>;
backlinks?: RefEntry[];
};ContentRelations
type
Declared relations: { name: collection }, or { get name() { return collection } } for a cycle.
The frontmatter field named after each relation carries the target id(s): a string → one ref, a
string[] → many.
type ContentRelations = Record<string, unknown>;Coordinate
type
A point in the matrix — { version: 'v1', locale: 'fr' }.
type Coordinate = Record<string, string>;Crumb
type
One breadcrumb step: a group label on the path from root to a leaf (href when it is a page).
type Crumb = {
label: string;
href?: string;
};DimensionsSpec
type
type DimensionsSpec = {
axes: Record<string, Axis>;
resolve: (coord: Coordinate) => Outline | OutlineSpec | Promise<Outline | OutlineSpec>;
};EmitHandler
type
A GET handler an emission mounts as. export const GET = site.emit.sitemap({ base }).
type EmitHandler = (event: EmitEvent) => Promise<Response>;EmitOptions
type
Common emission options. origin overrides the request origin (needed for prerendered output).
type EmitOptions = {
base?: string;
origin?: string;
};Entry
type
A resolved entry from get() — data, meta, body, and the graph fields fully populated. rel is {} and backlinks [] when the collection has no graph. body is an inline <Region>,
rendered in the page's own SSR pass, so islands inside it hydrate normally.
type Entry<Data = Record<string, unknown>, Meta = Record<string, never>> = {
id: string;
data: Data;
meta: Meta;
body?: RegionValue;
source?: () => Promise<string>;
rel: Record<string, RefEntry | RefEntry[] | null>;
backlinks: RefEntry[];
};EntryParts
type
What a format computes from one raw record. body is already a region you render with <Region>.
type EntryParts<Meta = Record<string, never>> = {
data: Record<string, unknown>;
body?: RegionValue;
meta?: Meta;
source?: () => Promise<string>;
};Fallback
type
What fell back for a page (which axis, from → to), or null when the page is native.
type Fallback = {
axis: string;
from: string;
to: string;
} | null;Finding
type
One check result — file-anchored where possible, so it reads in the build-error voice.
type Finding = {
check: string;
severity: Severity;
message: string;
slug?: string;
file?: string;
line?: number;
};FolderOptions
type
type FolderOptions<Meta> = {
page?: RegExp;
meta?: RegExp | false;
convention?: Convention;
format?: (input: RawSource<unknown>) => Source<Meta>;
};Format
type
Parse one raw value into entry parts (data + optional body + optional meta).
type Format<V, Meta = Record<string, never>> = (value: V, id: string) => EntryParts<Meta> | Promise<EntryParts<Meta>>;GetRemote
type
type GetRemote<Out> = (id: string) => Promise<Out>;GlobMap
type
import.meta.glob(...) map — eager values or lazy loaders.
type GlobMap = Record<string, unknown | (() => Promise<unknown>)>;GroupMeta
type
Directory/section decoration a source may expose (groups()), keyed by clean group path.
type GroupMeta = {
label?: string;
};GroupSpec
type
An explicit group. base prefixes the slugs of entries beneath it.
type GroupSpec = {
label: string;
items: Collection | Selection | OutlineNode[] | OutlineThunk;
base?: string;
slug?: (id: string) => string;
collapsed?: boolean;
badge?: string;
};Heading
type
A heading pulled from the markdown pass (h2–h4). Powers on-page TOCs; rides markdown meta.
type Heading = {
depth: 2 | 3 | 4;
id: string;
text: string;
};LinkOptions
type
Tuning for the links check — the old audit options, now on the value.
type LinkOptions = {
anchors?: boolean;
redirected?: 'error' | 'warn' | 'ok';
ignore?: (href: string) => boolean;
};LinkRef
type
One markdown link collected during the compile pass (raw, unclassified). Rides markdown meta;
ogygia's audit resolves these against the site's address space. line is approximate (relative
to the post-frontmatter text).
type LinkRef = {
href: string;
text: string;
line?: number;
};LinkSpec
type
A plain link node — points anywhere; not backed by an entry.
type LinkSpec = {
label: string;
href: string;
};ListRemote
type
Return types for the minted remotes (the callable shape consumers use; cast for extra methods).
type ListRemote<Out> = () => Promise<Out[]>;LlmsEmitOptions
type
type LlmsEmitOptions = EmitOptions & {
title?: string;
description?: string;
};MarkdownMeta
type
Meta the markdown source derives: h2–h4 headings (for a TOC) and every markdown link (for the ogygia link audit), both collected during compile.
type MarkdownMeta = {
headings: Heading[];
links: LinkRef[];
};MetaDecoration
type
Directory decoration a +meta.json may carry. DELIBERATELY tiny — the blessed convention has one
ordering channel (the NN- prefix) and one naming channel (this file). Order does not belong
here (that would be a second way to say the same thing), and chrome behavior (collapsing,
badges) belongs to the spec/escape hatch, not to content decoration.
type MetaDecoration = {
label?: string;
ordered?: boolean;
};NavGroup
type
A group of nav items — a section (from convention) or an explicit outline group.
type NavGroup = {
kind: 'group';
label: string;
collapsed?: boolean;
badge?: string;
items: NavItem[];
};NavItem
type
type NavItem = NavGroup | NavLeaf | NavLink;NavLeaf
type
A leaf in the nav tree — one content entry.
type NavLeaf = NavRef & {
kind: 'leaf';
badge?: string;
};NavLink
type
A plain link — points anywhere, external or otherwise; not backed by an entry.
type NavLink = {
kind: 'link';
label: string;
href: string;
};NavRef
type
A shallow reference to one entry, ready to link: its address + display fields.
type NavRef = {
slug: string;
href: string;
title: string;
summary?: string;
};NavTree
type
The serializable sidebar tree — what site.nav() returns and a sidebar brick renders.
type NavTree = NavItem[];NumberedOptions
type
type NumberedOptions = {
pad?: number;
contiguous?: boolean;
duplicates?: 'error' | 'allow';
};OutlineNode
type
What can sit inside a group's items, or at the top level of a spec.
type OutlineNode = Collection | Selection | GroupSpec | LinkSpec | OutlineThunk;OutlineOptions
type
type OutlineOptions = {
redirects?: (entry: Ent) => string[] | string | undefined;
};OutlineSpec
type
A whole spec: a bare collection (degenerate case) or an ordered list of nodes.
type OutlineSpec = Collection | OutlineNode[];OutlineThunk
type
type OutlineThunk = () => OutlineNode[] | OutlineNode | Promise<OutlineNode[] | OutlineNode>;PageFields
type
What every ogygia surface reads off a page. title is required; the rest carry blessed defaults.
type PageFields = {
title: string;
summary: string;
draft: boolean;
badge?: string;
redirect_from?: string | string[];
related: string[];
};PageView
type
Everything a single page position needs, as plain data. entry carries the inline body region;
everything else is derived from the outline and the content graph.
type PageView<Data extends Record<string, unknown> = Record<string, unknown>, Meta = unknown> = {
slug: string;
href: string;
entry: Entry<Data, Meta>;
section: string;
crumbs: Crumb[];
headings: Heading[];
trail: {
prev?: NavRef;
next?: NavRef;
related: NavRef[];
suggested: NavRef[];
};
coordinate?: Record<string, string>;
fallback?: {
axis: string;
from: string;
to: string;
} | null;
};PostFields
type
Extra fields a blog post carries beyond a page (a Blog shell reads these; the brains do not).
type PostFields = {
date: string;
author?: string;
tags: string[];
};PrevNext
type
How "keep reading" is chosen. 'graph' = content relations, order fallback.
type PrevNext = 'graph' | 'order' | false;RawEmit
type
The raw-markdown emission: a GET handler + its prerender entries, for a [...slug].md/+server.ts.
type RawEmit = {
GET: (event: {
params: Record<string, string | undefined>;
}) => Promise<Response>;
entries: () => Promise<Array<{
slug: string;
}>>;
};RawRecord
type
One raw record before parsing: a compiled .svx module, a JSON blob, an API result.
type RawRecord<V> = {
id: string;
value: V;
order?: number[];
filePath?: string;
};RawSource
type
A raw source yields unparsed values; a Format turns each into EntryParts.
type RawSource<V> = {
init?: () => Promise<void>;
refs(query?: unknown): Promise<RawRecord<V>[]>;
get(id: string): Promise<RawRecord<V> | null>;
live?: () => SourceChanges;
groups?: () => Promise<Map<string, GroupMeta>>;
};ReadContext
type
A request context the site derives per read (preview, roles) and threads into collection filters.
type ReadContext = Record<string, unknown>;RefEntry
type
A resolved relation target: a shallow reference to another entry — its id and validated data.
Deliberately shallow (no body, no URL); build the link from ref.id, or collection.get(ref.id).
type RefEntry<Data = Record<string, unknown>> = {
id: string;
data: Data;
};Resolved
type
Resolution of a slug back to its collection + entry id + placement in the tree.
type Resolved = {
slug: string;
entryId: string;
collectionIndex: number;
section: string;
crumbs: Crumb[];
filePath?: string;
};ResolvedBlockNode
type
A resolved node: its type already turned into a region value, ready for <Blocks nodes={…}>. This is
the wire-law shape — the registry (full of functions) is consumed here, so the tree that survives
is data whose leaves are regions. Fed back into <Blocks nodes={…}>.
type ResolvedBlockNode = {
of: RegionValue;
children?: ResolvedBlockNode[];
};SchemaLike
type
Any Standard Schema (valibot / zod / arktype) or a { parse } object.
type SchemaLike = {
['~standard']?: {
validate: (value: unknown) => StandardResult | Promise<StandardResult>;
};
parse?: (value: unknown) => unknown;
};SearchBrain
type
type SearchBrain = (q: string, opts?: SearchOptions) => Promise<SearchHit[]>;SearchClient
type
type SearchClient = {
query(q: string): Promise<SearchHit[]>;
ready: Promise<void>;
destroy(): void;
};SearchClientOptions
type
type SearchClientOptions = {
base?: string;
endpoint?: string;
limit?: number;
};SearchDoc
type
One searchable document — a page SECTION (split by heading), or the page lead. Mount-independent:
stores slug + anchor, so href is computed per query with the caller's base.
type SearchDoc = {
id: string;
slug: string;
anchor: string;
title: string;
section: string;
heading: string;
text: string;
};SearchEngine
type
The engine adapter: build documents into a queryable index. Must run in node AND the browser.
type SearchEngine = {
init?(): Promise<void>;
build(docs: SearchDoc[]): Promise<SearchIndex>;
};SearchHit
type
One ranked hit — plain data, ready to render as a link.
type SearchHit = {
href: string;
slug: string;
title: string;
section: string;
heading: string;
excerpt: string;
score: number;
};SearchIndex
type
type SearchIndex = {
query(q: string, opts: {
limit: number;
base: string;
}): Promise<SearchHit[]>;
};SearchOptions
type
type SearchOptions = {
limit?: number;
in?: Collection[];
base?: string;
};Selection
type
A subset of one collection, in resolution order — produced by pick().
type Selection = {
readonly [SELECTION]: true;
readonly collection: Collection;
readonly patterns: string[];
};Severity
type
How loud a finding is: 'error' fails the build (load throws); 'warn' logs in dev.
type Severity = 'error' | 'warn';ShellContext
type
type ShellContext = {
site?: Site;
base: string;
components?: ComponentMap;
title?: string;
};SiteData
type
Site-level facts, surfaced as site.data and used as the default for every emission.
type SiteData = {
title: string;
description: string;
origin: string;
};SiteMeta
type
The SHELL bundle — everything <Shell> needs as plain data, so the corpus can stay server-only. site.meta(slug) returns it; expose it as a remote and pass the result to <Shell {meta}>.
type SiteMeta = {
nav: NavTree;
switcher: Switcher | null;
data?: SiteData;
};SiteOptions
type
The single-object argument to site(). outline is the only required key.
type SiteOptions = {
outline: Outline | OutlineSpec;
data?: SiteData;
base?: string;
context?: (event: {
url: URL;
request?: Request;
cookies?: unknown;
}) => ReadContext;
prevNext?: PrevNext;
trail?: TrailScope;
checks?: Check[];
components?: Record<string, Component<Record<string, unknown>>>;
search?: {
engine?: SearchEngine;
};
redirects?: (entry: ContentRef) => string[] | string | undefined;
};Source
type
The source contract — the only thing content({ loader }) accepts.
type Source<Meta = Record<string, never>> = {
init?: () => Promise<void>;
refs(query?: unknown): Promise<SourceRef<Meta>[]>;
get(id: string): Promise<SourceEntry<Meta> | null>;
live?: () => SourceChanges;
groups?: () => Promise<Map<string, GroupMeta>>;
};SourceChanges
type
A live source's change signal. Yield to tell the collection to re-read:
- yield anything (e.g.
1) → the collection re-lists the whole source (simple, default); - yield a
string[]of ids → the collection reloads only those ids (get(id)each, missing ids are dropped) — incremental, for large collections where a full re-list is wasteful.
type SourceChanges = AsyncIterable<string[] | unknown>;SourceEntry
type
One full entry a source yields from get() — a ref plus the two heavy faces. Never crosses a wire.
type SourceEntry<Meta = Record<string, never>> = SourceRef<Meta> & {
body?: RegionValue;
source?: () => Promise<string>;
};SourceRef
type
A shallow reference a source yields from refs() — identity + data, plus optional derived meta and
structural order. NEVER a body or source text; those live only on SourceEntry. Wire-safe.
type SourceRef<Meta = Record<string, never>> = {
id: string;
data: Record<string, unknown>;
meta?: Meta;
order?: number[];
filePath?: string;
};Switcher
type
type Switcher = SwitcherAxis[];SwitcherAxis
type
One axis of the switcher: where you are on it, and where each value would take you.
type SwitcherAxis = {
axis: string;
label: string;
current: string;
options: Array<{
value: string;
href: string;
current: boolean;
missing: boolean;
}>;
};TrailScope
type
Reading-order policy for prev/next: the whole site, or bounded by the top-level section.
type TrailScope = 'site' | 'group';