The workflow that actually holds together for me is Claude Code writing the site, Framer MCP giving it a real design surface to work against, and Puppeteer checking that what shipped is what was asked for.
The web build workflow I actually use now has four pieces doing four different jobs, and the thing that makes it work is that none of them is asked to do a job it is bad at. Claude Code writes and edits the code. Framer’s MCP server is what gives it a real design surface to work against rather than a prose description of one. Framer Motion is what actually produces the motion design in the shipped site. Puppeteer is the part that checks, after the fact, that what rendered is what was asked for — not what the code claims it does, what a browser actually shows. Splitting the responsibility this way took longer to set up than asking one general-purpose prompt to handle everything, and it has paid that setup cost back many times over on every build since, because each failure now points at exactly one of four places rather than the whole undifferentiated pipeline.
The step that changed the workflow most was giving the agent a real design surface to work against through Framer’s MCP server, rather than asking it to describe animation in words and hoping the translation into CSS held up. Motion design specified as prose — fade in from the left, slightly delayed — loses precision at every step of that translation. Handing the agent a structural connection into the actual design tool means it is working with the same primitives a person would use by hand, not guessing at how to approximate them in code.
Framer Motion earns its place in the stack specifically because declarative animation composes in a way that hand-rolled CSS transitions do not. When an agent is generating and regenerating a component across several rounds of edits, animation logic tied to component state survives those edits; animation logic scattered across stylesheet selectors does not, because the agent has no reliable way to know which selector still applies after a restructure. I stopped fighting this once I stopped asking for anything the framework was not built to hold.
None of that is trustworthy on its own, though, which is where Puppeteer comes in. The agent will report that a change worked, and the code will often be entirely correct and still not do the thing I asked for, because the gap between correct code and the intended rendered result is exactly where most real bugs in this kind of work live. A scripted browser pass — load the page, wait for the actual interaction, screenshot the actual state — is the only check in the loop that is looking at what a visitor would see rather than what the code claims.
The overall shape is a pipeline rather than a single prompt: generate against a live design reference, render it, verify the render against the request, and only then call the step finished. Skipping the verification stage is the single most common way this kind of build looks done and is not — a passing build and a clean terminal say nothing about whether the button moves the way it was supposed to, and I have shipped exactly that gap before I started closing the loop with an actual screenshot instead of trusting the summary.
What I would not go back to is having any one of these four do another’s job — asking the coding agent to eyeball its own animation, or asking a static screenshot diff to stand in for a real design tool, or skipping the browser check because the code review looked clean. Each piece is doing the part it is actually good at, and the seams between them are where the workflow either holds or does not.
The other thing this setup changed is how I brief the work in the first place. Once I know the agent has a real design surface and a real verification step downstream, I stop trying to describe the outcome in exhaustive prose up front, because the prose was always a lossy substitute for the tools now doing that job directly, and writing less of it and trusting the pipeline more has made the whole loop faster rather than riskier.