shadcn-parity
Shadcn Parity
Core Contract
When the user asks for shadcn parity, treat ../shadcn as the source of
truth for registry behavior and patterns.
Do not give them "inspired by shadcn". Do not invent a Plate-specific model when upstream shadcn already has one.
The rule is simple:
- upstream schema first
- upstream resolver behavior first
- upstream file/layout patterns first
- upstream namespace semantics first
- Plate divergence only when the repo has a real constraint
Plate does not fork shadcn CLI. Do not talk about Plate as if it owns a custom installer. Plate owns a registry and template sync layer around the upstream shadcn contract.
If you diverge, say exactly why.
Ownership
Shadcn owns the contract:
- registry item schema
- namespace semantics like
@shadcn/buttonand other registry prefixes - resolver behavior for plain items, namespaced items, URLs, and local files
- local-file add behavior
components.jsonregistry semantics
Plate owns the content and delivery:
- registry source files under
apps/www/src/registry/* - registry build logic in
apps/www/scripts/build-registry.mts - generated registry output under
apps/www/public/randapps/www/public/rd - the
@platenamespace configured in templatecomponents.json - template sync tooling in:
tooling/scripts/update-template.shtooling/scripts/prepare-local-template-registry.mjs
Important boundary:
- shadcn owns how registry items are resolved and installed
- Plate owns what the registry contains and how local template sync feeds it
Plate's registry build is custom. The goal is still upstream parity at the item and resolver boundary.
Registry Rules
Registry items should stay as close as possible to upstream RegistryItem
shape.
When building or changing Plate registry items:
- check
../shadcnfirst - copy upstream file/layout/helper patterns when they fit
- prefer upstream naming and dependency structure over Plate-specific novelty
- keep dynamic Plate-specific behavior in build or sync tooling, not in a fake registry data model
Registry dependency rules:
- prefer
@shadcn/*when an upstream shadcn item exists - prefer upstream namespace syntax over raw URLs when the namespace already covers the case
- if upstream does not expose a small standalone item, use a small Plate registry item instead of dragging in a huge upstream dependency just to steal one internal file
- do not expand compatibility hacks into new conventions
Do not fork shadcn CLI to compensate for Plate registry problems. Fix the registry data or the Plate sync tooling instead.
Template Rules
For template installs, shadcn CLI is still the installer. Plate supplies the registry.
Template rules:
- keep
templates/*/components.jsonaligned with shadcn registry semantics - treat
@plateincomponents.jsonas the install entrypoint for Plate items - prefer registry fixes over template-only patches when generated output is wrong
- compare Plate output against
../shadcnbefore inventing a custom rule
For local template sync:
--localuses local-file mode, not localhost- local sync works by preparing a JSON mirror from
apps/www/public/rd - local sync exists to feed upstream shadcn local-file install flow, not to replace it
If a change would make public installs cleaner but would break local-file sync, call that out and fix both sides together.
Current Divergences
These are real Plate divergences today. Treat them as constraints, not as a pattern to spread.
- Plate publishes a registry from
apps/www, not from upstream shadcn infrastructure - local template sync uses prepared JSON mirrors and local-file mode
- template install entrypoints use the
@plateregistry incomponents.json - some built registry output may still emit absolute Plate self-URLs for compatibility; treat that as behavior to minimize, not a new model to copy
Red Flags
Stop and reassess if you are about to do any of this:
- describe Plate as a fork of shadcn CLI
- invent a new Plate-only registry schema
- replace upstream namespace behavior with raw URL sprawl
- solve a registry issue by adding more installer logic when the data is wrong
- patch templates by hand without checking whether the registry source is the real problem