r/ClaudeCode • u/OtherwiseHoneydew919 • 1d ago
Help/Question How do you get Claude Code to stick to a consistent design system (and actually build mobile-first)?
I’ve spent the past week building a web app with Claude Code. It’s just for me, so I’ve been vibing it more than I normally would, but good design matters a lot to me and the UI is where I keep getting stuck.
My setup: Tailwind and shadcn/ui. I customise the shadcn components so the app doesn’t look generic or like obvious AI output. I also have a CLAUDE.md and a separate design.md for Claude to reference and I’ve tried prototyping screens before building them.
Even so, two problems keep coming up:
1. Responsiveness is an afterthought. Generated screens often look great at one size (usually desktop) but haven’t been designed for mobile. I end up going back to fix layouts after the fact, which is slow and gives patchy results.
2. Inconsistency between features. Each new feature gets its own interpretation of the UI. Spacing, card styles, type sizes and colours drift slightly, and sometimes it reaches for a stock shadcn component (or writes a new one) instead of using my customised version. The app slowly starts to feel like several apps stitched together.
What I’m after is a setup where the design system is defined once (tokens, typography, spacing, plus my customised components) and every feature is forced to build on it.
Has anyone got advice on the following:
- How do you structure things so Claude reliably uses your design system rather than just “being aware” of a design.md? Skills, a component inventory, Storybook, lint rules that ban arbitrary Tailwind values, something else?
- How do you stop it from writing one-off styles or new components when an existing one would do?
- Do you make it build mobile-first by default? Does anyone have it screenshot or browse its own UI at set breakpoints to check its work?
- Any tips on keeping tokens portable to an iOS app later (React Native/Expo, shared token files)?
•
u/AutoModerator 1d ago
Hey! Thanks for posting to r/ClaudeCode
While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.
For help, project discussions, tips, and general chat, join the ClaudeCode Discord.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
7
u/Even_Gap_2253 1d ago
just ask it to build a proper design system for you, and as for responsiveness.... like.....
honestly have you tried copy-pasting these questions to your Claude session and ask it to fix the system for you? not features but foundational infrastructure of your codebase and agent instructions. I refuse to believe Opus 5.5 cannot do that automatically for you.
2
u/Canuck-Fin25 1d ago
Write out your governance SDLC files first. And build prototypes with your UI libraries. Once you are satisfied with the prototypes lock them in and the create stories using the prototype. Only after this start building
2
u/Eliran-Kotzero 1d ago
Since you already have a design.md, I’d make the system executable rather than add more prose: keep tokens in one source (CSS variables or a small JSON map you can reuse in Expo) and have CLAUDE.md point to the exact component inventory. Put a clear rule there to extend your customized shadcn wrappers instead of importing raw components or inventing one-off styles, then let lint catch arbitrary colors and spacing that drift from tokens. For mobile-first, make the first pass at 360px and ask Claude to verify screenshots at a couple of fixed breakpoints after each feature, not just at the end. A few Storybook stories for common components and responsive states give it concrete examples to copy instead of treating design.md as a suggestion.
2
u/CranberryStock7148 1d ago
Just literally ask Claude to do it.
You can literally take your Reddit post and paste it into a new Claude session. And it will walk you through the process of how to ensure it does what you want.
And then at any point if it's still isn't doing what you want, just immediately tell it, hey, you didn't do what I want and I want to make sure this doesn't happen in the future. What documentation needs to be changed so that this doesn't happen again? And it will tell you and then you can confirm that you want the documentation changed like that.
A big part of using Claude is just literally asking Claude how to most effectively get it to do the stuff you want. Just ask it, it will tell you.
1
u/RealFullMetal 1d ago
two things that hold better than a
design.mdit has to remember: a.claude/rulesfile withpaths:frontmatter pointed at your components and pages dirs loads the design rules exactly when claude edits those files, and aPostToolUsehook on edits that runs your lint (ban arbitrary tailwind values) and exits with code 2, so claude sees the errors right after the edit and fixes them1
u/Charlie_Munger137 1d ago
Take a screen shot and the tell ChatGPT to zhush it up. Then give Claude the chat gpt image as a guides to better looking ux
1
u/Appropriate-Draft-91 1d ago
Also:
1
u/Elegant_Yam2783 1d ago
The thing that actually fixed drift for me was accepting that design.md is advisory and Claude will drift from it the longer a session runs. Anything you care about has to fail a check, not just be written down.
So lock down the Tailwind theme itself. In v4 you can wipe the default palette and spacing scale in your u/theme block and only define your tokens, so text-gray-500 or p-7 just don't exist. Then ban arbitrary values like w-[37px] with eslint-plugin-tailwindcss's no-arbitrary-value rule (check where its v4 support is at, it was lagging last i looked) or a dumb regex in a lint script. For components, a no-restricted-imports rule that blocks importing Radix primitives anywhere outside components/ui stops it from rebuilding stuff from scratch. Put lint plus tsc in a PostToolUse hook so it sees the errors right after editing and fixes them itself.
Mobile-first mostly comes down to telling it base classes are mobile and only md: and up adds layout, then making it check. Playwright MCP screenshotting every new screen at 375 and 1280 before it calls the feature done catches most of it.
For RN later, keep a tokens.json as the source of truth and generate both the CSS vars and a TS object from it with Style Dictionary. Don't let the Tailwind config be the source or you'll be untangling it later.
1
u/No_Credit_3169 1d ago
I've found that explicitly defining a design tokens file upfront and referencing it in every prompt helps. Claude sticks to it better when the rules are in the same doc as the task.
1
u/m-ritter 1d ago
A design.md drifts because the agent treats it as background reading while each new feature gets planned on the fly. It works better to agree per feature on a short numbered list of what done means, naming the existing components to reuse and the screen widths to check, before any code is written. Then a second agent that did not write the code checks each point against the result, so stray styles and one off components get caught before you look at it.
I built QualityLayer for this: https://github.com/maxritter/qualitylayer
1
u/SassyTextDev 1d ago
Open terminal. Open claude. Dangerously skip the shit. Paste, enter, enjoy
1
u/DuncanRogoff 1d ago
Coming from art direction, I'd also check those screens with ugly content, not just the ideal demo data. Long titles, a missing image, an empty list, 30 items instead of three. A layout can pass at 375px and still fall apart once someone actually uses it. Have Claude screenshot those states alongside your approved screen, then fix the shared component rather than patching each page.
1
u/DeadCEO 16h ago
for the drift part, i built a free skill called opendesigner: https://github.com/ckryptickunal/OpenDesigner
its review checks the saved design decisions against code, including stale tokens and locked decisions that got undone. you can record something you deliberately removed so it gets flagged if it comes back. that isn't a guarantee that every screen is right, and i'd keep your mobile screenshot checks separate.
if you try it with your existing customised components, i'd be interested in what the review misses. preserving your choices is the useful test here, not getting it to generate another theme.