Avoid the AI Aesthetic
You ask your favorite agent to generate a design for your exciting new product. It churns for a while, and then your shoulders drop a little when you see it—that telltale AI design that looks like every other website on the planet. Indigo accents, Inter everywhere, a centered hero with two buttons, and vague promises like “Elevate your workflow." The details vary, but they all feel like the same the product.
Why is this the default look, anyway? Blame Tailwind UI. Okay, I’m kidding. But also, not really. The creator of Tailwind, Adam Wathan, even apologized for turning AI-generated sites purple. Purple isn’t the only problem, though—even if you get past that and tell your agent “no purple” or “no Inter,” it tends to move to another set of defaults that other agents follow too: cream and terracotta, acid green on black, newspaper layouts, and so on.
Users are sick of these designs. Developers don’t really want to build them either (people have scoured Reddit for ways to avoid it), but agents tend to jump right into the same templated territory. It’s the default behavior, and it would take effort to avoid, so most people don’t bother.
The good news is that models are highly steerable. It doesn’t take as much effort as you’d think to get drastically better results with designs. With a little prodding, we can push our designs away from the dreaded defaults and toward something that is both unique and suitable for the product.
Before I go on, I should note that full-blown design tools like Claude Design offer much more flexibility and control and are built specifically for this purpose. But many builders find them to be overkill. They don’t want to go through an entire design app just to generate an initial design for their product. They want to stay in the terminal. If that’s you, this post is for you.
Design iteration: Push the agent(s) further
Treat design the way you already treat code: generate options, look at them critically, and refine.
- Go wide (and wild). Prompt the agent(s) to come up with 3-5 different proposed designs for your product. Require genuinely different structures, hierarchies, typography, density, and personality—not palette swaps—and ask it to include one wildcard that may question the workflow itself. At this stage, you’re trying to be as open and creative as possible, so resist the temptation to just send it a design and tell it to “make it like this.” You want to perform a divergent exploration, not a narrow dictation.
- Clarify key criteria. Now that you see some options, you might gravitate towards one structure versus the other. Think about why—is there something about the product goals that can help you decide? Define what matters most—task clarity, hierarchy, density, accessibility, responsiveness, and implementation fit. Then render the directions side by side, choose one against those criteria, record why it fits, and iterate within it.
- Adversarial review. Once a high-level direction for the design is chosen, ask fresh-context reviewers to attack it from distinct perspectives: the user’s task, visual hierarchy, accessibility, skeptical first use, and implementation constraints. Each reviewer should identify the most consequential weakness and propose a concrete correction.
- (Optional) Design system. You now have a starting point with some ideas of where else it could go. If you want to go further, you could spend some time iterating on the design system, brand, colors, and so forth. That is typically the thing people start with, but really it should be left for the end (or not done at all, until the product needs are a bit more clarified.) One approach for this is to build out a DESIGN.md file. (You might find this library of DESIGN.md systems useful: styles.refero.design.)
An example exploration
I’m going to walk through how I used this process to iterate on a design for a product I’m prototyping called AutoQA. It’s a simple app for launching QA runs and monitoring outcomes. Its existing design came from only a few basic iterations when I first built it—mostly asking for something “dark and sleek”—so the near-black treatment partly reflected my own prompt. The underlying problem remained: I accepted a plausible visual treatment and kept building.

The baseline looks polished, but its visual choices are not meaningfully tied to the needs of a QA tool. They are broadly “average good”: near-black with one bright accent, all-caps labels, a large sparse heading, rounded containers inside rounded containers, glowing dots, and status pills. The same treatment could have been applied to almost any developer SaaS dashboard.
As an example of where this one-shot design went wrong: Green is not a great accent color for a QA tool. Green should mean passed. Spending it on buttons, decorative glows, and general chrome weakens the most important signal on the page. Everything around it can remain neutral.
First pass: Divergent exploration
I generated four directions with different visual stances: operational, evidence-oriented, calm and editorial, and an attempted wildcard.

The point wasn’t to choose the prettiest color scheme, so I compared them in grayscale first—structure, density, and hierarchy had to carry the design.

A few decisions became obvious once the options were visible:
- Reserve color for meaning. This is a QA tool. Failure red and pass green should dominate at a glance—even when you squint. One direction used red decoration beside passed runs, so it failed immediately. The rest of the interface should be neutral, and status must still be clear through text and shape.
- Give the work enough room. Another direction put the Run Tests action in a permanent side column, compressing every run row. The action matters, but the results are the primary evidence surface.
- Responsive is not the same as stacked. Every option fit at mobile width, but that alone did not make it mobile-friendly. Starting a run and opening a previous result still need to work clearly on a small screen.
- Simple product logic beats visual novelty. These judgments were not exotic design insights. They followed directly from what the tool does.
Concrete options made those ideas easier to see and explain. Books such as Adam Wathan and Steve Schoger’s Refactoring UI help developers build the vocabulary—hierarchy, spacing, contrast, and color—but comparison gives that knowledge something specific to react to.
Second pass: Clarify criteria
All four designs still had nearly identical content and interaction models. That was not meaningful convergence. My brief had required every option to preserve the existing repository header, action, and run list.
Some of those constraints came from earlier LLM-led implementation decisions rather than validated user needs. By freezing them, I made it impossible for the wildcard to question the experience itself.
Before generating another round, I clarified the criteria:
- Which constraints reflect the real user task?
- Which simply describe the current implementation?
- What may the wildcard change—visual treatment, information hierarchy, or the workflow itself?
A later wildcard organized the page around the latest outcome rather than the run list. That was a genuine UX alternative, but the execution made PASS comically large. It was useful because it showed a boundary, not because it deserved to win.

I passed on that execution. The direction I took into adversarial review was a neutral, full-width run history with semantic status.

Third pass: Adversarial review
Once we had a general direction, the next risk was getting stuck in it. I ran five parallel fresh-context reviews to find opportunities the current direction might hide. Three models split the roles: gpt-5.6-sol:high examined the QA workflow and wildcard alternative; claude-sonnet-5:low covered interaction, accessibility, and implementation; and gpt-6-luna:high reviewed hierarchy, design logic, and theme. They suggested several minor changes that improved the direction.
The wildcard critique was more consequential. It proposed organizing the product around distinct unresolved problems rather than chronological runs. I did not adopt that model because it depends on unproven assumptions about grouping failures and knowing when later runs resolve them. But it changed how I thought about the layout: the primary unit may eventually be a problem needing attention, not a run that happened.
Functional or UX-divergent ideas are especially valuable. Instead of iterating only on small choices such as fonts and colors, we should review the different ways the product could solve the problem. This is the right stage to do that—after a direction is concrete enough to critique, but before the design is locked. Otherwise, both people and models can reinforce the same assumptions through every later iteration.


Try it yourself
The next time you have an agent generate a design for you, don’t stop at the first pass. Take a little time to iterate. A little goes a long way.
Each time you do this, you’ll find slight variances in the process that work best for you.
Bit by bit, you’ll find your own aesthetic.