Install
Set up the Redpanda UI Registry in your project, then install components.
Prerequisites
Install @base-ui/react in your app before running shadcn add. Registry components import
from @base-ui/react@^1.8.0, and the peer dep must be present in your package.json:
bun add @base-ui/react@^1.8.0
# npm install @base-ui/react@^1.8.0
# pnpm add @base-ui/react@^1.8.0Project setup
You only need to do this once per project.
1. Create a components.json file
Create a components.json file at the root of your application or project:
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/globals.css",
"baseColor": "neutral",
"cssVariables": true
},
"aliases": {
"components": "@/components/redpanda-ui",
"utils": "@/components/redpanda-ui/lib/utils",
"ui": "@/components/redpanda-ui",
"lib": "@/components/redpanda-ui/lib",
"hooks": "@/components/redpanda-ui/lib"
},
"iconLibrary": "lucide",
"registries": {
"@redpanda": "https://redpanda-ui-registry.netlify.app/r/{name}.json"
}
}Adjust the aliases paths if your project uses a different base directory for UI components.
2. Install and configure Tailwind CSS
The UI Registry uses Tailwind CSS for styling. You'll need to configure the Tailwind compiler in your project.
bun add tailwindcss tw-animate-css
bun add @tailwindcss/postcss -DThen, create a postcss.config.mjs file at the root of your application or project.
export default {
plugins: {
'@tailwindcss/postcss': {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
},
},
};3. Install the theme and import styles
bunx shadcn@latest add @redpanda/themeCreate a globals.css file within your project's src directory and add the following:
@import "tailwindcss";
@import "tw-animate-css";
@import "./components/redpanda-ui/style/theme.css"; /* or wherever your aliases point + /style/theme.css */The order matters. theme.css extends Tailwind — @theme, @utility, @custom-variant — and its
@layer base block has to land inside the layer order that @import "tailwindcss" declares, so Tailwind
comes first. If you keep a palette override file of your own, it goes after theme.css: see
Theming your app.
4. Wrap your app in RedpandaProvider
Most registry components rely on a few cross-cutting providers — theme management, a motion/react
MotionConfig, and a global Sonner toaster. The registry ships these pre-wired as the
Redpanda Provider. Install it once and mount it near the root of your app:
bunx shadcn@latest add @redpanda/redpanda-providerimport { RedpandaProvider } from "@/components/redpanda-ui/components/redpanda-provider";
import { ThemeScript } from "@/components/redpanda-ui/components/theme-provider";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
{/* Before anything paints — see below */}
<ThemeScript />
<RedpandaProvider>{children}</RedpandaProvider>
</body>
</html>
);
}RedpandaProvider defaults motion/react to reducedMotion="user", which makes registry
components honor the OS-level prefers-reduced-motion setting. Without it, motion's default
is "never" and animations always play, even for users who have asked for reduced motion.
5. Apply the theme before the first paint
ThemeProvider can only apply the stored theme from its mount effect, which is one paint too late: a
server-rendered page shows the light ground and then flips to dark. ThemeScript is that same resolve
as a blocking inline script — render it inside <head> or as the first thing in <body>, and put
suppressHydrationWarning on <html>, since the script's whole job is to mutate the element the server
rendered. Pass it the same storageKey and defaultTheme as the provider, or the two disagree for one
paint.
A client-rendered app (Vite, CRA) has an entry module that runs before React instead, so call
initTheme there — above createRoot:
import { initTheme, ThemeProvider } from "@/components/redpanda-ui/components/theme-provider";
initTheme({ defaultTheme: "dark", storageKey: "my-app:theme" });
ReactDOM.createRoot(document.getElementById("root")!).render(
<ThemeProvider defaultTheme="dark" storageKey="my-app:theme">
<App />
</ThemeProvider>
);Both write the same three things, which together are what "being in a theme" means: data-theme (what
theme.css keys on), the .dark class (for CSS the theme does not own — a stylesheet you vendored
before the move, or Tailwind's own class-based dark: in your app code), and color-scheme (what the
browser keys on: scrollbars, native form controls, date pickers). Nothing else in your app needs to
set any of them.
Fonts & typography
Installing @redpanda/theme (step 3 above) handles fonts automatically — no Google Fonts link
or manual font setup is needed. The theme package adds the following npm dependencies to your
project and theme.css imports them:
| Package | Fonts provided |
|---|---|
@fontsource/inter (weights 400/500/600/700) | Inter — --font-sans |
inter-ui | InterDisplay — --font-display |
@fontsource/geist-mono (weights 400/500/600) | Geist Mono — --font-mono |
Fonts are self-hosted: they resolve from node_modules through your bundler, so no CDN dependency is introduced.
Install a component
Most projects only need a handful of components. Every registry item is addressable as
@redpanda/<name> — pass one or more names to shadcn add and the CLI copies the source
(plus any dependencies) directly into your project.
Install a single component:
bunx shadcn@latest add @redpanda/buttonInstall several at once — the CLI resolves shared dependencies so nothing is duplicated:
bunx shadcn@latest add @redpanda/button @redpanda/input @redpanda/formEach component's own doc page has a ready-made install snippet — see Button for an example.
Browse and build a command
Pick components by category. The command at the bottom updates live as you tick boxes — copy
it once you've got the set you want. Toggle --overwrite to replace existing local copies.
bunx shadcn@latest add @redpanda/<component>
Install everything
For scaffolding a new app, auditing the full set of components, or maintaining an internal
fork, the registry ships a meta item — @redpanda/all — that depends on every component,
hook, and style. Running the command below is equivalent to ticking every box above.
bunx shadcn@latest add @redpanda/all --overwrite
Prefer installing only what you need for production apps. @redpanda/all pulls in every
component in the registry, which inflates your bundle, dependency graph, and upgrade
surface area. It exists for convenience, not as the recommended default.
Update components
Use add with --overwrite to update a component to the latest version:
bunx shadcn@latest add @redpanda/button --overwriteTo update the entire registry at once:
bunx shadcn@latest add @redpanda/all --overwriteUse diff to see what changed in a component since you installed it:
bunx shadcn@latest diff @redpanda/buttonOther CLI commands
Preview a component's code before installing:
bunx shadcn@latest view @redpanda/buttonSearch for components in the registry:
bunx shadcn@latest search --query "form"Migrating from fumadocs/cli
If you previously used @fumadocs/cli with a cli.json file, run the migration script:
bash <(curl -fsSL https://redpanda-ui-registry.netlify.app/migrate.sh) --cwd .The script reads your existing cli.json, generates components.json with the correct aliases and @redpanda registry, deletes cli.json, and prints reinstall commands for all detected components.
Or migrate manually:
- Create
components.jsonas shown above (use your existingcli.jsonbaseDirto set thealiasespaths) - Delete
cli.json - Install new components with
bunx shadcn@latest add @redpanda/<name>instead ofbunx @fumadocs/cli add --dir ...
Your existing installed component files will continue to work as-is. No changes needed to already-installed code.