I gave an agent a design handoff document and asked it to build the site: a real Cloudflare Worker, a real database, a real admin panel I would log into and use myself, rather than a mockup or a prototype.
Specification beats conversation
The handoff document did most of the work before any code got written. It named exact pixel values, exact timing curves, exact copy. It said what was firm, no boxes, no cards, one serif everywhere, and what was open, screenshots, long form project copy, real posts. That distinction mattered more than I expected.
Where the spec was precise, the build was precise. Where I had left something vague, the agent made a reasonable call and told me it had done so, instead of guessing silently and hoping I would not notice.
If I had just described the site in conversation, I probably would have gotten something close. The document got me something exact.
The agent found its own bugs, eventually
The hero headline clips descenders if you do not give the reveal mask enough padding, and mine did not, so the y in "you" got cropped and I only caught it from a screenshot. The homepage ticker referenced a keyframe defined in a different stylesheet, which this version of Next.js quietly refused to resolve, so the marquee just sat still. Two sections had bottom padding but no top padding, so paragraphs ran straight into headings with no room to breathe.
These were ordinary mistakes rather than exotic ones, the kind you only catch by looking at the rendered page rather than the code. Every one got fixed within a few minutes of me pointing at a screenshot and saying what looked wrong.
The lesson here was not that the agent writes perfect code, because it does not. It was that showing it a picture of the actual failure beats describing that failure in words, every time.
Deployment is still the human's job
The agent could provision a database, write the schema, apply migrations, and seed an account, all through tooling that reached Cloudflare on a path its own sandbox allowed. It could not deploy the Worker itself, though, because its environment was blocked from reaching the Cloudflare API directly, so the actual wrangler deploy had to run from my machine, with my credentials, in my terminal.
That felt correct rather than like a limitation to route around. A build that can push itself to production silently, with no human in the loop, is a build I would trust less, not more. I would rather copy and paste a command myself than not know when something shipped.
Windows made this part rougher than it needed to be. Wrangler crashed uploading an eighteen megabyte video over R2's CLI path, and PowerShell rejected the double ampersand as a command separator because I was on the old Windows PowerShell rather than PowerShell 7. These were minor issues individually, but the kind that costs you twenty minutes when nobody tells you what is actually wrong.
Security by default was worth the upfront cost
The admin sign in is not just a hidden path. It runs on bcrypt hashes, opaque session tokens stored in the database, rate limiting on login attempts, and a 404 instead of a 401 when you are not signed in, so a probe cannot even confirm the admin exists.
I never had to ask for any of that twice, or argue for it. It was in the plan before the first line of code got written, because the design document said it had to be, and the agent treated that requirement as fixed, in exactly the same way it treated the type scale as fixed.
That is probably the real takeaway. A specification that treats visual polish and password handling as equally firm requirements produces a build that treats them the same way too. The gaps that showed up, the clipped letter, the missing gap between sections, the ticker that would not move, all lived in the part of the spec that described motion and spacing in prose. The part that described data models and auth flows in structured detail came out right the first time.
Write the specification, check it against a rendered page, fix what is wrong with a screenshot instead of a paragraph, and repeat until it is done. That was the whole loop.