Field notes / Building with Claude Code
How I build a client app or site with Claude Code.
AI lets one person do the work of a development team. It does not let one person skip the process the team would have followed. This is the process I ran on two clinic websites, and the part of it that makes the difference: a person in the controller's chair the whole time.
- SpecQuestions become rulings
- DesignSettled before any style
- PlanNumbered tasks, tests first
- BuildDispatched to implementers
- TestCode and content, every commit
- ReviewA model that did not write it
- EditPunch list, approved by number
- RepeatRecords, then the next plan
01 / The one idea
The model is not what separates a finished site from a decent AI template.
- The division of labor is fixed. I make every ruling, review every page on a phone, and write or dictate the copy. The AI sessions do the coding, the testing, and the reviewing, under standing instructions that forbid inventing a provider, a credential, a testimonial, a price, or a service.
- A person guides, decides, and thinks past the defaults. The system checks everything, every time. Neither half works without the other.
- Claude does not catch everything by default. It will drop a section from the old site and tell you the page is complete. It will write "robust" and "seamless" unless you ban them. It will mark a task done when the test asserts nothing.
- Content alignment and attention to the last pixel are not the default. You tease them out, and the tools for that are process, records, and tests.
- Nothing moves forward until it passes. The full test suite runs before every commit, and it covers the content as strictly as the code.
02 / Start to finish
The same sequence on both builds, and the one I would run again.
- 01 ContextRequirements and context. A client meeting, then a project context document: scope, constraints, open client decisions with a default for each, the old-site inventory, the people. Every factual claim is labeled verified, stated, or unverified.
- 02 PlatformPlatform decisions. Framework, host, DNS, forms vendor, analytics, chosen against a written standard I keep for clinic sites, with the vendor research behind each choice.
- 03 BriefThe design brief. What the site should feel like in one line, what it must not look like by name, the photography direction, sample headlines, and the axes the concepts will vary on. Settled before anything is drawn.
- 04 DesignDesign rounds. Concept boards on named axes, with examples and direction rather than "make it different." The client picks one. The pick becomes a theme in words and one wireframe per page type, and the rounds continue at page level through the build (section 04).
- 05 SequenceThe build sequence. The order of the plans and what each one has to leave deployed and testable. It is the map; the plans are the turn-by-turn directions.
- 06 PlansNumbered plans. Each with a spec, a plan, and a ledger. The first build day puts the whole site in draft on a preview address with every unconfirmed claim and placeholder visibly flagged. Everything after is polish, content, forms, search, and review rounds.
- 07 ReviewClient review rounds. The client walks the preview on a phone. Every note becomes a numbered punch list item. I approve by number. Each approved item becomes a plan task with before and after screenshots.
- 08 CutoverCutover as its own plan. Its own runbook, DNS mirrored and compared live before the switch, a redirect crawl before and after.
- 09 DebriefThe written record. What was built, how, and where everything lives, so the client can operate the site and audit the work.
03 / Documents before code
If the thinking is not captured, the session fills the gap with defaults.
The documents are what Claude Code reads first in every session. Whatever it does not read, it fills in with defaults, and the defaults are the template.
- The project context wins any conflict. It opens with "Read this first" and says so: "Where they conflict with this document, this document wins."
- Every claim carries its provenance. "Verified means it was read from the live site, the client's forms, a vendor's documentation, or the Google listing. Stated means the client said it. Unverified means it is an inference or a claim not yet checked. Do not promote an Unverified item to a fact without checking it."
- Open client decisions get a default. A three-column table: decision, default if undecided, build implication. That table is why the build never blocks waiting on the client.
- Client input is converted before it reaches a build session. A 25-message email thread became a one-page handoff with five sections graded by certainty: confirmed in writing, new content, reference material to apply with care, build items still open, not answered yet.
- A client answer becomes a build change and, where it can, a test. A client's decision to keep prices off the site became a build test that fails on a dollar amount in rendered page text.
- The design brief stops the template before it starts. It lists the generated-page tells by name: a cream page with a serif headline and a terracotta accent, every section in the same rounded card with the same soft shadow, a tracked-out all-caps label above every heading, an arrow after every button, numbered 01/02/03 markers on things that are not a sequence. If you do not write that list, you get every item on it.
04 / Design iteration
Decide by looking at real pages on a real phone, then record the decision.
The design is never settled in one round. It is settled in a sequence of rounds that each put choices side by side, and every pick becomes a rule the build has to follow.
- The brief comes first and stays the tiebreaker. Every later question about tone goes back to it, and a punch list item that touches tone cites it by section.
- "Do something different" does not work. Claude's default styles are strong and it slides back to them. Asked to make a page less generic, it hands back the same page with a different accent color. What moves it is specifics: a one-line idea the design serves ("it should look like a family's doctor, not a clinic and not a daycare"; "healthy people keep work moving"), named references to borrow from and named ones to avoid, a palette with values, typefaces by name, sample headlines that set the register, and the list of tells written out one by one.
- Show it, then hold it there. Screenshots and reference pages do more than adjectives. Once the client has picked a concept, every later session builds against that picture and the theme captured from it, not against a fresh description. Expect the defaults to creep back three plans later, a card grid here, a label above every heading there. When they do, the punch list item names the brief section it violates, and if a test can catch the pattern (a font weight, an action color, a label), one gets written.
- Concept boards vary on named axes. The home page concepts were produced as full desktop and phone views and placed on axes: warm versus bright, photo-led versus type-led versus doors-led, doctors above or below the fold, sparse versus dense, pricing shown or not. The variations differ on purpose, so the client's pick says something.
- The pick becomes a theme in words before any style exists. Color roles with values, two typefaces, a type scale, spacing, shape, photography rules, and a component vocabulary. "Brand blue is the only action color and there is no yellow button." "No gradients." "No motion on page load." Tests then enforce the parts a test can reach.
- Boards keep running at page level. The same pick-from-a-board method ran through the build for single problems: six variants of the shared page bottom, three boards for the IEP page, a flow board and a mix board for the testing page. Each board is an HTML file in the project folder with the pick recorded.
- Put the candidates behind a switch on the preview. When the client said the pastels might read too young, the answer was a palette test: two firmer versions of every tint behind a toggle, so he and I looked at the same pages in all three on a phone. The firmer palette won and the portraits were re-backgrounded to match.
- Measure before you rule. The type size change was surveyed before and after on 41 pages at four widths. The body gray was chosen from three candidates shown at real size. The reading column width was measured on the live preview before it went into the theme. A design argument that can be settled by looking is settled by looking.
- Every section has a job. Page order follows the order of the reader's questions. The brief says not to add a section because the page feels short; anything new has to help a visitor decide where to go. The measure of a hero is whether it carries the brand promise, not whether it names the page.
- The phone is the design. Every page is checked at 375 by 812 before 1440 by 900, and the client reviews on his phone throughout. Most of the real design decisions came from that: the hero picture dissolving into the page tint so the headline starts higher, team cards becoming a single swipe row, the action bar that hides whenever its twin button is on screen.
- Reversals are normal and the record keeps both. An item approved as a swipe row was reversed to a wrapping grid the same day after it was seen live. A rule against per-image positioning was reversed when a real case appeared. The punch list carries the approval and the reversal in sequence, so the next session sees why.
- Generated-page tells are a named defect. The brief's list of tells (section 03) is the checklist. When one shows up in a build, it is a punch list item that cites the brief section it violates.
05 / The daily loop
Spec, design, plan, build, test, review, edit, repeat.
The same loop whether the work is a new site or a one-line fix that turned out to be bigger than it looked.
- The superpowers skills run the loop. Superpowers is a set of Claude Code skills that script the workflow.
brainstormingproduces the spec,writing-plansproduces the plan, andsubagent-driven-developmentexecutes it with implementers and reviewers as separate agents. CLAUDE.md names which skill governs which step, so a session does not improvise the process. - Size the request first. A controller edit is content the client dictates verbatim, a record update, or a one-line fix with no logic. It gets a decision row and a commit. Everything else goes through the full loop, even when it arrives phrased as a quick tweak. When unsure, it is not a controller edit.
- Brainstorm to a spec. Every open question is answered one of three ways: a dated ruling from me, a cited source, or a ruling made on my behalf. Every ruling carries its cost if wrong, and the spec ends with a rulings table: ruling, why, cost if wrong.
- Record cost if wrong on every ruling. "The page shows the old page's visible durations until the clinician confirms. Why: they are what the practice publishes today. Cost if wrong: edit three strings." A cheap reversible call gets made; a costly one gets escalated to me.
- Produce the plan. Numbered tasks with the files, the interfaces each task produces and consumes, the test written first, and the commit message. Before the first dispatch, a preflight table checks that the tasks agree with each other. The last task on every plan is the records, and it runs in the controller session, never an implementer.
- Build with subagents, from the controller's chair. The main session is the controller and works under my direction: it dispatches, reviews, rules, measures the built site, and writes the records. It does not write feature code. Implementers get no browser, no API access, and no subagents of their own. Two implementers never share one working tree at the same time, because they overwrite each other; parallel work needs its own checkout.
- Let an implementer say BLOCKED. Plans contain defects. An implementer that stops on a wrong brief and waits for a ruling is doing its job. The ledger records the ruling that unblocked it.
- Test before anything moves. Every task starts with its test. Every commit runs the full suite and the type check first. A task that cannot pass is not committed, reviewed, or merged.
- Test content like code. Unit tests check logic in isolation. Build tests run a production build and read the output the way a crawler would: one top-level heading per page, alt text on every image, no em dash in the copy, every title naming a place, every description between 120 and 160 characters, every office phone and address character-identical on the page, in the structured data, and in the AI-readable file, every price in the structured data visible on the page, every search term in the page's own copy, only loaded font weights used, every color pair at WCAG AA contrast, no vendor script anywhere, every item carried from the old site still on its page.
- Gate the launch with the same suite. A launch mode fails while any unverified claim, placeholder, or open inventory row remains. The site cannot go live until it passes. A test that asserts nothing is a defect.
- Review on a model that did not write it. Each task is reviewed by a separate model before its commit, with a fix round and a scoped re-review when the review finds something. The whole plan is reviewed at the end by a third model that has not seen the work being produced, followed by one fix wave and a re-review.
- Look at the built site. Implementers cannot see it and reviewers read code. The controller session builds it and measures at 375 by 812 before 1440 by 900, recording the numbers in the ledger, and I review every page on a phone. "The column is 327px but the lead image is still 797px and the page still scrolls to 822." The review had passed that task. The measurement caught it.
- Preview feedback becomes a punch list. Each item says where the problem shows, what is wrong, what it falls short of, the proposed change, and which screenshot to look at. The header on every punch list: "Status: waiting for Chris's approval by item number. Nothing has been changed."
- Append, never delete. Approvals and reversals are added to the item in bold, so a later session can see that item 10 was approved as a swipe row and reversed to a wrapping grid the same day after I saw it live.
- Stop at the stops. A plan names its approval stops: a shot list, a punch list, a copy audit, a design review, the merge. At a stop the session reports and waits. "Do not continue past a stop on inference."
- Update the records at the end of every session. Decision rows, unverified lines, the runbook section if anything new is operable, and the ledger copied from the disposable workspace into the project folder. One plan's review notes were lost because that copy was skipped once.
06 / The records
A session starts with nothing. The records are its memory.
What a session knows about the project is what it reads, so every record has to be something a stranger could pick up and continue from.
- CLAUDE.md. The standing rulebook every session reads first: content rules, the no-invention rule, the no-vendor-script rule, the records, the review process, the stops. Both projects also point at a stack standard I keep across clinic sites (framework, host, forms, analytics), so those choices are made once.
- The project context. The why, the constraints, the open decisions. Wins any conflict.
- DECISIONS.md. One row per technical or client decision, dated, with one line of rationale. Client decisions name the person and the date received. Superseded rows are never deleted; the new row says what it supersedes. Each site launched with several hundred rows.
- UNVERIFIED.md. Every claim nobody has confirmed with the client or against a vendor's current documentation. Nothing on it goes in a plan or on a page as fact. Each line names the file where the claim sits and who can close it.
- RUNBOOK.md. How to do every routine thing without me or an AI session: change hours, add a provider, swap a form, roll back. Documentation passes when someone else can operate the site from it.
- Specs, plans, ledgers. One of each per plan, in the project folder. The ledger logs every dispatch, review result, fix round, and ruling.
- Punch lists and screenshots. Numbered items with their approvals, and before and after captures at both widths for every approved item.
- The build sequence. One paragraph per plan with its spec, plan, ledger, and merge commit named.
- CUTOVER.md. The launch runbook as it was run, with what to do after and how to roll back.
07 / Working with Claude Code
What I do at the keyboard, and why.
- Build the session prompt as a document. Each kickoff prompt is a file in the project folder with the same sections: a one-paragraph why, "Read first" with exact paths, preconditions, where things stand as of a date, the work in numbered order, the stops, and the house rules.
- Check the state before the work. "git fetch and confirm local main matches origin/main. Confirm no other session is working in the checkout. Tell me if either isn't true."
- Paste the house rules every time. "npm test and npm run check before every commit, model trailer on commits, every ruling a DECISIONS.md row with its cost if wrong, ledger copied to the project folder at the end of every session, no em dashes, you never generate images, nothing is pushed until I say push."
- Keep resume prompts short. The records carry the context. "Resume Plan 5 from its ledger per site/CLAUDE.md." "Preview feedback below. Add it to the punch list and stop for my approval." "Controller edit per site/CLAUDE.md: the exact text and where it goes."
- Bring questions at the right step. "Questions that need my ruling, bring them at that step, not mid-build." A session that stops every ten minutes did not brainstorm properly. A session that never asks is making rulings you did not see.
- Approval for one thing does not cover the next. "Ask me before anything outward: every email, every Cloudflare invite, every push." The session never enters credentials or creates accounts. Secrets live in a config file it reads and never prints into chat.
- Fix the copy, never the test. Claude will offer to loosen the test, widen the regex, or add an exception. The answer is no. Each content test exists because a human caught something once and said it must not happen again. Loosening the test deletes the lesson.
- Turn feedback into a test. A client's note that small prices look suspicious became the name of a test. "Current wording sounds like clicking is committing" became a build test that fails on any "Become a member" link. A ruling that lives only in chat is gone by the next session.
- Close on evidence, not on a change. "No change for item 17: the 6px overhang was measured only inside the closed details element and never widens the page." Claude will change working code to make a note go away. Make it prove the problem first.
- Do not edit from inference. When a legal page contradicted a staff correction, the practice supplied the wording. When a price was still being decided, the site got a neutral line until the practice settled it. A plausible answer on a medical practice's website is a liability.
- Pick the model for the job. Implementers on Sonnet, task reviewers on Opus, scoped re-reviews on Sonnet, the final whole-plan review on Fable. The work is never grading itself.
- Script anything repeatable. The old-site audit rendered every page in a headless browser and diffed them. Share cards are generated from the site's own credited images. Forms were created from build sheets through the vendor's API, with a test that fails if the live form drifts from the sheet. The DNS zone was compared live against both nameservers before the switch.
08 / Lessons learned
What AI did not catch by default, and what changed because of it.
- The process drifted the moment nothing enforced it. After four plans on the full workflow, the main session made 28 commits straight from my preview feedback with no spec, no plan, and no review. The repo had no CLAUDE.md, so nothing told a new session what the process was. The session follows the process only if the process is in a file it reads first. Your own discipline is not enough, because the session cannot see it.
- A decision was written without reading the source. The old Media page was redirected to the home page because "the captured page holds only the shared navigation." It held 20 newsletters, a podcast, three books, and four videos the capture never saw. Nobody noticed until the client asked what had happened to the practice's video. Every item on the old site now gets an inventory row, and a test fails if a carried item leaves its page or a dropped item lacks a named, dated decision.
- The AI version looked complete until a human compared it to the original. "If I'm the clinician, I'm going to look at the new page and go 'where did everything go?'" Claude will produce a clean page and report it finished. Whether it carries the content the practice needs is a question only a person asking "what would the clinician think" can answer.
- The spec itself can be wrong, and the final review is the net. A spec misread the old page and dropped a visible fact as if it had been hidden copy. The third-model review caught it. Three layers of review exist because each one catches what the previous one wrote.
- A sync overwrote a live form. An automated synchronization matched a form's paragraphs one slot off and overwrote them, so the live form showed the wrong text. The whole-branch review caught it the same hour. The paragraphs are now pinned by name, and the incident is in the decision log.
- The reviewer caught what the implementer would have shipped. A regex that read $1900 as 190. An analytics config that would have sent a form value to Google on the second click. A thumbnail lazy-loaded because "the spec had said lazy everywhere" when it was the page's largest paint. A test that asserted nothing because the thing it checked for had been renamed.
- The controller caught what the reviews passed. Three titles that looked bolder and pixelated because a 600 weight was never loaded and the browser faked it. A hero button sitting directly above its twin in the phone action bar. A 327px column with a 797px image. Reviews read code. Somebody has to look.
- Copy drifts toward the generic unless you push on every line. "Drop concierge." "A stat is not exactly a 'let us partner with you' closer." "An empty lobby says the opposite." "Every hero should be quietly reinforcing the brand message, not just a form title." Each is a decision row, and each is a line Claude wrote that was fine and was not right.
- Audit the copy in a table. Every row of new copy with a Decision column for approve, strike, or my edit, applied only after I decide. The intentionality is in the edits, word by word.
- Facts disagreed with each other and nobody flagged it. One old site priced the same service two ways on two pages. The other published its hours three ways. A build carries the contradiction forward without comment. The unverified list is where it goes, and the client is who closes it. What nobody confirmed was pulled from the launch build rather than published.
- Launch day had surprises, all now in the playbook. A DNS sweep missed three records the zone export held, so the export is mandatory. The old platform kept serving the bare domain for 20 minutes after its record was deleted. The old preview address stayed reachable and indexable for a week. One form's routing decision turned out to be wrong: nothing was broken, and a person noticed the next morning.
09 / What it produces
None of it needed a team. All of it needed the process.
- Two sites, built in parallel in under a month by one person and a set of AI sessions.
- Several hundred dated decisions on record for each site, with the reasoning and, for client decisions, the name and date.
- Several hundred automated checks that run before every change ships, on the content as well as the code.
- Every item from the old site tracked to the new one or dropped by name and date.
- Perfect or near-perfect mobile Lighthouse scores at launch, and zero vendor scripts on any page.
- Everything in accounts the client owns. Nothing depends on my login or a vendor's.
10 / Your first project
The checklist.
- Produce the context document before you open Claude Code. Label every claim. List the open decisions with a default for each.
- Produce the design brief, including what it must not look like. Run a concept round on named axes. Capture the theme in words before any style exists. Settle every later design question by putting the candidates side by side on a phone.
- Create CLAUDE.md on day one. The records, the review process, the stops, and the no-invention rule. The session reads it first, every time.
- Size every request. Controller edit, or full loop. When unsure, full loop.
- Spec, design, plan, build, test, review, edit, repeat. Every question gets a ruling with its cost if wrong. Every task starts with its test. Nothing is committed, reviewed, or merged until the whole suite passes, content checks included. Every plan ends with a review on a model that did not write it.
- Look at every page yourself, phone first. Record what you measured.
- Turn every catch into a test. Fix the copy, never the test.
- Hold the three lines. Nothing unconfirmed goes on a page. Nothing is pushed until you say push. Nothing continues past a stop on inference.
- Copy the ledger before the session ends.
- Compare the new site to the old one, item by item, before you call anything done. Ask what the client's expert would say when they see the page.
The AI will do the coding, the testing, and the reviewing. The guiding, the deciding, and the thinking past the defaults are the job. That part does not get faster, and it is the part the client is paying for.