23rd is an open-source shadcn/ui registry of tasteful, opinionated UI components. Copy what you need, paste into your app, and ship, without fighting a kitchen-sink design system.
Site: 23rd.dev · Docs: 23rd.dev/docs
Most kits hand you every option. 23rd picks a direction: spacing, motion, and interaction patterns that already feel finished. You can still override anything; you just start from a sharper baseline.
- shadcn-native: install with the CLI, own the source in your repo
- Opinionated defaults: less boilerplate, clearer decisions
- React and Svelte 5: every published registry item ships for both; pick a framework on the install command
Install a component (React):
pnpm dlx shadcn@latest add @23rd/gooey-color-pickerSvelte 5 (lands in src/lib/components/ui/):
pnpm dlx shadcn@latest add @23rd/gooey-color-picker-svelteOr pull straight from GitHub:
pnpm dlx shadcn@latest add radiumcoders/23rd.dev/gooey-color-pickerThe 23rd agent skill teaches a coding agent every published registry component: which one fits, how to install it for React or Svelte, and the props that actually exist. It also knows when not to use a component.
npx skills add radiumcoders/23rd.dev --skill 23rdGlobal install:
npx skills add radiumcoders/23rd.dev --skill 23rd -gskills/23rd/ is the copy the skills CLI discovers. .cursor/skills/23rd/ is the same skill for Cursor /23rd in this repo. Docs: 23rd.dev/docs.
| Component | Install | Description |
|---|---|---|
| ASCII Fluid | @23rd/ascii-fluid |
Mouse-trail WebGL fluid quantized to a clean ASCII brightness ramp |
| ASCII Logo | @23rd/ascii-logo |
Interactive ASCII wordmark: hover shove, then click to scatter, drop, and gather |
| Dithered 404 | @23rd/dithered-404 |
Bayer-pixel 404; a fireball cursor scorches it into embers and smoke, then it reforms |
| Folio | @23rd/folio |
The page leans back in perspective while you scroll, blurs, then springs flat |
| Gooey Color Picker | @23rd/gooey-color-picker |
Floating swatch → hue wheel, alpha, hex, joined by an SVG gooey filter |
| Live Orb | @23rd/live-orb |
An evenly lit sphere with two capsule eyes that follow the pointer |
| Logo Burst | @23rd/logo-burst |
Hair-line tentacles explode from the center, then breathe, light and dark |
| Phosphor Score | @23rd/phosphor-score |
Vertical CRT sheet music; notes fall, bloom at the playhead, then exit in a flare |
| Radiant Lines | @23rd/radiant-lines |
Hyperspace starfield background; warp speed driven by scroll |
| Ring Tower | @23rd/ring-tower |
A three.js tower of tilted image bands; drag to spin, neighbors counter-turn |
| Shader Anime Fire | @23rd/shader-anime-fire |
Cel-shaded flames licking up from the bottom of a landing hero |
| Shader Gradient | @23rd/shader-gradient |
Quiet WebGL wash behind landing heroes, empty states, and marketing sections |
| Shader Sky | @23rd/shader-sky |
Clear blue or rain behind a hero; drifting clouds, optional window-glass film |
| Shader Metal | @23rd/shader-metal |
Liquid chrome, gold, or copper ribbons; the key light follows the pointer |
| Stretchy Footer | @23rd/stretchy-footer |
Dia-style rubber overscroll; aurora stretches past the bottom, then snaps back |
| Typewriter | @23rd/typewriter |
A playable typewriter in SVG; keys press, typebars strike, the carriage steps |
import { GooeyColorPicker } from "@/components/ui/gooey-color-picker"
export function Example() {
return (
<GooeyColorPicker
defaultValue={{ h: 210, s: 90, l: 55, a: 1 }}
onChange={(color, css) => console.log(color, css)}
/>
)
}Svelte:
<script>
import GooeyColorPicker from "$lib/components/ui/gooey-color-picker.svelte"
</script>
<GooeyColorPicker
defaultValue={{ h: 210, s: 90, l: 55, a: 1 }}
onChange={(color, css) => console.log(color, css)}
/>This repo is the docs site and registry source.
pnpm install
pnpm devUseful scripts:
| Script | What it does |
|---|---|
pnpm dev |
Next.js dev server |
pnpm build |
Build registry, OG cards, and the production app |
pnpm preview |
Build with OpenNext and preview in the Workers runtime |
pnpm cf:deploy |
Build with OpenNext and deploy to Cloudflare Workers |
pnpm cf:upload |
Build with OpenNext and upload a preview version |
pnpm registry:build |
Emit public/r/*.json from registry/ |
pnpm test |
Registry, Svelte compile, OG, and sponsors tests |
pnpm typecheck |
MDX + TypeScript check |
pnpm lint |
ESLint |
Stack: Next.js 16, React 19, Fumadocs, Tailwind CSS 4, shadcn/ui (Base UI), Cloudflare Workers (OpenNext).
pnpm cf:deployGitHub Actions deploys production on push to main. Opening a PR uploads a preview version (production is untouched) and comments a stable URL, the same idea as Vercel preview deployments:
https://pr-<number>-23rd-dev.<subdomain>.workers.dev
That alias stays put as you push more commits to the same PR. Preview URLs live on workers.dev; they are public unless you later put Cloudflare Access in front of them.
You can get the same PR comments from Workers Builds instead: connect the repo in the Cloudflare dashboard, set the deploy command to pnpm cf:deploy, the non-production command to pnpm cf:upload, and enable Builds for non-production branches. Don’t run both Workers Builds and this GitHub Action for the same events or you’ll double-deploy.
Point 23rd.dev DNS at the Worker when you’re ready to cut over from Vercel.
The sponsors page is the same empty-slot board as shadscan: Diamond $250/mo, Platinum $100/mo, Gold $50/mo, Silver $20/mo. Live Creem payment links are wired, so empty slots open checkout.
- Sign up at creem.io and open the dashboard.
- Leave Test Mode on (sidebar toggle) while you wire this up. Test and live products/keys are completely separate.
- Complete store details if the dashboard asks for them. Live payouts later need KYC/KYB under Balances → Payout Account.
In Products, create one recurring / every-month / USD product per tier:
| Product name | Price | Env var |
|---|---|---|
| 23rd Diamond | $250 | CREEM_SPONSOR_DIAMOND_CHECKOUT_URL |
| 23rd Platinum | $100 | CREEM_SPONSOR_PLATINUM_CHECKOUT_URL |
| 23rd Gold | $50 | CREEM_SPONSOR_GOLD_CHECKOUT_URL |
| 23rd Silver | $20 | CREEM_SPONSOR_SILVER_CHECKOUT_URL |
On each product, set the success URL to https://23rd.dev/sponsors/thanks (or http://localhost:3000/sponsors/thanks in test). Click Share and copy the payment link (https://www.creem.io/payment/prod_...).
You can do the same from the Creem CLI after creem login --api-key creem_test_...:
creem products create \
--name "23rd Diamond" \
--description "Monthly Diamond sponsorship: logo, link, and release notes." \
--price 25000 \
--currency USD \
--billing-type recurring \
--billing-period every-month \
--tax-category saasPrices are in cents (25000 = $250.00). Repeat for 10000, 5000, and 2000.
Live payment links are already in wrangler.jsonc, .env.example, .dev.vars.example, and the fallback in lib/sponsors.ts.
Local Next.js (pnpm dev): copy .env.example → .env.local.
Local OpenNext/Wrangler (pnpm preview): copy .dev.vars.example → .dev.vars.
A Cloudflare Worker secret with the same name overrides the wrangler.jsonc var:
npx wrangler secret put CREEM_SPONSOR_DIAMOND_CHECKOUT_URL
npx wrangler secret put CREEM_SPONSOR_PLATINUM_CHECKOUT_URL
npx wrangler secret put CREEM_SPONSOR_GOLD_CHECKOUT_URL
npx wrangler secret put CREEM_SPONSOR_SILVER_CHECKOUT_URLPaste the matching https:// payment link when prompted. Redeploy after changing a secret.
New components live under registry/<name>/ with a vanilla engine, React/Svelte wrappers, and a registry.json (React item plus <name>-svelte), then get documented in content/docs/components/. Run pnpm registry:build before shipping registry changes.
PRs that sharpen defaults, fix edge cases, or add tasteful components are welcome.
Made by radiumcoders (Jay).