Versioning and drift
How items are versioned, how an app pins a release, and how the lockfile catches silent edits.
Item versions
Every item has its own semantic version in meta.version of its item.json, and its own CHANGELOG.md next to it. The registry build refuses an item whose changelog has no entry for its version.
| Change | Bump |
|---|---|
| Fixes a bug without changing how the item is used or how it looks | patch |
| Adds a prop, a variant or a token; existing screens look the same | minor |
| Renames or removes anything, or changes how an existing screen looks | major |
Items stay below 1.0.0 until nalarx-frontend runs on them. Before 1.0.0, a breaking change bumps the minor version.
Changelog entries are written for the people who install the item: what changed on screen or in usage, in plain words.
Release tags
| Tag | Points at | Example |
|---|---|---|
v<semver> | A release of the whole registry (public/r at that commit) | v0.1.0 |
<item>@<semver> | The commit that released that item version | theme@0.1.0 |
The repo version in package.json is the registry release. Bump it whenever any item changes, tag the commit v<version>, and add an <item>@<version> tag for each item that changed.
Pinning a release
public/r is committed, so every tag is a complete snapshot of the registry. An app pins a release by putting the tag in its @nalarx URL:
{
"registries": {
"@nalarx": {
"url": "https://raw.githubusercontent.com/<org>/nalarx-ui/v0.1.0/public/r/{name}.json",
"headers": { "Authorization": "Bearer ${GITHUB_TOKEN}" }
}
}
}Pin the whole namespace rather than single items. Items depend on each other as @nalarx/<item>, and the shadcn CLI resolves those through the same URL, so one pin keeps every dependency on the same release. The shadcn CLI can also install a single GitHub item at a ref (<org>/nalarx-ui/theme#theme@0.1.0), but its dependencies then follow the app's @nalarx URL, which is why the namespace pin is the default.
When a hosted registry exists, its deploy should also publish each release under /r/v<semver>/, so https://<host>/r/v0.1.0/{name}.json works without a GitHub token.
The lockfile
@nalarx/drift-check installs scripts/nalarx-ui-drift.ts. record writes nalarx-ui.lock.json:
{
"lockfileVersion": 1,
"registry": "@nalarx",
"items": {
"base": {
"version": "0.1.0",
"files": {
"src/components/ui/nx/lib/cn.ts": "sha256:…",
"src/styles/nalarx-ui/nx.css": "sha256:…"
}
}
},
"overrides": {
"src/components/ui/nx/lib/cn.ts": "Adds a local class order fix until nalarx-ui ships it (NAL-123)."
}
}record [item...]fetches each item from the@nalarxURL, follows its@nalarx/*dependencies, finds the installed files throughcomponents.jsonaliases andtsconfigpaths, and stores the version and a sha256 of each file. With no names it re-records everything already in the lockfile.checkhashes every recorded file and exits 1 when one is missing or changed. Files underoverridesare skipped, and each override must say why.outdatedprints each recorded item with the registry's current version.
Fingerprints ignore line endings (CRLF and LF hash the same). Run the formatter before record.
Updating an item
bunx shadcn@latest add @nalarx/base --overwrite
bun scripts/nalarx-ui-drift.ts record baseRead the item's changelog first, then review the diff like any other change.