I love shadcn/ui. I use it on almost every project. And I will say what most people will not. **shadcn looks generic** by default, and the reason your AI app looks like every other AI app is almost certainly that you installed shadcn, accepted the defaults, and asked the agent to build from there. The components are excellent. The defaults are the trap.
This post is about why shadcn out of the box collapses to a single visual identity, why AI agents make that worse, and the small set of token edits that get you out of it without giving up the library.
Why shadcn is great and still a trap
The whole point of shadcn is that you copy components into your project and own them. That is genuinely a good idea. Most component libraries hide their internals so deep that customization is painful. Shadcn flips that. The code is yours, the styling is yours, and you can edit any of it.
The trap is that almost nobody does. People run the install command, accept the default theme, accept the default radius, accept the default Inter font, and start building. The components are all consistent with each other, which feels like a design system. It is not. It is a starting kit, and the starting kit is the same starting kit everyone else got.
Then an AI agent shows up. The agent looks at your codebase, sees shadcn, and reaches for shadcn defaults on every new component. Of course it does. That is the most common pattern in your code, so that is what it generates. The defaults compound, and three weeks later your app is visually indistinguishable from any other shadcn project on the internet.
The shadcn fingerprint
If you have looked at more than ten AI generated apps, you know the look. Slate or zinc neutrals. Inter at the default sizes. Eight pixel radius on everything. A Card with a one pixel border at slate 200. A Button at the default primary. The DataTable that looks exactly like the docs example. The Dialog that looks exactly like the docs example. The whole thing is competent and forgettable.
This is not a shadcn problem. It is a defaults problem that shadcn happens to be the most popular vehicle for. The same thing happens with any component library when you skip the customization step.
The token customization that fixes it
The good news. Shadcn is built on CSS variables. Every component reads its colors, radii, and a few other values from a small set of tokens defined in your CSS. Edit the tokens once, and every component updates everywhere. You do not have to touch a single component file.
Here is the minimum set of edits that makes the biggest difference. Each one is a one line change in your styles.css or globals.css. The categories below match what your design.md should already declare, which is why this works so well together.
Replace the neutral scale
Slate and zinc are the most common shadcn defaults, and they are the reason every shadcn app looks the same. Pick a different neutral. Warm bone at oklch 0.97 0.01 80 for surfaces and oklch 0.16 0.012 250 for foreground reads editorial. A near black surface with cool gray text reads cinematic. A pale taupe with deep brown text reads premium. Any of these beats slate because none of them are the default.
Pick a real radius position
The default radius variable is somewhere around half a rem. That is the safe middle. Move off it. Set --radius to zero pixels for a confident sharp look, or to one rem for a soft generous look, or to nine hundred ninety nine pixels for a fully pill aesthetic. The same components, with a different radius, read as a completely different product.
Override the font tokens
Shadcn defaults to whatever sans is configured in your Tailwind theme, which is usually Inter or system sans. Override --font-sans and --font-display with a real pairing. A serif display with a clean sans body. A geometric sans display with a humanist body. Loaded once via Google Fonts, declared in your tokens, applied across every component.
Pick a saturated accent
The default --primary in most shadcn themes is a muted indigo or zinc. Replace it with a single, saturated accent that belongs to your brand. Then resist the urge to add a second accent for secondary actions. The secondary action should be the absence of color, not a different color. One accent, used sparingly, is the look.
Add a token shadcn does not ship
This is the move that separates a customized shadcn project from one that still looks like the kit. Add one token that shadcn does not include by default. A grain texture variable. A signature shadow you use everywhere. A specific easing curve for transitions. A non default border treatment. Anything that is yours, named, and applied consistently. That one extra token is what gives the project a fingerprint.
Why your AI agent will respect these tokens
Once your CSS variables are different, every shadcn component the agent reaches for picks up your values automatically. That is the whole architecture. The agent does not have to know you customized anything. It generates a Button as usual, and the Button reads your radius, your font, your accent, and your neutral. The output is on brand by construction.
This is why shadcn plus a real design.md outperforms shadcn alone, and it is why both outperform a from scratch component library for AI driven projects. The agent is going to reach for the most common pattern in your code. Make sure the most common pattern is yours, not the default. The generic landing page teardown walks through the same idea from the other direction, starting from the symptoms instead of the components.
Shadcn is not the problem. Shadcn defaults are the problem. Edit five tokens and you keep the library and lose the look.
What about going beyond tokens
Eventually, tokens are not enough, and you will want to actually customize a few components. That is fine, and shadcn is built for it. But do not start there. Start with tokens, because tokens move every screen at once. Component edits move one screen at a time. The order matters, and most teams do it backwards, which is why they end up with twelve customized components and an app that still feels like the default kit.
The same logic applies to which files hold what. Tokens belong in your design.md and your CSS variables. Component conventions belong in CLAUDE.md or .cursorrules. The files cheat sheet covers the split if you have not nailed that down yet.
A working order of operations
Install shadcn as usual, accept the kit, do not theme it yet.
Write a design.md that declares your neutrals, accent, fonts, radius, and one signature token.
Translate those tokens into your CSS variables, overriding the shadcn defaults.
Point CLAUDE.md, .cursorrules, and any agent prompts at design.md for all styling decisions.
Generate a screen, compare to the default kit, and watch the personality appear.
That order, in that sequence, is the difference between a shadcn project that looks like every other shadcn project and one that looks like your product.
Where to go from here
Pick a system from the directory whose feeling matches your product, copy the design.md into your repo, port the tokens into your CSS variables, and regenerate one screen. The shadcn components stay where they are. The look changes immediately. That is the whole fix, and it takes about an hour the first time you do it.
Frequently asked questions
Why does shadcn look generic by default?
Because almost everyone installs shadcn, accepts the default theme, the default radius, the default Inter font, and starts building. The components are excellent, but the defaults are the same defaults everyone else got. The result is competent and forgettable, which is exactly the look people are trying to avoid.
Is shadcn the reason my AI app looks generic?
Not directly. Shadcn is a great library. The reason your AI app looks generic is that the agent reaches for shadcn defaults on every new component, because that is the most common pattern in your code. Change the underlying tokens and the agent generates the same components against your tokens instead of the kit defaults.
Which shadcn tokens should I edit first?
Five. Replace the neutral scale away from slate or zinc. Pick a real radius position instead of the safe middle. Override the font tokens with a real pairing. Set a single saturated accent. Add one token shadcn does not ship, like a signature texture or shadow. Those five edits move every component at once.
Do I have to fork shadcn components to fix shadcn looking generic?
No. Shadcn is built on CSS variables. Every component reads its colors, radii, and a few other values from tokens defined in your CSS. Editing the tokens is enough for most of the impact. Component edits come later, only if you need them, after the tokens are doing their job.
How does design.md help fix shadcn looking generic?
design.md is where you declare the tokens once, in human readable form, so any AI agent working in the project picks them up. The same values get translated into your CSS variables for shadcn to read. One source of truth, two consumers, no duplication.
Is shadcn still worth using if it looks generic by default?
Yes. The accessibility, keyboard handling, and component quality are excellent. The trap is the defaults, not the library. Edit the tokens and you keep all the benefits while losing the default look. Going from scratch is almost always more work for less polish.
What is one token shadcn does not ship that I should add?
Anything that becomes your signature. A grain texture variable, a signature shadow used across all elevated surfaces, a specific easing curve for hover states, or a non default border treatment. One extra token, applied consistently, is what gives a customized shadcn project its fingerprint.
Should I customize tokens or components first?
Tokens first. Tokens move every screen at once. Component edits move one screen at a time. Most teams do this backwards and end up with twelve customized components in an app that still feels like the default kit. Start with five tokens, regenerate, and only customize components if specific cases still need it.
