Every AI coding agent on the market right now can build you a page in 30 seconds. Cursor, Claude Code, GitHub Copilot, OpenAI Codex, Windsurf: the shortlist is the same and the demo looks identical. The page ships. The diff is a different story.
Nadeem Ur-Rehman is a UI architect who still writes frontend and reviews the PRs that arrive with the note “the agent basically did it.” He ran a real test: an internal landing page in Angular and TypeScript using his team’s existing design-system components. He got the 30-second page. Then he read the file.
️ What the Agent Actually Produced
The first output had demo glow. Soft cards, fat hero, CTA doing too much. Underneath the surface:
- A new card primitive instead of the team’s existing one
- Hardcoded spacing instead of design tokens
- “Responsive” layout that assumed one iPhone viewport
- Accessibility that passed a linter but failed keyboard navigation
- No empty state, no real error state
He called it eighty percent of a mid-level first draft. Fast, but one merge from becoming the team’s problem permanently.

The Core Distinction Worth Keeping
He draws a clean line between two modes that the internet keeps conflating.
Vibe coding is describing what you want and accepting what comes back. It works for prototypes. It becomes a curse around week three when nobody has actually read the code.
Agentic engineering is everything around the model: a spec before the first prompt, a definition of done, tests, a PR review step, and sometimes MCP tools with a harness so rules are enforced rather than suggested. Same model. Opposite outcome.
The loop he describes showing up in engineering Slack: Issue → Agent → PR → Review → Release. Generation is cheap now. The bottleneck moved to whether a human read the diff.
The Prompt Contract (Copy This)
He stopped chatting with the agent and wrote a structured prompt contract instead. Same agent, same ticket. The second pass landed on the team’s components, their tokens, real states, and five explicit tradeoffs he could argue against before merge.
Here is the full template. Change the stack. Do not delete the refusals.
[ROLE]
You are a senior frontend engineer inside an existing design system.
Write code a staff engineer can review without reconstructing your intent.
[CONTEXT]
Internal tools. Angular + TypeScript. Our UI kit. Existing routes.
Match: {{path to similar page}}
Use only: {{tokens + components}}
If you have MCP / repo tools, read those files first. Do not guess.
[TASK]
Landing page: hero, 3-6 feature cards, testimonials, one primary CTA.
Mobile-first. Production repo, not a prototype.
[DEFINITION OF DONE]
loading / empty / error / success
semantic HTML, keyboard path, WCAG 2.1 AA as a floor
matches existing patterns, not a generic SaaS layout
[HARD NO]
new npm packages
global CSS
new primitives we already have
hardcoded color, space, or type
touching auth or routing
[OUTPUT]
file list
code
5 bullets I should fight you on before mergeThe [HARD NO] section is the part most people skip. It is also the part that does the work. A vague task in a capable agent still ships fanfic. A tight task with explicit refusals gives you a reviewable PR.

Common Pitfalls
If you need fifteen follow-up prompts to finish one ticket, your spec is a group chat. The model is not lost. The task was never clear.
Tool comparisons (Cursor vs Claude Code vs Copilot vs Codex) are useful but secondary. A sloppy task in a great agent still produces problems. A tight task in a less hyped agent still gives you something mergeable.
New models advertise fewer prompts and better UI generation from screenshots or design system files. That adherence capability does not help if your repo’s component rules, token names, and architectural decisions are not in the prompt.
On the “AI Taking Jobs” Question
He frames it this way: AI will take the job of generating the first 70 percent, the scaffolding, the CRUD screens, the “make me a table” requests. It will not replace the person who writes the definition of done, knows which component must be reused, rejects a new dependency, reads the diff, and owns the incident when the empty state was never built.
If your identity is typing every line, the floor moved. If your identity is architecture, constraints, and review, you have a faster junior who never sleeps and never feels shame about the PR.
Same agent. Different prompt. Read the diff before you merge.

