Generic-Looking AI App: 5 Fixes, Before and After
Why does an app built with AI look like every other one? Five CSS fixes for one afternoon, with before and after shots and a prompt ready for your agent.


An app built fast with AI almost always looks generic for the same five reasons. You can fix them with a bit of CSS in an afternoon, without redesigning anything. Here are the five fixes, a screenshot after each one, and a prompt for your agent at every step.
We built the screen ourselves, on purpose: a small invoice dashboard with made-up data. It is not anyone's product. It looks like what you get when you ask an AI for "a clean SaaS dashboard" and accept the first answer.

Same layout, same colors, same purple button.
The Before: Five Usual Suspects

Nothing is broken, and that is the problem: it works, but it looks like a hundred other screens. Random gaps, flat text, placeholder words, mixed icons, buttons that never react.
1. Use a Spacing Scale
What it is: a short list of allowed gaps. We used 4, 8, 12, 16, 24 and 32 pixels, all multiples of four.
Why it matters: the before had 13 pixels here, 22 there, 7 between the buttons. The screen feels "off" even if nobody can say why.
How to do it: write the list once as CSS variables (space-2 for 8 pixels, space-4 for 16, and so on) and use only those names. Rule: things that belong together get a small gap, groups get a bigger one. The label sits 8 pixels above its number, cards sit 16 pixels apart, sections 32. When unsure, pick the bigger value.

Define a spacing scale as CSS variables: 4, 8, 12, 16, 24, 32px. Replace every margin, padding and gap on this screen with a value from the scale, and ban every other number. Rule: small gaps between things that belong together, bigger gaps between groups (label to number 8px, card to card 16px, section to section 32px).
2. Give the Text a Clear Hierarchy
What it is: type hierarchy, where size and weight tell you what to look at first.
Why it matters: in the before, title, labels and table cells were all between 14 and 22 pixels, mostly bold. When everything shouts, nothing is important.
How to do it: one font and four sizes, 13, 15, 18 and 30 pixels. Then three decisions:
- Numbers loud, labels quiet. Amounts at 30 pixels, labels at 13 pixels in grey. Your eye goes straight to "how much".
- Bold only where it means something. In the table, only the invoice number stays bold.
- Numbers line up. The CSS setting tabular-nums gives every digit the same width. With amounts right-aligned, columns compare at a glance.

Reduce this screen to one font and four text sizes: 13, 15, 18 and 30px. The most important figure goes to 30px, labels to 13px in grey, not bold. Remove bold everywhere except where it marks something (like an invoice number). Use font-variant-numeric: tabular-nums for numbers and right-align amounts in tables.
3. Replace Placeholders With Real Content
What it is: believable words that do a job. You do not need real customers.
Why it matters: this is the step people skip, and it makes the biggest difference. "Metric 1" and "John Doe" say one thing: this was never finished.
How to do it: for every piece of text, ask what the person using the screen wants to know.
- "Welcome back, User!" with a waving hand becomes "October invoices", with a useful line below: €2,790 still waiting, one invoice overdue.
- "Metric 1, 2, 3" become "Paid this month", "Waiting for payment" and "Overdue", each with a hint like "1 invoice, due 15 Oct".
- "Create New", "Action" and "Button" become "New invoice", "Export CSV" and "Send reminder".
And the numbers must add up. The two waiting invoices, €1,450 and €700, make the €2,150 in the card. Waiting plus overdue gives the €2,790 in the subtitle. When numbers agree, the screen feels real.

To catch leftovers, a tiny script in the browser console (right-click, Inspect, Console) is enough: on the starting screen it found 15, on the final one none.
Replace every placeholder text on this screen with believable content for [describe your app in one sentence]. The subtitle must be one useful sentence about the user's situation, not a greeting. Every button must name the exact action. Numbers must agree: card totals must match the sum of the table rows. Then write me a script to paste into the browser console that lists, in a table, every text on the page containing lorem, ipsum, John Doe, Jane Smith, Item 1 or Metric 1.
4. Make Icons and Borders Match
What it is: choosing one style for icons, borders, corners and shadows, once.
Why it matters: the before mixed emoji, filled and outline icons, three kinds of borders, two shadows and corners of every shape. It looks like a collage, not a product.
How to do it:
- One icon style. All outline, 18 pixels, same line thickness. We used simple SVGs; one icon set works too.
- One border. A single light grey 1-pixel line for cards, table rows and the secondary button.
- One family of corners. 12 pixels for cards, 8 for buttons and menu items, fully round for small status labels. Smaller things get a smaller radius.
- No shadows on things that do not float. Cards sit flat on the page. Shadows stay for menus and dialogs on top.

Unify the style of this screen. Icons: all outline, 18px, same line thickness, no emoji, one set only. Borders: one light grey 1px line for cards, table rows and secondary buttons. Corners: 12px for cards, 8px for buttons and menu items, fully round for status labels. Remove shadows from elements that do not float; keep them only on menus and dialogs.
5. Make Every Button Answer Back
What it is: four visible states on every button.
Why it matters: a button that always looks the same makes the app feel flat and a little broken. Vercel's post on design engineering lists interactions that show what you can do, and support for touch and pointers, among the things that matter.
How to do it:
- Hover: the button gets a little darker.
- Press: it shrinks to 97% while held down. Tiny, but it feels like a real button.
- Focus: a clear 2-pixel ring when you move with Tab. The :focus-visible selector shows it for keyboard users and hides it after a mouse click.
- Disabled: faded, with a cursor that says no. It uses the real HTML disabled attribute, so the keyboard skips it and clicks do nothing.
In Chrome all four work: Tab moved from "Export CSV" to "New invoice" with a visible ring and skipped the disabled button.
Add four states to every button on this screen: hover slightly darker; active with transform: scale(0.97); focus with a visible 2px ring using :focus-visible; disabled with the HTML disabled attribute, lower opacity and a not-allowed cursor. Never remove the focus outline without replacing it.
Ready to Copy: All Five at Once
Review this screen in five steps, without changing layout, brand colors or fonts. 1. Spacing scale 4, 8, 12, 16, 24, 32px as CSS variables, no other values. 2. Four text sizes (13, 15, 18, 30px), one loud thing, small grey labels, tabular-nums on numbers. 3. Real text instead of placeholders, numbers that agree between cards and table. 4. One icon style, one 1px border, 12/8px corners, shadows only on things that float. 5. Hover, active, focus-visible and disabled states on every button. Before touching any code, list what is wrong for each of the five points. Then apply one point at a time and stop after each.
Small Test
Ten minutes. Open your app, press Tab a few times and watch: can you always see where you are? Then search the page for "Lorem", "Metric" and "John Doe". If you find a problem, paste the step 5 or 3 prompt and try again. It worked if you can reach every button with the keyboard alone, always seeing the ring, and no placeholder is left.
Watch Out For
- The placeholder script does not catch everything. It misses generic labels like "Action" or "Button". Read every button out loud once.
- Never remove the browser's focus ring without adding your own. Keyboard users would no longer know where they are.
This article is adapted from a before and after Alek published on Medium.
Next step: apply the same method to forms with Forms That Look Cheap: 5 Fixes. For a whole app, read Redesign an App With AI Without Breaking the Code.
In short: A generic app does not need a new look: it needs gaps from one scale, one loud thing per screen, real words, one style for icons and borders, and buttons that answer back.
Newsletter
AI that actually works, in your inbox.
New pills, the tools we use and what we learn on real projects. Few emails, only when there is something useful.


