Tailwind CSS and shadcn/ui
Warlock owns the integration between its Web project layout and these tools.
Tailwind compiles through PostCSS in development and production; shadcn’s CLI
copies components into src/web/ after Warlock prepares the aliases, tokens,
and shared helper it expects.
Install Tailwind CSS
Section titled “Install Tailwind CSS”warlock add tailwindYou do not need to run warlock add web first. The feature installer resolves
Web before Tailwind and then:
- adds
tailwindcssand@tailwindcss/postcssas development dependencies; - creates
src/web/app.csswith@import "tailwindcss";; - creates
postcss.config.mjswith the Tailwind PostCSS plugin; - imports that stylesheet from
src/web/root.tsx.
Tailwind v4 is CSS-first. There is no generated tailwind.config.js and no
content-glob list to maintain. Put tokens and plugins in src/web/app.css:
@import "tailwindcss";
@theme { --color-brand: oklch(0.62 0.19 259); --font-display: "Inter", sans-serif;}Those tokens produce utilities such as bg-brand, text-brand, and
font-display. Use them from any page or layout:
export default function HomePage() { return <h1 className="font-display text-4xl text-brand">Hello</h1>;}Prepare shadcn/ui
Section titled “Prepare shadcn/ui”warlock add shadcnThis one command also resolves Tailwind and Web when they are missing. It adds
the prerequisites that shadcn init normally owns, adjusted for Warlock’s
src/web/ layout:
components.json, withrsc: false, Tailwind v4 configuration, and aliases targetingweb/components,web/lib, andweb/hooks;src/web/lib/utils.ts, exporting thecn()helper;- shadcn’s neutral design tokens in
src/web/app.css; - the
web/*TypeScript path alias; clsx,tailwind-merge,class-variance-authority, andlucide-react.
Warlock prepares the project; shadcn’s own CLI still owns component generation. Add the components you want:
npx shadcn@latest add button cardUse a generated component
Section titled “Use a generated component”The configured aliases place UI components under src/web/components/ui/:
import { Button } from "web/components/ui/button";
export default function HomePage() { return ( <main className="p-8"> <Button>Ship it</Button> </main> );}Generated components are copied into your source tree. They are application code: edit and version them like any other component.
Optional overlay animations
Section titled “Optional overlay animations”Dialogs, menus, tooltips, and sheets work without an animation package; they
appear immediately. To enable shadcn’s enter and exit animations, install
tw-animate-css with your package manager and import it directly below
Tailwind at the top of the stylesheet:
@import "tailwindcss";@import "tw-animate-css";When styles do not appear
Section titled “When styles do not appear”Check the rendered page and the generated project files:
src/web/root.tsxdirectly imports./app.css.- The active PostCSS config registers
@tailwindcss/postcss. src/web/app.cssbegins with the Tailwind import.- shadcn design tokens such as
--color-primaryexist in that stylesheet. components.jsonpoints its CSS path atsrc/web/app.cssand its aliases atweb/*.
In development, the document should contain a render-blocking stylesheet URL
ending in ?direct. In production, CSS is emitted from Vite’s manifest for the
matched root, layout, and page chain.