The registry: add, diff and how it stays safe
On this page
BizzPocket publishes small pieces of source code: blocks, shared components, data helpers and setting
traits. bizzpocket add <name> copies the source into your theme. After that it is your code. Use
it as it is, change it, or tweak it. The idea is the same as shadcn/ui: you install source, not a black
box.
Contents: Add · Diff · What the registry holds · Setup · Security: who gets your token
bizzpocket add
bunx bizzpocket add money-price
bunx bizzpocket add money-price products-data # several at once
bunx bizzpocket add hello --overwrite # replace files you have changedadded money-priceWhat it does:
- Looks the names up in the registry. An unknown name stops everything with
UNKNOWN_ITEM. - Also adds anything the item depends on (
registryDependencies), so you get a working set. - Checks the whole plan before writing anything. If one file is unsafe or changed, nothing is written.
- Writes the files into your theme and records them in
bizzpocket.json.
Where files go:
| Item kind | Copied to |
|---|---|
block |
blocks/<name>/<file> |
component |
components/<name>/<file> |
data |
data/<name>.ts |
trait |
traits/<name>.ts |
bizzpocket.json
{
"registry": { "name": "@bizzpocket/blocks", "version": "0.1.0" },
"items": {
"money-price": {
"version": "0.1.0",
"files": { "components/money-price/money-price.tsx": "fb52e883a918...(a sha-256 of the file as installed)" }
}
}
}It records what you installed and a fingerprint of each file as it was installed. Commit it. It lets
add and diff tell your changes from the registry's.
If you changed the file
Run add again for an item whose files you edited and you get:
MODIFIED_FILE: data/products-data.ts has local changes; re-run with --overwrite to replace itYour work is not lost. Use --overwrite only when you want the registry's version back. Running add
again on an item you have not changed is harmless.
Packages the item needs
Items list the npm packages they use (for example @bizzpocket/theme). add does not install them.
Make sure they are in your package.json.
bizzpocket diff
diff shows how the registry's current version differs from the copy in your theme. It only reads and
prints. Nothing is changed and nothing is run.
bunx bizzpocket diff # every installed item
bunx bizzpocket diff products-data # one item--- a/data/products-data.ts
+++ b/data/products-data.ts
@@ -4,3 +4,4 @@
export const productsData = ({ collection, count }: { collection: string; count: number }) => ({
items: products({ collection, first: count }),
});
+// mine- Lines starting with
-are in the registry and not in your file. - Lines starting with
+are in your file and not in the registry (your changes). - No output means your file is the same as the registry's.
diff some-namefor something you never installed givesNOT_INSTALLED.
To take an upstream change, read the diff and copy the lines you want by hand, or run
add <name> --overwrite if you have no changes of your own to keep.
What the registry holds
Today (@bizzpocket/blocks 0.4.0) the registry has 38 items. Four are hand-written and 34 are
generated from the toyshop theme:
| Kind | Count | Items |
|---|---|---|
block |
20 | hello and group (a CSS-only container for other blocks, group.md), both hand-written, and 18 from toyshop: breadcrumbs, cart, category-showcase-by-age, category-showcase-by-category, collection-cards, content-page, footer, grid-best-sellers-toyshop, header, hero, login-form, newsletter, not-found, policy-content, product-detail-fashion, promo-banner, signup-form, testimonials |
component |
14 | money-price (hand-written) and 13 from toyshop: add-to-cart, customer-auth, discount-handoff, home-products, json-ld, paths, pick-categories, price, product-image, safe-url (requireSafeUrl), store-home, store-query, variant-picker |
0.3.0 dropped the responsive-image component and the copied URL checks: responsiveImage, isSafeUrl,
isSafeMediaUrl and toSafeUrl are @bizzpocket/theme exports now (data.md).
A theme that installed the old components/responsive-image keeps working; switch its imports to
@bizzpocket/theme and delete the folder.
| data | 1 | products-data: a function that returns a products() need for a block with collection and count fields (hand-written). |
| trait | 3 | spacing, color-scheme, typography (generated) |
A note on products-data: it is a plain function that calls products(...). A block that calls it
inside data() becomes runtime, not static, because only bare calls of the built-in helpers are
static (data.md). Copy the one line into your block instead, or
use the function in load().
Where the toyshop items come from
The toyshop items are generated, never edited by hand. The toyshop theme
(packages/themes/toyshop) is the source of truth, so add installs exactly what the toyshop test
suite covers:
bun packages/blocks/scripts/sync-toyshop.ts # regenerate registry/items and registry.json
bun packages/blocks/scripts/sync-toyshop.ts --check # exit 1 if anything is out of date or impure--check fails when an item differs from what toyshop would generate (or is stale), when an item
imports anything except @bizzpocket/theme, @bizzpocket/theme/client, react and its own
components, and when its CSS has an unguarded custom property (below). The registry tests run it too.
Eight toyshop blocks (shop listing, filter rail, account area) still lean on theme-sdk helpers and are
skipped. To change an item, change toyshop (or the generator) and regenerate. The four hand-written items
(hello, money-price, products-data, group) are the generator's SEEDED list: it leaves them alone
but checks them for purity too.
The generator rewrites the theme scope [data-theme="toyshop"] to [data-theme], so the styles apply
under any theme's wrapper, and it prepends the shared toyshop class rules a block uses.
Required CSS custom properties
Item CSS reads your theme's tokens as CSS variables. Three groups need nothing from you, because every
theme defines them through its theme() config: --colors-*, --fonts-* and --radii-*. Everything
else is written with a fallback, so the item still looks right in a theme that does not define it:
| Variable | Fallback |
|---|---|
--ts-on-media-ink |
#fff (text over a photo and its dark scrim; hero, promo-banner, category-showcase-by-category) |
--spacing-page-x / --spacing-section-y / --spacing-block-gap |
clamp(1rem, 4vw, 3rem) / clamp(2.5rem, 6vw, 5rem) / clamp(1.25rem, 3vw, 2rem) |
--motion-fast / --motion-medium / --motion-slow |
200ms / 300ms / 500ms |
--shadows-sm / --shadows-md / --shadows-lg |
toyshop's light-mode shadows |
Define these in your theme to override the fallbacks. A fallback is only used when the variable is undefined, so toyshop itself renders as before.
Setup
add and diff find the registry in this order:
- Inside the BizzPocket repository (the CLI runs from a checkout, or your theme sits inside one),
the registry folder
packages/blocks/registryis used directly. - Otherwise the npm package
@bizzpocket/blocksis downloaded from your registry.
For the second case, tell your package manager where the BizzPocket registry is. Put this .npmrc in
your theme folder:
@bizzpocket:registry=https://npm.bizzpocket.com
//npm.bizzpocket.com/:_authToken=${NPM_TOKEN}- The registry line can be
@bizzpocket:registry=...orregistry=.... With neither, the default ishttps://npm.bizzpocket.com. - The token line is only needed if your registry access needs one. The token is read from an
environment variable, never written into the file. Only
NPM_TOKEN,BIZZPOCKET_NPM_TOKENandVERDACCIO_TOKENmay be named in.npmrc; any other${NAME}is refused withINVALID_REGISTRY. The rule is absolute:.npmrcmay only referenceNPM_TOKEN,BIZZPOCKET_NPM_TOKENorVERDACCIO_TOKEN. Note: the CLI only checks this on the token line it is about to send. A token line for another host, or one that is skipped because the host is not trusted, is never read, so the error appears only when that token would really be used. - The registry address itself cannot contain
${...}.
If the package cannot be found (wrong address, no access, no network) you get REGISTRY_NOT_FOUND.
Security: who gets your token
A theme folder is untrusted input: it may come from a stranger. Its .npmrc and even a .env
file next to it could try to trick the CLI into sending your registry token somewhere else. The CLI
therefore follows a few strict rules. In plain words:
1. Only known hosts get the token.
The token goes to npm.bizzpocket.com and to nothing else, unless you name another host on the command
line:
bunx bizzpocket add money-price --trust-registry registry.mycompany.com--trust-registry takes a bare host name (no https://, no port, no path) and can be repeated. Nothing
else can add trust: not an environment variable, not .npmrc, not .env, not any file. If the host is
not trusted, the CLI still downloads (anonymously), and prints a warning that it ignored your token.
2. Only over a safe connection.
Tokens are sent over https on the normal port. The one exception is plain http to localhost,
127.0.0.1 or [::1], and only if you also trusted that host.
3. Not when something may be listening in the middle.
If a proxy variable (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, in any letter case) or
NODE_TLS_REJECT_UNAUTHORIZED is set, the token is withheld and the CLI warns. Bun loads a .env
file from the folder you run in, so a stranger's theme could use one of these variables to route your
token through their server. If you really are behind a proxy you trust, add --allow-proxy:
bunx bizzpocket add money-price --allow-proxyIt still prints a warning. Certificate checking stays on for every request, and the token is never sent
over plain http through a proxy.
4. Never with a custom certificate authority.
If NODE_EXTRA_CA_CERTS, SSL_CERT_FILE or SSL_CERT_DIR is set, the token is always withheld,
and --allow-proxy does not change that. A planted certificate authority would make an interceptor
look legitimate. Unset the variable to authenticate.
5. Only to the registry's own address. The token is attached only to requests to the registry's origin, and a redirect on such a request is an error instead of being followed. So it cannot be forwarded to a tarball on another host.
6. The download is checked.
The package is verified against the registry's sha512 (or sha1) checksum before anything is read.
7. Files stay inside your theme.
Item names and file paths are checked. A path that leaves the theme folder, goes through a symlink, or
uses a reserved Windows name is refused with UNSAFE_PATH. Files are written safely (to a temporary file
first, then renamed), and add and diff never run any of the code they copy.
If a withheld token means the registry refuses you, the symptom is REGISTRY_NOT_FOUND. Read the warning
printed just above it: it names the variable.
Next: migrate.md.