Shadcn/ui
Build extension UI with accessible, composable components using the same shadcn/ui workflow used in web apps. This is useful when your team wants reusable design primitives instead of custom ad-hoc UI per surface.
Extension.js supports shadcn/ui best through a Tailwind-enabled React setup.
When shadcn/ui is a good fit
- You need reusable UI primitives across sidebar, popup, and options surfaces.
- You already use React + Tailwind in product code.
- You want source-owned components that your team can fully customize.
shadcn/ui capabilities
| Capability |
What it gives you |
| Source-owned UI components |
Keep generated components/ui/* files versioned in your project |
| React + Tailwind alignment |
Use the same authoring model as modern web app stacks |
| Extension-surface reuse |
Share component primitives across sidebar, popup, and options pages |
| Gradual adoption |
Start from a template, then scale component coverage over time |
Template examples
Use the sidebar-shadcn template as the default starting point:

npx extension@latest create my-extension --template=sidebar-shadcn
This template includes a working React sidebar UI with Tailwind + shadcn-style component structure.
Repository: examples/sidebar-shadcn
Stack assumptions
- React + TypeScript
- Tailwind CSS
- PostCSS (
@tailwindcss/postcss)
- Local
components/ui/* component files (shadcn-style structure)
Manual setup in an existing project
- Set up Tailwind and PostCSS (see Tailwind CSS).
- Initialize shadcn in your project and generate components.
- Keep generated UI components inside your extension source (for example
src/components/ui/).
- Import your Tailwind stylesheet in the extension entry where UI renders.
PostCSS example (Tailwind v4)
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
Example components.json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"tsx": true,
"tailwind": {
"css": "sidebar/styles.css",
"cssVariables": true
}
}
Usage
Use generated components from local imports:
import { Button } from "@/components/ui/button";
import "./styles.css";
export default function MyComponent() {
return <Button className="text-lg font-semibold">Click Me</Button>;
}

Content script notes
- Extension pages (popup/options/sidebar/new tab) are the easiest place to start with shadcn/ui.
- For content scripts, ensure your style entry is imported in the content-script entrypoint.
- Content-script styles are emitted through Extension.js content-script CSS pipeline and can still conflict with host page styles.
If you need stronger isolation for content scripts, prefer mounting inside an isolated root strategy and keep class scopes intentional.
Best practices
- Treat shadcn/ui as source-owned components, not a runtime UI package import.
- Keep Tailwind config/content paths aligned with your extension folders (
pages, scripts, src).
- Start with one surface (like sidebar or popup) before adding content-script rendering complexity.
- Keep shared tokens and utility helpers in dedicated files (
lib/utils, design tokens, theme variables).
Next steps