}>
  **gentleduck/registry-build** is a build core for index-like outputs. It powers UI registries, but also drives package catalogs, Arch-style repository indexes, search manifests, and custom artifacts through explicit extensions.

## What this package 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 machine-readable indexes or repository artifacts.
* Generate derived outputs: manifests, search indexes, component indexes, theme files.
* Keep the build reproducible and consumer-owned instead of hardcoding repo paths.

The package splits into a small core and explicit extensions. The base runner stays reusable; docs-site builds still work through a compatibility layer.

***

## Why it exists

The old approach to registry generation 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

***

## Capability map

| Layer | Responsibility | Why it matters |
| --- | --- | --- |
| Config loader | Discover config, resolve `extends`, normalize paths | Consumers own the build contract |
| Collections model | Materialize named datasets and source declarations | Non-UI consumers get a generic starting point |
| Compatibility layer | Translate legacy UI config into generic collection artifacts | Existing docs-style builds keep working while the core evolves |
| Built-in extensions | Index build, components, colors, component index, validation, banner | All processing is extension-driven, nothing runs by default |
| Custom extensions | Add repository indexes, manifests, search indexes, or any domain-specific output | Composable and explicit |
| CLI | Run builds from app/package roots | Works like a normal tool, not a repo-only script |
| Performance layer | File-hash cache, write skipping, changed-only mode, bounded concurrency | Fast warm builds and less filesystem churn |

***

## Quick links

} className="[&_ul]:my-0">
  * [Getting Started](/duck-registry-build/getting-started) - Install and ship your first build.
  * [Architecture](/duck-registry-build/architecture) - Build lifecycle, context, artifacts, and extension stages.
  * [Configuration](/duck-registry-build/configuration) - Full config reference.
  * [Extensions](/duck-registry-build/extensions) - Built-in extensions and the custom extension API.
  * [CLI](/duck-registry-build/cli) - Commands, flags, JSON output, scripting patterns.
  * [Performance](/duck-registry-build/performance) - Cache behavior, changed-only mode, warm builds.
  * [Recipes](/duck-registry-build/recipes) - Patterns for docs sites, manifests, and custom outputs.
  * [Course](/duck-registry-build/course) - Walkthrough for building an Arch-style package index.
  * [Testing and CI](/duck-registry-build/testing-ci) - Golden tests, pack smoke tests, release checks.
  * [Troubleshooting](/duck-registry-build/troubleshooting) - Failure modes and debugging paths.

***

## Installation

npm
pnpm
bun

```bash
npm install @gentleduck/registry-build
```

```bash
pnpm add @gentleduck/registry-build
```

```bash
bun add @gentleduck/registry-build
```

***

## Core model

Consumer-owned config

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

Core phases vs extensions

The core runner is extension-driven. Index building, component generation, validation, component-index generation, colors/themes, and banners are extensions you attach explicitly. Unattached extensions do not run.

Typed registry namespaces

For UI registries, item types are validated as `registry:${string}`. That namespace carries through `sources`, `targetPaths`, package mappings, schema item types, and inline registry entries. Non-UI consumers start from `collections` and skip those compatibility fields.

Collections-first model

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

Incremental rebuild behavior

The builder stores cache data under `<output.dir>/.registry-build/`. Warm runs reuse file hashes, skip unchanged writes, and remove stale generated files. `--changed-only` plus explicit changed paths narrows the work further.

***

## 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 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 runs.

***

## Production checklist

* Keep the config beside the app or package that owns the outputs.
* Start new non-UI builds from `collections` rather than UI compatibility fields.
* Declare every UI registry item type through the `registry:${string}` namespace.
* Use extensions for optional or logic-bearing outputs.
* Verify two consecutive warm builds rewrite zero files when nothing changed.
* Keep `.registry-build/` ignored by Git.
* Add typecheck, docs-content build, and at least one consumer smoke test to CI.