Skip to content
shadcn registry

Arrecho UI

The commerce design system every Arrecho storefront installs from — tokens, components, whole pages, and full-stack addons, served as source you own rather than a package you depend on. Change a token once and it updates everywhere.

What ships

6 layers and 108 items, each layer consuming the one above it. Everything lives under one namespace, so a single line of config reaches all of it.

Tokens
foundation + 11 themes

Brand-invariant structure lives in @arrecho/foundation; a theme supplies values only, so one registry dresses many brands.

Primitives
44 components

Button, dialog, table, field, sidebar — built on Base UI, drawn entirely from the tokens, never a hard-coded color.

@/components/ui/<name>

Sections
9 sections

Full-width page sections — hero, feature row, testimonial, newsletter. Domain-neutral and prop-driven, so a section is reusable rather than a thing you gut.

@/components/sections/<name>

Ecommerce kit
16 components

The storefront's own vocabulary — product card, price, variant picker, cart line, order summary. Part of the ecommerce addon rather than a tier of its own: these are the pieces its pages are built from.

@/components/ecommerce/<name>

Blocks
0 pages

Whole pages, composed from sections. Installing one writes a route; the layout it uses stays installable on its own.

app/<route>/page.tsx

Addons
schema + actions + UI

Full-stack features: a Drizzle table, guarded server actions, and the UI that drives them. One install lands a working feature.

@/components/<addon>/*, @/server/<addon>/*

Point an app at it

// components.json
{ "registries": { "@arrecho": "https://registry.arrecho.tech/r/{name}.json" } }
pnpm dlx shadcn@latest add @arrecho/foundation @arrecho/gruvbox
pnpm dlx shadcn@latest add @arrecho/product-card
pnpm dlx shadcn@latest add @arrecho/checkout

Always with the @arrecho prefix — a bare shadcn add button resolves to shadcn's own registry and installs the Radix component instead of the Base UI one these apps are built on.

Using it

Installing writes source into your app. From there it is yours — imported by path, styled through tokens, and updated only when you ask.

Then import it

The item name and the import path are not the same thing. An item installs into the directory its type implies, resolved through the aliases in your components.json — so @arrecho/price lands at @/components/ecommerce/price, not at @/price.

import { Button } from "@/components/ui/button";
import { ProductCard } from "@/components/ecommerce/product-card";
import { Hero } from "@/components/sections/hero";
import { money, formatMoney } from "@/lib/money";

// Prices are Money — integer minor units with the currency attached,
// so a cart total cannot drift and a euro store cannot render dollars.
<ProductCard title="Country Sourdough" price={money(900, "USD")} />;

Changing how it looks

Five tiers, least invasive first. Reach for the lowest one that works — the lower it is, the longer the component keeps receiving updates.

  1. 1. Brand token

    Swap values — colors, --radius, --shadow-color, fonts. Every token-driven component re-skins at once. Squared vs rounded is one variable.

  2. 2. Component variant

    Use the variant or size the component already ships. No new CSS, no new file.

  3. 3. className at the call site

    cn() runs tailwind-merge, so a class you pass in beats the component's own.

  4. 4. Wrapper component

    Re-export a wrapped version to set app-wide defaults without touching the original.

  5. 5. Own the copy

    Edit the installed source. That file then diverges from the registry and stops tracking it — which is a legitimate choice, just a deliberate one.

Only the last one forks the file. Everything above it survives a re-install, and pnpm ui:check in your app will tell you which of your copies have drifted, and by how many versions.

Where to look

Three places, and they don't overlap: the catalog documents components, this site runs the pages, the harness proves the full-stack addons.

Storybook
The component catalog: every primitive and commerce component, a story per state, with accessibility and interaction checks. It needs no database.
pnpm storybook
Page blocks
The blocks run as real routes on this site — browse a storefront end to end, then install any page you like the look of.
Addon harness
/demo/admin-crud runs the installed addon against a real Postgres, behind the same admin guard a consuming app uses — the part stories can't prove. Needs the local database and an admin sign-in.

Page blocks

Full pages composed from the primitives and commerce components. Each one is live here and installable by name.

  • The cart surface: line items with live re-pricing, free-shipping progress, order summary, and a recommendation shelf. Installs the route and the view it renders.
    @arrecho/ecommerce-cart-ui
  • Checkout and order confirmation. The form collects contact, address and delivery method, then places a pending order; the confirmation reads it back by token, so a guest can see their receipt without an account.
    @arrecho/ecommerce-checkout-ui
  • Checkout and order confirmation. The form collects contact, address and delivery method, then places a pending order; the confirmation reads it back by token, so a guest can see their receipt without an account.
    @arrecho/ecommerce-checkout-ui
  • The shopping surfaces: homepage, product listing with server-side filtering and paging, and a product detail page with variant selection. Installs three routes and the views they render.
    @arrecho/ecommerce-storefront-ui
  • The shopping surfaces: homepage, product listing with server-side filtering and paging, and a product detail page with variant selection. Installs three routes and the views they render.
    @arrecho/ecommerce-storefront-ui
  • The shopping surfaces: homepage, product listing with server-side filtering and paging, and a product detail page with variant selection. Installs three routes and the views they render.
    @arrecho/ecommerce-storefront-ui

Every block, with the route it installs to, is on the blocks page.

Design tokens

The whole system reduces to these values. They are generated from themes/*.mjs into CSS variables, so everything below is drawn from the same source the components read — switch the theme in the header and every swatch re-skins live.

Primary

primary
secondary
accent

Surfaces

background
card
popover
muted

Semantic

success
warning
destructive
info

Commerce

sale
out-of-stock

sale must read as the primary price; out-of-stock pairs with clear text — never color alone.

Chart accents

chart-1
chart-2
chart-3
chart-4
chart-5

Typography

Named styles — use the utility class, not an ad-hoc text-* stack, so type stays consistent. A brand swaps in its own heading and body typefaces through the same token map.

UtilitySample
displayArrecho UI
heading-lgSection heading
heading-mdSub-section
bodyBody copy — the quick brown fox jumps over the lazy dog.
body-smSmaller body copy for dense areas.
metaProduct metadata · SKU 4471 · Ships in 3 days
labelFree shipping
product-titleCountry Sourdough — 24-hour cold ferment

Price styles

price$24.00
price-lg$24.00
price-sale + original$18.00$24.00
unit / from$4.50/ lb

Radius & shadow

Corner softness and shadow warmth are what separate handmade from clinical, and both are one value per brand — radius steps scale off --radius, shadows tint with --shadow-color.

Radius scale

rounded-sm
rounded-md
rounded-lg
rounded-xl
rounded-2xl
rounded-3xl

Shadow scale

soft-sm
soft-md
soft-lg
Tokens are generated from themes/*.mjs — the single source of truth. Edit a theme there and rerun pnpm themes; never edit the generated CSS.