# Registry

> An open JSON format for shareable theme presets and blocks — one file anyone can host, any tool can fetch, and a schema that says what is valid.

Source: https://ngwr.dev/guides/registry

## What it is

A registry item is one installable unit as a single JSON file: a theme preset (token overrides), a block (several ngwr components composed into a page or a section), or a component. There is no server and no account — an item is a URL. Host it on your own domain, in a gist, in your repo; a tool fetches it, validates it against the schema, and writes what it describes.

The format is published at [ngwr.dev/registry/schema.json](https://ngwr.dev/registry/schema.json), and the two worked examples are beside it — [theme-slate.json](https://ngwr.dev/registry/items/theme-slate.json) and [block-sign-in.json](https://ngwr.dev/registry/items/block-sign-in.json). Point your editor's `$schema` at the first and you get completion and validation while you write one.

The shape borrows from shadcn's registry on purpose: an author who has published one of those should recognise this one. What differs is what Angular needs — `entryPoints` names `ngwr/*` subpaths, and `cssVars` names `--wr-*` tokens rather than arbitrary properties.

## A theme preset

Tokens, and nothing else.

```typescript
{
  "$schema": "https://ngwr.dev/registry/schema.json",
  "name": "theme-slate",
  "type": "registry:theme",
  "title": "Slate",
  "description": "A cooler, lower-saturation take on the default palette.",
  "ngwr": ">=11",
  "cssVars": {
    "light": {
      "--wr-color-primary": "#41598f",
      "--wr-color-primary-rgb": "65, 89, 143",
      "--wr-color-surface": "#fbfcfd"
    },
    "dark": {
      "--wr-color-primary": "#5b7fd6",
      "--wr-color-primary-rgb": "91, 127, 214",
      "--wr-color-surface": "#0c1018"
    }
  }
}
```

Keys must be `--wr-*`. A preset that sets `--brand-blue` is arbitrary CSS wearing the label: people install a theme expecting the library's own token layer to be what changes, and everything ngwr paints is derived from that layer. See [tokens](https://ngwr.dev/guides/tokens) for what is available.

## A block

Files a tool writes into your project.

```typescript
{
  "$schema": "https://ngwr.dev/registry/schema.json",
  "name": "block-sign-in",
  "type": "registry:block",
  "title": "Sign-in card",
  "description": "A centred sign-in card wired to Signal Forms.",
  "ngwr": ">=11",
  "entryPoints": ["ngwr/card", "ngwr/form", "ngwr/input", "ngwr/button", "ngwr/validators"],
  "files": [
    {
      "path": "sign-in.ts",
      "target": "src/app/sign-in/sign-in.ts",
      "content": "import { Component } from '@angular/core';\n…"
    }
  ]
}
```

## The fields

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `name`required | kebab-case, unique within the registry that hosts it. | `string` | — |
| `type`required | A theme is tokens and nothing else. A block composes several ngwr components into a page or a section. A component is one unit of UI. | `'registry:theme' \| 'registry:block' \| 'registry:component'` | — |
| `title`required | Short human name, shown in a picker. | `string` | — |
| `description`required | One sentence on what it is for. | `string` | — |
| `author` | Whoever publishes it. | `string` | `—` |
| `ngwr` | Compatible ngwr versions, as a semver range — e.g. `">=11"`. | `string` | `—` |
| `dependencies` | npm packages beyond ngwr and its peers. | `string[]` | `[]` |
| `registryDependencies` | Absolute `https` URLs of other items this one composes. Relative is meaningless — the resolving tool does not know where this item came from. | `string[]` | `[]` |
| `entryPoints` | The `ngwr/*` subpaths the item imports from. Checked against the real catalog, so a typo fails instead of installing something that will not compile. | `string[]` | `[]` |
| `cssVars` | Token overrides per theme (`light` / `dark`). Every key must be a `--wr-*` token. | `{ light?: Record<string, string>; dark?: Record<string, string> }` | `—` |
| `files` | Source files to write: `path` (inside the item), `target` (relative to the project root) and `content`. Required for a block or a component, refused for a theme. | `RegistryFile[]` | `[]` |

## Two rules worth knowing before you publish one

**A target is a relative path, and that is enforced.** An item is remote content that a CLI writes to disk, so `files[].target` rejects absolute paths, Windows drive letters, anything that looks like a URL scheme, and any `..` segment — including one that appears after a legitimate prefix, which is the form a naive "does it start with `..`" check misses. If your item needs to write outside the project, it is not a registry item.

**A theme has no files and a block has at least one.** A theme that ships code would install unreviewed source as part of "changing the colours"; a block that ships none installs nothing at all. Both are refused rather than warned about.

`pnpm check:registry` runs in this repo's lint chain: it validates every shipped item, checks each `entryPoints` name against the real catalog, and compares the published schema against the validator so the contract and the enforcement cannot drift apart.

## See also

- [Design tokens](https://ngwr.dev/guides/tokens) — The `--wr-*` layer a theme preset overrides.
- [Theming](https://ngwr.dev/guides/theming) — How the token layer is applied, and what `provideWrTheme()` does with it.
- [Agent skill](https://ngwr.dev/guides/agent-skill) — The other half of the machine-readable surface: the rules an agent needs to write ngwr correctly.
