Miraee: A Design System for AI
How we got the AI to reuse our components instead of regenerating them


Product
- Miraee by Mondee, a B2B2C travel app on iOS, Android and Web.
- One design system meant to serve all three platforms, living in code.
My role
Lead product designer. I ran the audit, set the strategy and rebuilt the system, working with the engineers on what to delete and the PM on what to protect.
Team
- Shashank Sharma (PM)
- Harsha Arrimala (UI/UX Designer)
- Shubham, Raunak & Akhil (Engineers)
- Mridula & PC (Cross-functional Leads)
Timeline
About a month in 2026. Audit, rebuild, then the audit again.
Speed
2.5×
faster to build a screen. Days became hours.
Bugs
~60% fewer
Jira tickets about UI drift and visual bugs.
Load time
35% faster
page loads on web, once duplicate styles and dead code were gone.
TL;DR
We went AI-first to ship faster, and we did. But every screen the AI built made the design system a little worse. When I went looking for our brand orange in the code, I found ten oranges. Ours was sixth.
We couldn't change how the AI works, so we changed what was around it: a rules file, a website it can read, and fewer things to choose from. Then people forgot to add the file to their prompts, so we moved notes for the AI into the code, above every page. Now it reads them on its own.
In the new system, 4,250 hand-typed colours became zero, and 287 card components became one.
The problem
How did going AI-first make the design system worse?
It started with a search bar. I had designed one toolbar with the search, the filter and the view toggle built in, and the pages were not using all of it. It's not rocket science to notice. But once I started looking, it was everywhere.
Miraee is one product on three platforms: web, iOS and Android. We had one designer for all three, and three full-stack engineers. The company wanted speed, so we went AI-first. Engineers built screens with AI, and the gaps a designer would normally fill got filled by a generator.
A design system is supposed to be the one place every screen comes from. Build a button once, use it everywhere, change it in one place. Going AI-first was supposed to make that faster. It did the opposite. Every time the AI built a screen, it lost the context of what already existed. It made a new button rather than find ours. It copied a colour from the nearest file, even when that file was a mistake. It built the happy path and nothing else.
Where this project steps in
Spread across web · iOS · Android
Two things pulled against each other. The company wanted velocity, and the AI-first mandate was not up for debate. The product needed consistency, and one designer could not police every screen on three platforms. Slowing the engineers down was not an option. The system had to work at the speed they were already going.
The company wants
Velocity
Ship every feature faster. AI-first, three engineers, no slowing down.
The product needs
Consistency
One button, one card, one grey, the same on web, iOS and Android.
The goal
Make the design system the thing the AI reuses instead of regenerates, so the codebase gets leaner, faster and consistent across web, iOS and Android, without slowing the engineers down.
The audit
Counting the damage, in all three codebases
Two passes: source, then browser.
~4,250
Hardcoded colours, three apps
122
iOS card structs
74 / 78
Card pages, no empty state
39 / 52
Web components never imported
57%
Body text failing contrast
10
Oranges; brand ranked sixth
Show all 29
Table row heights
10 heights
Table dividers
5 treatments
Filter buttons
4 treatments
Primary colour
4 primaries
Destructive reds
3 platforms, 3 reds
Oranges
10 in use · official sixth
Grey scales
3, one documented
Raw hex
2,813 web · 959 iOS · 484 Android
Text contrast
57% of body fails
Heading font
179 headings fall back
This is only some of it. The same thing shows up everywhere else we looked. Dates are written at least twelve different ways in the code. There are 124 modals across the three apps. Icons come from one library, but 32 files still draw their own. On mobile it's the same story: 29 corner radii on iOS, 165 card composables on Android, and eight different progress bar heights. Most likely there's a lot more we missed.
Same mistakes everywhere. One fix.
Insights
Why it drifted: the AI, and the people using it
Two things caused this, and they fed each other: how the AI writes code, and how people worked with it. The bigger the circle, the more of the product it shows up in.
Most numbers come from the audit. One comes from outside research: trust and checking, from Sonar's State of Code survey.
Generated UI is only going to grow, so the fix had to work with the AI, not around it.
Strategy
Stop fighting the cheapest path. Put the right thing on it.
If you can't change the behaviour, change the environment.
We couldn't change how the AI works, and people didn't want to do more work either. So instead of asking anyone to change, we changed what was around them, so the right thing happens on its own.
Five moves
Each move answers behaviours from the two maps.

01
A rules file
One Markdown file with a list of all the components and how to use them. You give it to the AI along with your prompt.
Fixes
- Copies the nearest code
- Starts fresh every session
- Design page by page

02
A website the AI can read
117 pages in the repo, made from one rules file. The AI reads these instead of Figma.
Fixes
- Falls back to library defaults
- Paste values from Figma
- One designer for three apps

03
Less to choose from
One typeface, fewer components, token names the AI can guess, and scales with no gaps to invent a value in.
Fixes
- Hardcodes values not tokens
- Restyles shared components

04
Checklists
A screen is done when it has its states, uses only tokens and works at 500 rows.
Fixes
- Builds only what it's asked for
- Looks finished when it isn't
- Test with demo data
- Ship code that looks right

05
Remove the wrong options
We deleted the 39 dead components, so the AI can't copy them. What's left is a correct example on every platform.
Fixes
- Deadlines beat consistency
- Leave unused code in place
- Copies the nearest code
Before. A prompt on its own
Build a trip card
Thinking
- No design system in context
- Opening the nearest file
- Copying the card in it
- Picking an orange, #FF5733
- Adding a shadow
- Skipping empty and loading
Result
San Francisco
Upcoming12 Nov 2026
A new card, one more to maintain.
After. A prompt with the rules
Build a trip card
- design-system.md
- CHECKLIST.md
Thinking
- Reading design-system.md
- Found Card, using it
- Colours from tokens only
- Reading CHECKLIST.md
- Adding empty, loading and error
- Checking 500 rows
Result
San Francisco
12 Nov 2026Upcoming
The shared Card, reused.
What we chose not to do

Lint rules and CI gates
Automatic checks that stop code from merging when it breaks a rule.
Why not
Engineers would have had to build and manage these checks, and they weren't willing to give that time at the moment.

Visual regression testing
The AI compares screenshots after each change to catch anything that moved.
Why not
When we tested it internally, the AI didn't catch the mistakes, so we couldn't rely on it. It also used a lot of credits.

A Figma MCP server
A connection that lets the AI read Figma directly while it works.
Why not
It makes Figma the source of truth again, and keeping Figma and code in sync is what caused the drift. The website gives the AI the same answers with nothing to sync.

Switching to Paper
Another design tool, paper.design. From what I know, it's meant to be a little better for designing UI.
Why not
It would have needed some learning and getting used to.
The test for everything: can the AI pull the right component faster than it can write a new one?
What worked and what didn't
People kept forgetting the file
The fix had to work even when people forgot.
The first version depended on people. Anyone prompting the AI had to add the rules file and the checklist every time. When they missed it, the AI went back to copying the nearest code.

Didn't work
Adding files to every prompt
It worked when people remembered. No matter how many times we said it, someone would eventually miss it.

Worked
Notes for the AI, above every page
The notes sit in the codebase itself, so the AI goes through them on its own whenever it works on a page. Nobody has to remember anything.
Three decisions along the way
Three other things did not go the way I had planned, and they taught me the most.
What I kept, against the cleanup
What I reversed
What I did not build
Results
The same audit, run on the new system
Before and after, in numbers.
Colours typed by hand
4,2500
Oranges
100
Grey scales
31
Reds
31
Badge styles
364
Text failing contrast
57%0%
Typefaces
31
Text sizes
1310
Card components
2871
Primary button kinds
101
Unused components
390
Modals
1241
Pages with no empty state
740
Corner radii
296
Shadows
2184
Progress bar heights
81
Icon sets
31
Date formats
121
And the same wall as the audit, with one of each thing instead of many.
Primary buttons
1 kind · 6 variants

Status badges
4 values · a dot and a word

Flight cards
1 card

Hotel rows
1 row

Trip rows
1 row · 48px

Nothing found
1 empty state · names the query

Tables
1 table · sorts and pages

Search bars
1 toolbar

Metric tiles
1 tile · every number has a comparison

Page titles
1 header · one primary action

Tabs
1 kind

Charts
1 line style

Avatars
1 style
What else changed
Rebuilding the system was also an opportunity to rethink some of the other things that were causing lots of issues down the road.
From pages to cards
Earlier, a page was like one component. Now each part of a page is a separate thing, usually a card, designed on its own, and these fit into a responsive grid. It's a little inspired by the Carbon design system.
Before. The whole page is one thing

After. Each part stands on its own

From warm to neutral
One of the costs was visual warmth. Midway, we were asked to move to a neutral colour palette instead of a warm one, so the product would feel modern and new instead of old.
No more pictures
We realised people were not adding pictures, so All Trips no longer depends on them. The table is just names, routes and status.
Before. Warm palette, three fonts, pictures

After. Neutral palette, one font, no pictures

Both versions use sample data.
Impact
What changed for the team
Screens went from days to hours.
2.5×
Faster to build a screen
~60%
Fewer UI bug tickets
35%
Faster page loads on web
95%
Old code cleared on global updates
How we measured it
We did not have a pilot group the way a product feature would. What we had was the audit. We re-ran it at each milestone, against the same baseline, so adoption was a number we could show rather than a feeling we had. Alongside it we counted Jira tickets, and timed how long a screen took from handoff to merged.
Leadership & reflections
What leading this actually involved
Designing for the environment
Prioritising workflow over aesthetics
What I would do differently
- 01
Track adoption from day one
Not after the fact. The audit script should have existed before the first system did. - 02
Test with real data volumes earlier
Most lists were designed against six sample items. 500 rows would have shown the problem in week one. - 03
Decide how the system stays maintained before designing it
Manual token syncing between Figma and code is what caused the drift the first time.
In conclusion
























































































































