shadcn/ui
Use shadcn/ui components in your NukeJS project. Because NukeJS doesn't use RSC, setup takes a few manual steps — but the CLI handles everything after that.
shadcn/ui is a collection of accessible, composable components you copy directly into your project. Since NukeJS doesn't use React Server Components in the RSC sense, follow the manual installation path rather than a framework-specific preset.
1. Install Tailwind CSS
shadcn/ui is styled with Tailwind CSS. If you haven't set it up yet, follow the Tailwind CSS guide first, then come back here.
2. Install dependencies
npm install shadcn class-variance-authority clsx tailwind-merge lucide-react tw-animate-css3. Configure path aliases
shadcn/ui uses @/ path aliases. Add them to your tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
}
}4. Configure styles
Add the shadcn CSS variables to your global stylesheet. In NukeJS, that lives at app/public/main.css:
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";
@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--radius-sm: calc(var(--radius) * 0.6);
--radius-md: calc(var(--radius) * 0.8);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) * 1.4);
}
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
}
@layer base {
* { @apply border-border outline-ring/50; }
body { @apply bg-background text-foreground; }
}5. Add the cn helper
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}6. Create components.json
Create a components.json at the project root. The aliases below match the NukeJS project structure:
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "radix-nova",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "app/public/main.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/app/components",
"utils": "@/app/lib/utils",
"ui": "@/app/components/ui",
"lib": "@/app/lib",
"hooks": "@/app/hooks"
},
"iconLibrary": "lucide"
}Note "rsc": false — NukeJS doesn't use React Server Components in the RSC sense, so this tells the CLI not to add "use client" directives automatically (you'll add them yourself where needed).
7. Add components with the CLI
With components.json in place, the shadcn CLI can install components directly into your project:
npx shadcn@latest add input
npx shadcn@latest add button
npx shadcn@latest add dialogComponents are copied into app/components/ui/ — they're plain TypeScript files you own and can edit freely.
8. Use in a client component
shadcn components use React hooks internally, so any component that imports them must be a "use client" component in NukeJS:
"use client"
import { useState } from "react"
import { Button } from "@/app/components/ui/button"
import { Input } from "@/app/components/ui/input"
export default function ContactForm() {
const [email, setEmail] = useState("")
return (
<form className="flex gap-2">
<Input
type="email"
placeholder="your@email.com"
value={email}
onChange={e => setEmail(e.target.value)}
/>
<Button type="submit">Subscribe</Button>
</form>
)
}Then drop it into any server page — NukeJS will SSR the HTML and hydrate only this component:
import ContactForm from "../components/ContactForm"
export default function Home() {
return (
<main>
<h1>Stay in the loop</h1>
<ContactForm />
</main>
)
}Available components
The full component catalogue — Button, Dialog, Select, Table, and 50+ more — is at ui.shadcn.com/docs/components. Each page includes copy-pasteable code and live previews.