Browser-based builders like v0 and Lovable share a trait that makes design consistency tricky: the project starts in the chat, not in your repository.
There is no .rules folder on the first prompt, because there is no folder yet. So the sequence matters.
Get the file in early
The single most effective thing you can do is add DESIGN.md as the first move, before you ask for any UI.
In Lovable, create the file in the project and then instruct the agent to treat it as binding:
Create DESIGN.md at the project root with the content I paste next.
Treat it as the visual contract for this project: every component you build
must use only its tokens for color, spacing, radius, and type.In v0, attach or paste the design constraints in the first message of a new chat. v0 carries chat context forward, so establishing the rules before the first component is worth more than correcting the tenth.
The constraint block
Full design documents are too long for a first prompt. Lead with a compact version:
Design constraints, follow exactly, no exceptions:
- Surfaces: background #0b0b0c, card #121214, border #232327
- Text: primary #f2f1ee, muted #8d8b86
- Action: #0061ff, text on action #ffffff
- Type: Inter. Display 28/600, heading 20/600, body 15/400
- Radius: cards 14px, controls 10px, pills 999px
- Borders 1px only. No gradients. No drop shadows.
- Spacing scale: 4 8 12 16 24 32 48Then describe the screen. Keeping constraints and content separate makes it obvious when the model has ignored one of them.
Add the rules file once the repo exists
Both tools can push to GitHub. The moment your project has a real repository, the ambient-context approach becomes available again.
Add DESIGN.md at the root, then wire up whichever assistant you use locally. From that point the browser builder and your local editor are reading the same contract, which is the whole point of keeping design in a file rather than in a prompt.
The normalisation pass
Here is the step most people skip, and it is where the biggest win is.
Generated projects accumulate near-misses: a #0a0a0b where your background is #0b0b0c, a rounded-xl next to a rounded-2xl. Individually harmless, collectively a mess.
Once a week, run one pass:
Audit every component in src/ against DESIGN.md.
List each value that does not match a token, with the file and line.
Do not change anything yet.Read the list, then approve the fixes. I have found the list is always longer than expected, and always shorter than the effort of a manual audit.
Verify it worked
Ask the builder to render two unrelated screens, then compare the greys and the corner radii. Matching values mean the constraints held. Divergence means the block got diluted and needs re-pasting.
Common mistakes
- Adding the design rules after ten components exist. Now you have a migration instead of a constraint. Front-load it.
- Assuming the chat remembers forever. Long sessions lose early context. Re-paste the constraint block when starting a big new screen.
- Skipping the repo file. If the design system only lives in a chat, it disappears when the chat does.
What this means for you
These tools are excellent at getting from nothing to a working screen. Give them a contract on the first message and they are also good at staying consistent.
Pick a documented system from the library, trim it to a constraint block, and keep the full file in the repo for the tools that can read it.