#Architecture
flake-explorer is three cooperating layers: a TypeScript CLI/extraction layer
that drives the host nix binary, a JSON data directory that both persists and
caches extraction results, and a Svelte 5 SPA that consumes those documents
either over HTTP or embedded in a single exported HTML file. The contract
between the layers is one file: src/schema.ts.
#System overview
The CLI (flake-explorer.ts) parses flags,
canonicalizes the flakeref, and dispatches to extract, export, or serve.
extract and export share src/extract/drive.ts
(extractToDir), which builds the manifest, reconciles the on-disk cache, and
extracts requested configurations. All Nix evaluation goes through
src/extract/run-nix.ts, a thin JSON-in/JSON-out
wrapper that runs nix eval --impure --json on
src/extract/extract.nix.
flowchart TD cli["flake-explorer.ts CLI dispatch"] --> drive["drive.ts extractToDir"] drive --> manifest["manifest.ts buildManifest"] drive --> options["options.ts extractOptions"] manifest --> runnix["run-nix.ts"] options --> runnix runnix --> nix["host nix binary evaluating extract.nix"] drive --> data["data dir: manifest.json + config blobs + .meta.json sidecars"] cli --> serve["serve.ts on-demand extraction + HTTP"] cli --> export["export.ts single-file HTML"] data --> serve data --> export app["build-app.ts bundles app/"] --> serve app --> export
The data dir (default ./flake-explorer-data) holds manifest.json, one
config/<kind>.<name>.json blob per extracted configuration, and a
.meta.json sidecar per blob recording the flake narHash and extractor
version that produced it (src/extract/cache.ts).
Two consumers read it: src/serve.ts serves the SPA plus
data over HTTP, extracting pending configurations on demand (single-flight per
config, request held open); src/export.ts composes the
SPA and every data document into one standalone HTML file that works from
file:// with no server. Both get the SPA from
src/build-app.ts, which bundles
app/main.ts in-memory.
#Design decisions
- Host nix, never vendored. The
nixon PATH is deliberately the user's own —package.nixnever vendors one andflake.nixdeliberately keeps nix out of the dev shell — so store paths and the flake registry match the user's system.src/extract/run-nix.tschecks version >= 2.19 at startup and forceslazy-trees = falseso store paths join across evals. - Chunk-by-chunk option walk.
builtins.tryEvalcannot catch missing-attribute/type errors, so one poisoned option would kill an entire eval.src/extract/options.tswalks options per top-level namespace, recursively halving failing chunks to isolate the bad option; only an unsplittable chunk descends the degradation ladder (full → no values → no values+descriptions) before being abandoned. - Bun.build, not Vite.
src/build-app.tsbundles the Svelte 5 (runes) SPA withBun.build+bun-plugin-svelte, returning JS and CSS as strings thatsrc/serve.tsandsrc/export.tscompose into a page — no separate build tool or dev server. - One shared data contract.
src/schema.tsdefines both documents (cheapManifest, expensive per-configConfigData) for the extractor and the SPA alike, withstorePathas the universal join key between file entries and option declarations/definitions. See Data schema.
#Directory map
| Path | Contents |
|---|---|
flake-explorer.ts |
CLI entry: flag parsing, flakeref canonicalization, command dispatch. |
src/ |
Server-side TypeScript: serve.ts, export.ts, build-app.ts, schema.ts, licenses.ts, pathref.ts. |
src/extract/ |
The extractor: drive.ts, manifest.ts, options.ts, cache.ts, run-nix.ts, extract.nix, plus imports/git/highlight helpers. |
src/extract/vendor/ |
Vendored tree-sitter-nix wasm + highlight query for server-side tokenizing. |
app/ |
The SPA: App.svelte, components/, and lib/ (state, indexes, colors, URL routing). See Frontend. |
test/ |
Bun test suite (happy-dom for component tests). See Testing. |
bin/ |
flake-explorer.mjs — npm/bunx launcher that executes the TypeScript entry via bun. |
scripts/ |
Docs-site tooling (build-docs.ts). |
.github/workflows/ |
CI (ci.yml) and Pages publishing (pages.yml). See Build & infra. |