v0 design system prompts that stop the shadcn default look
Copy-paste v0 prompts to set up a real design system (tokens, type, radius, components) so your v0 projects stop looking like every other shadcn/ui site.
v0 is built on Next.js, Tailwind and shadcn/ui. That's a strong foundation, and it's also why so many v0 sites look identical: shadcn's default theme (neutral greys, 0.5rem radius, Inter or Geist, a primary that's near-black or indigo) ships unchanged. The fix is to treat the theme as the first thing you build. Here are the prompts we use, in order.
Prompt 1: the token sheet
shadcn/ui reads colours from CSS variables in globals.css. Replace them all in one go:
Update app/globals.css. Replace the shadcn theme variables in :root with this palette (convert to the same format the file already uses, hsl or oklch):
background #f6efe4, foreground #221a14, card #fffaf3, card-foreground #221a14,
primary #d2421f, primary-foreground #fffaf3, secondary #efd9c4, secondary-foreground #221a14,
muted #efe6d8, muted-foreground #76685b, accent #efd9c4, accent-foreground #221a14,
border #dccab6, input #dccab6, ring #d2421f.
Set --radius to 0.25rem. Remove the .dark block for now; this site is light only.
Do not change any components.
That's our "atelier" palette, warm paper and a brick-red accent, which suits creative tools. The point is that every value is chosen, not inherited.
Prompt 2: fonts with next/font
In app/layout.tsx load two fonts with next/font/google:
- DM Serif Display (weight 400) as --font-display
- Work Sans (weights 400, 500, 600) as --font-sans
Apply both variables on <html>. In globals.css set body to var(--font-sans) and h1, h2, h3 to var(--font-display) with letter-spacing -0.02em. Remove Geist/Inter imports.
See best fonts for vibe-coded apps for other pairings that hold up in product UI.
Prompt 3: a type scale with contrast
Default v0 heroes are often text-4xl md:text-5xl over text-lg, a ratio of about 2.5. That's what makes them feel polite and forgettable.
Define a type scale in globals.css and use it everywhere:
display: clamp(48px, 7vw, 96px), line-height 0.95
h2: clamp(32px, 4vw, 52px), line-height 1.05
h3: 22px, body: 17px / 1.55, small: 13px
Apply display to the hero h1 only.
Prompt 4: component overrides
shadcn components inherit tokens, but a few defaults are worth changing directly:
Adjust shadcn components (edit the files in components/ui):
- Button: remove rounded-md, use the --radius variable; default variant has no shadow; add a 'link' style that is underlined with 2px offset.
- Card: border 1.5px solid var(--border), no shadow, padding 28px.
- Badge: uppercase, 11px, letter-spacing 0.1em, monospace font, square corners.
Don't change props or exports.
Prompt 5: layout rules
Layout rules for every page:
- Max content width 1200px, 32px side padding (20px under 640px).
- Hero is left-aligned in a 7/5 two-column grid with a real product screenshot on the right.
- No section may be a grid of three identical cards with icons. Use numbered lists, a lead feature with a screenshot, or a two-column text layout instead.
- Section dividers are 1.5px foreground borders, not background color changes.
Prompt 6: the banned list
v0 sometimes drifts back to defaults as you iterate. A short "never" list keeps it honest:
From now on in this project, never use: gradient backgrounds or gradient text, backdrop-blur, emoji as icons, rounded-full buttons, indigo/violet/purple Tailwind classes, Lucide icons inside colored circles, the words "seamless", "unlock", "supercharge", "elevate" or "effortless".
Re-paste it whenever you start a new chat on the project.
Order matters
Run the prompts in this order and check the preview after each one. Tokens first, because every later change depends on them. Fonts second. Then the type scale, then component overrides, then layout. If you start with layout, v0 will build the new layout with default tokens and you'll be fighting the same defaults twice.
If a prompt changes more than you asked, say so in the next message: "You changed the navbar structure, revert that and only apply the colour changes." v0 handles corrections well when they're specific.
A quick example
For a project-management tool called Tally, the full set of choices might be: Space Grotesk + IBM Plex Sans, paper #f5f2ec, ink #1a1714, accent ultramarine #2f4bd8, radius 2px, a hero that shows the actual board view, and a features section that's a single wide screenshot with three annotated callouts. That's an afternoon in v0, and nobody will mistake it for the default template.
Keep it as a v0 project instruction
v0 supports project-level instructions. Paste the token values, fonts, scale and banned list there so every generation starts from your system instead of shadcn's. If you also work locally in Cursor, the same content becomes a rules file: see Cursor rules for UI design.
Before you ship
Deploy to Vercel, then run the free scan on the *.vercel.app URL. It flags anything still on defaults (palette, fonts, card grids, glass, badges) and gives you a v0-ready prompt for each. Compare with other v0 projects on the Slop Leaderboard, and go through the pre-launch design checklist.
FAQ
Can v0 use custom fonts?
Yes. Ask it to load fonts with next/font/google in app/layout.tsx and expose them as CSS variables, then reference those variables in your Tailwind config or globals.css.
Where does v0 put theme colors?
Typically in app/globals.css as CSS variables (--background, --foreground, --primary, etc.) consumed by shadcn/ui. Changing those variables restyles every component at once.
Should I stop using shadcn/ui?
No. shadcn/ui is a good component base. The tell is shipping its default tokens unchanged, not using it.