Skip to main content

gentleduck/registry build

Generic index-building core with explicit extensions, type-safe config, and incremental rebuilds.

What this package is

gentleduck/registry-build is a consumer-owned build system for indexable content.

Use it when you need to:

  • declare one or more named collections of data or source trees
  • attach structured metadata to those collections
  • emit stable machine-readable indexes or repository artifacts
  • generate derived outputs such as manifests, search indexes, component indexes, or theme files
  • keep the build reproducible and consumer-owned instead of hardcoding repo paths

The package is intentionally split into a small core and explicit extensions. That keeps the base runner reusable while still supporting docs-site style builds through the compatibility layer.


Why it exists

The old approach to registry generation usually looks like this:

  • arrays of entries hardcoded in source
  • output paths hidden behind environment variables
  • framework-specific logic baked into the build
  • one repo layout assumed forever

registry-build replaces that with:

  • a typed registry-build.config.ts
  • a generic collections model for non-UI consumers
  • path-aware config composition with extends
  • explicit extension hooks for optional outputs
  • CLI-driven execution
  • incremental caching for repeated local builds

Architecture at a glance

Loading diagram...


Capability map

LayerResponsibilityWhy it matters
Config loaderDiscover config, resolve extends, normalize pathsConsumers own the build contract
Collections modelMaterialize named datasets and source declarationsNon-UI consumers get a generic starting point
Compatibility layerTranslate legacy UI config into generic collection artifactsExisting docs-style builds keep working while the core evolves
Built-in extensionsIndex build, components, colors, component index, validation, bannerAll processing is extension-driven, nothing runs by default
Custom extensionsAdd repository indexes, manifests, search indexes, or any domain-specific outputComposable and explicit
CLIRun builds from app/package rootsWorks like a normal tool, not a repo-only script
Performance layerFile-hash cache, write skipping, changed-only mode, bounded concurrencyFast warm builds and less filesystem churn


Installation


npm install @gentleduck/registry-build

npm install @gentleduck/registry-build

Core model

Consumer-owned config

The config file lives beside the app or package that owns the outputs. That means source paths, registry entries, output directories, extensions, and performance settings are all declared by the consumer, not buried inside the shared package.

Core phases vs extensions

The core runner is entirely extension-driven. Index building, component generation, validation, component-index generation, colors/themes, and banners are all extensions that consumers attach explicitly. If you do not attach them, they do not run.

Typed registry namespaces

If you are building a UI registry, item types are validated as registry:${string}. That same namespace carries through sources, targetPaths, package mappings, schema item types, and inline registry entries. Non-UI consumers can start from collections and avoid those compatibility fields entirely.

Collections-first model

For new non-UI builds, start with collections. A collection can hold file-backed data, source declarations, and arbitrary metadata that your extension reads later. That is the preferred mental model for package indexes, repository catalogs, and search manifests.

Incremental rebuild behavior

The builder stores cache data under <output.dir>/.registry-build/. On warm runs it reuses file hashes, skips unchanged writes, removes stale generated files, and can narrow work further with --changed-only plus explicit changed paths.


Typical use cases

  • Build a docs-site registry from component source folders.
  • Emit an installable JSON index for a CLI.
  • Generate an Arch-like repository database and search manifest.
  • Create a generated component import map for a framework.
  • Generate theme and token payloads from static data files.
  • Produce custom artifacts through extension hooks after the base registry is materialized.

Production checklist

  • keep the config beside the output-owning app or package
  • start new non-UI builds from collections instead of UI compatibility fields
  • declare every UI registry item type explicitly through the same registry:${string} namespace
  • use extensions only for optional or logic-bearing outputs
  • verify two consecutive warm builds produce zero rewritten files when nothing changed
  • keep .registry-build/ ignored by Git
  • add typecheck, docs-content build, and at least one real consumer smoke test to CI