Skip to content

About

shadcn registry with the Crowdin design tokens and a curated, pinned mirror of shadcn/ui components

Topics

Resources

Code of conduct

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

Crowdin UI Registry

A shadcn registry serving the Crowdin design tokens and a curated, pinned mirror of shadcn/ui components. Component source is pristine upstream shadcn; all Crowdin styling lives in the theme, style, and app-theme items.

Quickstart

Add the registry to your components.json:

{
  "registries": {
    "@crowdin": "https://crowdin.github.io/ui-registry/r/{name}.json"
  }
}

Install the Crowdin style (theme tokens + base CSS), then components:

npx shadcn@latest add @crowdin/style
npx shadcn@latest add @crowdin/button @crowdin/dialog

The registry serves the latest release - changes on main are not published until a release is made.

Theming

@crowdin/theme ships the canonical Crowdin design tokens as plain values - override them in your own CSS like any shadcn theme.

Apps that run inside the Crowdin iframe should also install @crowdin/app-theme. It re-points the tokens at the host --crowdin-* variables and keeps the canonical values as fallbacks so the app still looks right in local development outside the iframe:

npx shadcn@latest add @crowdin/style                       # standalone app
npx shadcn@latest add @crowdin/style @crowdin/app-theme    # app embedded in Crowdin

CSS variables never cross the iframe boundary, so @crowdin/app-theme also installs the host bridge that pulls the palette from the host: lib/crowdin-host.ts (framework-agnostic) and hooks/use-crowdin-theme.ts (React). Wire it once near your app root - it applies the host --crowdin-* variables to <html>, tracks host theme changes, and no-ops outside the iframe:

const mode = useCrowdinTheme() // "light" | "dark" - toggle your .dark class off this

The app must load the Crowdin iframe SDK (https://cdn.crowdin.com/apps/dist/iframe.js) for the bridge to find the AP global; an async script tag is fine - the bridge probes for AP for ~10 seconds after mount before concluding it runs outside the iframe.

Updating components

npx shadcn@latest add @crowdin/button --diff
npx shadcn@latest add @crowdin/button --overwrite

MCP

The registry works with the shadcn MCP server:

npx shadcn@latest mcp init --client claude

Development

pnpm install
pnpm test        # unit tests for the sync helpers and theme/bridge invariants
pnpm sync        # refresh registry/src/ from upstream shadcn (open the diff as a PR)
pnpm validate    # schema-validate registry.json
pnpm build       # emit r/*.json
pnpm smoke       # install everything into a fixture app, typecheck, compile CSS
pnpm site:dev    # run the component showcase locally (one-time: pnpm --dir site install)
pnpm site:build  # typecheck and build the showcase

registry/src/** is generated by pnpm sync - never edit it by hand. Crowdin styling changes go into the theme/style/app-theme items in registry.json. registry/crowdin/** is hand-written (the host-bridge sources shipped by app-theme) and survives sync.

To refresh the components from upstream shadcn, run the Sync upstream workflow from the Actions tab - it syncs, runs the full check suite, and opens a PR with the diff (only when something actually changed). New upstream components are opt-in: add the name to scripts/upstream-items.json first.

The showcase at crowdin.github.io/ui-registry is built from site/ and renders registry/src/** directly with the generated Crowdin theme - use its header toggles to preview dark mode and simulated Crowdin host variables.

About

shadcn registry with the Crowdin design tokens and a curated, pinned mirror of shadcn/ui components

Topics

Resources

Code of conduct

Stars

2 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages