Registry: getting started
Build a registry of your own, serve it as static JSON, and install from it with the same CLI.
Requirements
A registry is files on a static host. Anything that can serve JSON over HTTPS
with CORS will do: a CDN, an S3 bucket, GitHub Pages, or the public/
directory of the app you already deploy.
Write the items
Keep your components where you develop them and generate the registry from
there — that way the source you edit and the source you publish cannot drift.
The builder in this repository, apps/www/scripts/build-registry.mts, is small
enough to copy: it reads a list of items, inlines each file’s contents, and
writes public/r/index.json plus public/r/styles/default/<name>.json.
import { promises as fs } from "node:fs"
import path from "node:path"
const OUT = path.join(process.cwd(), "public/r")
for (const item of items) {
const files = await Promise.all(
item.files.map(async (file) => ({
...file,
content: await fs.readFile(file.path, "utf8"),
}))
)
await fs.writeFile(
path.join(OUT, "styles/default", `${item.name}.json`),
JSON.stringify({ ...item, files }, null, 2)
)
}
Serve it
Deploy the directory. If it lands at https://acme.dev/r, then
https://acme.dev/r/index.json and
https://acme.dev/r/styles/default/button.json both have to answer.
Install from it
Point one command at it:
npx newtui@latest add button --registry https://acme.dev/r
Or set it once, for every command in the project:
{
"registry": "https://acme.dev/r"
}
NEWT_REGISTRY_URL does the same thing for a shell session, which is the
convenient form in CI.
A full URL also works in place of a name, which is the quickest way to test a single item before you publish an index:
npx newtui@latest add https://acme.dev/r/styles/default/button.json
Depend on newt/ui
An item’s registryDependencies may name items in your own registry. To build on
top of newt/ui rather than beside it, vendor the components you extend into your
registry with newtui add, then list them as dependencies of your own items —
that keeps a single resolution pass and one copy of each file in the consumer’s
project.