Artifact contracts
scripts/build-query-artifacts.mjs converts canonical data into public, query-shaped JSON in static-runtime/data/generated/v1. Treat this directory as reproducible build output.
Versioning
The artifact version is defined in both the Node build side and src/lib/data/artifacts.ts. If an incompatible JSON shape changes, update both version constants together so clients cannot mistake a new schema for an old cached asset.
Primary artifact groups
data/generated/v1/
├── texts/{slug}/meta.json
├── texts/{slug}/pages/0001.json
├── texts/{slug}/references.json
├── lemmas/{bucket}.json
├── roots/{slug}.json
├── search/{bucket}.json
├── graph/
├── excerpts/{bucket}.json
├── concepts/
└── sutras/{bucket}.json Text pages are authored as 20-verse source chunks. The text route can compose 20-, 50-, or 100-verse reader pages by fetching only the small number of source chunks required for the requested range. Do not generate multiple complete page trees merely to support display-size choices.
Buckets
Lemma, search, excerpt, and some graph artifacts use two-character ASCII-normalized buckets. asciiKey removes diacritics and punctuation; bucketFor derives the first two usable characters. This keeps a request bounded without requiring a giant index file.
Runtime access
Use fetchArtifact from src/lib/data/client.ts, passing SvelteKit’s request-scoped fetch in loaders. It resolves versioned paths and deduplicates both in-flight and completed requests. Components can use browser fetch only when they are intentionally browser-driven.
const root = await fetchArtifact<RootDetailArtifact>(`roots/${slug}.json`, fetch); Do not fetch files under static/data at runtime. Do not add timestamp cache busting, a whole-corpus store, or client-side joins across unbounded data.
Text references
references.json maps a source reference and zero-based verse index to a source page. Reader navigation should derive a target display page from the verse index and the active page size. This avoids assuming that one display-page size is always in use.
Sanitized content
Text description HTML is sanitized while artifacts are generated. Only a conservative element and link allowlist reaches {@html} consumers. Keep all user-authored or externally supplied HTML on this pipeline rather than rendering it directly.