21st-design-sync

Look at the current project's design (its shadcn / Tailwind CSS variables and color tokens) and publish it to the 21st.dev community as a shareable theme, using `21st publish-theme`. Use when the user says "publish my theme", "share our design as a 21st theme", "sync my design to 21st", "turn my glo

By 21st-dev · 823 installs

npx skills add 21st-dev/skill --skill 21st-design-sync

Source repository · Upstream listing

21st Design Sync — publish your project's design as a theme Take the design a project already ships (its light + dark CSS variables) and publish it to the public 21st.dev theme library so anyone can preview, bookmark, and apply it. Under the hood this is one CLI call: 21st publish theme <file.css name "…" . Pre flight (always) 1. Auth needs a real API key. publish theme is a management endpoint: it accepts a 21st sk … key only , not a 21st login session token. Get one at https://21st.dev/mcp (or https://21st.dev/settings/api keys ) and pass it via api key 21st sk … or the TWENTYFIRST TOKEN / API KEY 21ST env var. If the user has no key, point them there — don't try to mint one. 2. The CLI is the unified @21st dev/cli (bin 21st ). Use npx @21st dev/cli if it isn't installed. 3. Publishing is public and outward facing. A published theme is immediately is public in the community library (there is no unlisted/private option for themes). Confirm with the user before publishing. Step 1 — Find the project's design tokens Locate the file that defines the shadcn/Tailwind theme variables. Check, in order: app/globals.css , src/app/globals.css src/index.css , styles/globals.css , app/styles/globals.css You're looking for a :root { … } block of CSS custom properties ( background , foreground , card , primary , secondary , muted , accent , destructive , border , input , ring , the chart / sidebar tokens, radius ) and a matching .dark { … } block. Values may be hsl(...) , oklch(...) , hex, or raw channels — keep them exactly as the project wrote them. Tailwind v4 projects usually keep the same :root / .dark blocks plus an @theme inline mapping; you only need the :root and .dark token values, not the @theme mapping. Step 2 — Assemble a valid theme CSS file The publish endpoint parses name: value; pairs out of a :root { … } block and a .dark { … } block, and requires both to be non empty . So the file you publish must contain both. Copy the project's :root and .dark blocks into a standalone file (e.g. project theme.css ). Nothing else is required. If the project has only a light :root and no .dark (or an empty one), generate a dark variant before publishing — don't ship a theme with an empty dark mode. Reuse the add dark mode / oklch skill approach: invert lightness while preserving hue/chroma so the dark set stays on brand. Keep the same token names. Keep the token names shadcn standard so the theme previews correctly on the card and applies cleanly for others. Minimal shape: Step 3 — Name & tag it Name (required, ≤ 50 chars): infer from the project — the product/brand name from package.json , the repo, or the site title. Ask the user if it's ambiguous. Tags (optional): a few descriptors that match how people browse themes, e.g. dark , minimal , neutral , vibrant , saas . Pass comma separated. Step 4 — Publish The command prints the live theme URL ( https://21st.dev/community/themes/<slug ). Share it with the user. Updating vs re publishing Each publish theme creates a NEW theme (there's no upsert by slug like components have). Running it twice = two themes in the library. To change name/tags/visibility on an existing theme, edit it in place: 21st edit <theme id type theme [ name "…"] [ tags a,b] . To change the colors , publish a fresh file and remove the old one: 21st delete <theme id type theme yes (soft unpublish, reversible). When NOT to use this Syncing a component library to a Claude Design project → that's the built in /design sync skill, a different destination. Publishing a component (not a color theme) → use 21st registry .