Why AI coding agents are bad at frontend, and how to fix it
The agent reports success. Tests green, build clean, 300 lines of new component
code. You open the page and the submit button is halfway off the card, the empty
state is a bare <div>, and on a phone the layout stacks into a column nobody
would ship.
None of that is a bug the agent could have caught. It just looks wrong, and the agent has no idea, because it never saw it.
Your agent is writing UI blind
Backend work has a natural scoreboard. The endpoint returns 200 or it doesn't. The test passes or it fails. An agent can run the suite, read the output, and know whether it's done.
Frontend has almost none of that. "Compiles" and "renders without an error" are a very low bar, and everything above it (spacing, hierarchy, alignment, whether the thing reads as one screen or three glued together) is invisible to a process that only ever sees source text.
So the agent optimises for what it can verify. It writes plausible markup, adds classes that sound right, declares victory, and hands you a diff that passes code review and fails the eye test. The gap isn't intelligence. It's a missing feedback loop.
Give the agent eyes
The single biggest upgrade to frontend agent work is letting it see the result. Most coding agents can now drive a browser or take screenshots through a tool integration, exactly the gap the Model Context Protocol exists to close, connecting the agent to your running app instead of just your files.
Once it can look, change the instruction. Not "build the settings page" but:
Build it, open
/settingsat 1280px and at 390px, screenshot both, and tell me what's wrong before I look.
Two things change. The agent catches its own overflow and misalignment, because now those produce evidence. And you get a description you can check in ten seconds instead of a diff you have to run yourself.
Make the loop explicit in the task: change → render → look → fix → look again. Agents rarely invent that loop on their own, but they follow it reliably once it's written down.
Point at code, not at adjectives
"Make it look more modern" is not a brief. The agent picks a font stack, a new shade of blue and a shadow you didn't ask for, because you gave it taste instead of constraints. What works is pointing at something that already exists:
- "Match the card in
BillingPanel.vue: same padding, radius and heading size." - "Use the spacing scale already in the config. Don't add new values."
- "Reuse the existing
Buttoncomponent. Ask before adding a variant."
Copying beats inventing. An agent is good at lifting a pattern from one file and applying it to another. It's much worse at originating a visual language, and worst of all at knowing which of your six historical button styles is current.
Which is why your standing UI rules belong in an AGENTS.md file: the component library, the token names, the file that owns your theme, and the list of patterns you've deprecated. Written once, applied on every task, instead of re-explained in every prompt.
Check the states nobody screenshots
Most UI bugs from agents aren't in the happy path. That's the one state they render while building. Ask for the rest by name.
- Empty. No results, no data yet, first run.
- Loading. And what the layout does when real content swaps in.
- Error. A failed request that doesn't wipe the page.
- Too much. A 60-character name, forty rows, a paragraph where you expected a word.
- Narrow. Whatever your smallest supported width actually is.
- Dark mode, if you have one. Hard-coded greys surface here immediately.
- Keyboard. Focus rings, tab order, anything reachable only by mouse.
That list is most of the value in this post. Paste it into the task and the agent handles the boring 80%, the part you'd have skipped at 6pm.
The honest limits
An agent can tell you a button is misaligned. It cannot tell you the screen is confusing, or that you're asking for three decisions where one would do. Screenshot loops verify conformance to a spec, not quality of judgement. Taste is still your job, and treating a clean screenshot as approval is the frontend version of trusting the diff because it's confident.
The loop also costs something. Rendering, screenshotting and re-checking burns time and tokens, worth it for real UI work, overkill for a copy change. And accessibility beyond the obvious still needs a human or a dedicated audit.
Keep the app next to the agent
All of this is easier when the thing you're building stays visible while it's being built. That's the shape SanuDesk is built for: a desktop app where your Claude Code, Codex and Gemini sessions tile into one grid, each workspace pointed at a project folder, so the agent and the app under test sit side by side instead of buried in tabs.
The Kanban board is where the checklist above stops being a paste. One card per screen, the states written into the brief, deployed to an agent and reviewed when it reports back. Loops run the recurring version: a nightly sweep across your breakpoints, or a fresh pass over every empty state after a design change. It drives the agent subscriptions you already pay for, and the free tier is a real one.
Try it on the next UI task
Take whatever frontend ticket is next. Write the brief with a component to copy, the states to check, and an instruction to screenshot before reporting done, then judge what comes back on how it looks, not on whether it compiled.
Download SanuDesk free and point a workspace at your repo, or see how the grid, the board and Loops fit together on the features page.