Tailwind CSS
Add Tailwind CSS to a NukeJS project. Because NukeJS controls the HTML pipeline you run Tailwind as a CLI watcher alongside the dev server.
NukeJS intentionally avoids using magic plugins to add features. It keeps everything minimal and simple so it’s easy for everyone to understand.
Install
npm install -D tailwindcss @tailwindcss/cliCreate the CSS entry file
Tailwind v4 uses a CSS-first approach. Create a single file at the project root that imports the framework and adds any global base styles:
@import "tailwindcss";
body {
@apply bg-blue-500;
}The Tailwind CLI reads this file, scans your TSX for class names, and writes the compiled output to app/public/styles.css. Never edit styles.css by hand — it is regenerated on every build.
Start the watcher with middleware
NukeJS loads middleware.ts before every request. Spawn the Tailwind CLI watcher there in development so it runs inside the same nuke dev process — no second terminal required:
import { spawn } from 'child_process'
import type { IncomingMessage, ServerResponse } from 'http'
if (process.env.ENVIRONMENT !== 'production') {
spawn(
'npx',
['@tailwindcss/cli', '-i', './global.css', '-o', './app/public/styles.css', '--watch'],
{ stdio: 'inherit', shell: true }
)
}
export default async function middleware(req: IncomingMessage, res: ServerResponse) {
// your existing middleware logic
}The ENVIRONMENT !== 'production' guard ensures the watcher only runs locally. In production the CSS is compiled by the build script before NukeJS bundles the app.
Update package.json
Add a build script that compiles Tailwind first, then hands off to NukeJS:
{
"scripts": {
"dev": "nuke dev",
"build": "npx @tailwindcss/cli -i ./global.css -o ./app/public/styles.css && nuke build"
},
"devDependencies": {
"@tailwindcss/cli": "^4.2.1",
"tailwindcss": "^4.2.1"
}
}Load the stylesheet in your layout
NukeJS serves everything in app/public/ as static files, so /styles.css resolves directly to the compiled output. Inject it into every page via the root layout:
import { useHtml } from "nukejs"
import React from "react"
export default function Layout({ children }: { children: React.ReactNode }) {
useHtml({
link: [{ rel: 'stylesheet', href: '/styles.css' }],
})
return <>{children}</>
}Use Tailwind classes
With the layout in place, use any Tailwind utility class in your page components:
import { useHtml } from "nukejs"
export default function Index() {
useHtml({
bodyAttrs: {
style: "margin:0;height:100vh;display:flex;justify-content:center;align-items:center;"
}
})
return (
<div className="flex flex-col items-center gap-4 text-center px-6">
<img src="/nuke.png" alt="NukeJS logo" className="w-24 h-24" />
<h2 className="text-3xl font-bold tracking-tight text-white">
Welcome to NukeJS
</h2>
<p className="text-slate-300 max-w-sm text-sm leading-relaxed">
React. Weaponized. — now with utility-first styling.
</p>
<a
href="/docs"
className="mt-2 px-5 py-2.5 rounded-lg bg-indigo-600 hover:bg-indigo-500 transition-colors text-sm font-medium text-white"
>
Read the docs →
</a>
</div>
)
}Tailwind with a client component
Client components use Tailwind classes exactly the same way — as long as the CSS is loaded in the layout, it applies everywhere:
"use client"
import { useState } from 'react'
export default function ThemeToggle() {
const [dark, setDark] = useState(true)
return (
<button
onClick={() => setDark(d => !d)}
className="flex items-center gap-2 px-4 py-2 rounded-lg border border-slate-700 bg-slate-800 text-sm text-slate-200 hover:border-indigo-500 transition-colors"
>
<span>{dark ? '🌙' : '☀️'}</span>
{dark ? 'Dark mode' : 'Light mode'}
</button>
)
}Tailwind v4 eliminates tailwind.config.js entirely. Theme tokens, custom utilities, and source paths all live in your CSS entry file via @theme, @utility, and @source directives.