@maholan/registry
v0.3.0
Published
MHL UI component registry — builds JSON served by the CLI
Readme
@maholan/registry
Component registry builder for the MHL Untitled UI Platform. Reads
registry.json (the source manifest), inlines component source files from
packages/ui, and outputs individual JSON files consumed by @maholan/cli.
What This Package Does
This package is a build-time tool — it is not published to npm and has no
runtime exports. Its sole job is to produce the public/r/*.json files that the
CLI fetches when a consumer runs npx @maholan/cli add <component>.
registry.json ← source manifest (edited by humans)
src/build.ts ← build script
│
▼ pnpm build
public/r/
├── index.json ← full registry index
├── button.json ← Button component (source inlined)
├── button-stories.json
└── ... ← one file per registry itemRegistry Manifest (registry.json)
The manifest is the single source of truth for what components exist and where their source files live in the monorepo.
Schema
Each item in items[] follows this shape:
{
"name": "button",
"type": "registry:component",
"title": "Button",
"description": "Accessible button built on React Aria.",
"dependencies": [
"react-aria-components",
"class-variance-authority",
"clsx",
"tailwind-merge"
],
"registryDependencies": [],
"files": [
{
"path": "registry/mhl/button/button.tsx",
"sourcePath": "../ui/src/components/base/buttons/button/button.tsx",
"type": "registry:component"
},
{
"path": "registry/mhl/button/button.variants.ts",
"sourcePath": "../ui/src/components/base/buttons/button/button.variants.ts",
"type": "registry:component"
}
],
"cssVars": {
"light": { "brand-600": "257 90% 58%" },
"dark": { "brand-600": "257 90% 65%" }
}
}Field reference
| Field | Description |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| name | kebab-case identifier — used as the CLI add argument and as the output filename (button.json) |
| type | registry:component for components, registry:file for standalone files (e.g., stories) |
| title | Human-readable display name |
| description | Plain-English description for CLI output and LLM context |
| dependencies | npm packages installed into the consumer project |
| registryDependencies | Other MHL components this one depends on — resolved recursively by the CLI |
| files[].path | Consumer-facing install path (written into the output JSON as-is) |
| files[].sourcePath | Path relative to packages/registry/ to the source file in the monorepo — read at build time and stripped from output |
| files[].target | Optional override for where the CLI writes the file in the consumer project |
| cssVars | CSS custom properties introduced by this component, for both light and dark modes |
sourcePathis a build-time field. It never appears in the built JSON files consumers download. The build script reads the file atsourcePath, inlines its contents as"content", and removessourcePathfrom the output.
Build
# From repo root
pnpm --filter @maholan/registry build
# From this package directory
pnpm buildThe build script (src/build.ts):
- Reads
registry.json - For each item, reads every
sourcePathand inlines the file content - Writes one JSON file per item to
public/r/<name>.json - Writes
public/r/index.jsonwith the full registry index (no file content)
Output Format
public/r/<name>.json (component file)
{
"name": "button",
"type": "registry:component",
"title": "Button",
"description": "...",
"dependencies": ["react-aria-components", "..."],
"registryDependencies": [],
"files": [
{
"path": "registry/mhl/button/button.tsx",
"content": "\"use client\";\n\nimport React from \"react\";\n...",
"type": "registry:component"
}
],
"cssVars": { "light": {}, "dark": {} }
}public/r/index.json (full index)
[
{
"name": "button",
"type": "registry:component",
"title": "Button",
"description": "...",
"dependencies": ["..."],
"registryDependencies": []
}
]Deployment
public/r/ is a static directory — serve it from any HTTP host. The CLI reads
the registry URL from mhl.config.json:
{
"registries": {
"@maholan": "https://mhl-ui.dev/r"
}
}The CLI fetches <registryUrl>/<name>.json for each component:
https://mhl-ui.dev/r/button.json
https://mhl-ui.dev/r/input.jsonVercel (current setup)
vercel.json in this package configures the deployment. The public/r/
directory is served at the root of the deployment.
Adding a New Component
- Create the component in
packages/ui/src/components/<name>/(all 5 files:.tsx,.variants.ts,.stories.tsx,.test.tsx,index.ts) - Add an entry to
registry.jsonwith all fields filled in - Run
pnpm --filter @maholan/registry buildto generate the JSON - Verify
public/r/<name>.jsoncontains the correct inlined source - Commit both
registry.jsonandpublic/r/<name>.json
Related Packages
@maholan/ui— Source of all component files referenced bysourcePath@maholan/cli— Fetches the built JSON files at runtime
