Skip to content

Claude Code Website Audit: Complete Production Checklist

An audit asks what is wrong with what already shipped, and which of it matters. Four passes in a deliberate order, prompts that produce evidence instead of impressions, and the check that quietly lies to you.

Claude Code Guides: Claude Code Website Audit. A page under a magnifying lens with findings ranked beside it.

An audit is not a launch checklist

A launch checklist asks is this ready to ship? An audit asks what is wrong with what already shipped, and which of it matters? The second question is harder, because the site in front of you looks finished. Somebody signed it off. Everything that is broken is broken quietly.

The distinction changes the method. A launch checklist is worked through in order, because the work is sequenced. An audit is an inspection: you gather evidence first and prioritise afterwards, and the order you inspect in is chosen to stop you from being told what to think.

This guide is the method. The list of things to look at is a separate document — the website audit checklist — which is free, ungated, and designed to be handed to Claude Code section by section. Read this for how to run an audit; open that for what to check.

The order that matters

Four passes, and the order is the single most useful thing in this article.

Four audit passes in order. One, crawl every URL recording status, title, description, canonical and word count. Two, fetch the rendered HTML for one page per template, because what ships matters more than what the template says. Three, use the site on a phone and try to complete its primary action. Four, read the code last, once you know what to look for.
Reading the templates first tells you what the site is supposed to do, which makes it much harder to see what it does.

Most audits are run in exactly the wrong order: open the repository, read the components, form a mental model, then check the site against it. By the time you look at the live site you are no longer able to see it. You see your model of it, and your model is built from source that describes intentions.

Claude Code has the same failure mode, more strongly. Give it the repository first and it will describe an excellent site. Give it the responses first and it will describe the one that exists.

Setting Claude up to audit, not to fix

The default behaviour of a coding assistant is to fix things. During an audit that is actively harmful: findings disappear into commits before anyone has decided whether they matter, and the record of what was wrong is lost.

Say so explicitly at the start of the session:

We are auditing this site, not fixing it. For this session:

- Do not edit any file.
- Do not commit, push, or open a pull request.
- Record findings as: URL, what you observed, how you observed it,
  why it matters, severity.
- If you cannot verify something, say so and mark it unverified.
  Do not infer it from the source.

That last rule does most of the work. Without it you get findings phrased as "the canonical tag appears to be self-referencing", which means the template looked right. With it you get "fetched https://example.com/x, canonical is https://example.com/x" or an explicit gap.

If the audit is something you run regularly, this belongs in a skill rather than being retyped, and the "do not edit" half belongs in a hook, where it is enforced rather than requested.

Pass 1: crawl and record

Start with a table. One row per URL, columns for status code, final URL after redirects, title, meta description, canonical, H1 count, and word count. Nothing clever — the point is coverage, not analysis.

Write a script that crawls this site starting from the homepage,
following only internal links, and records for each URL:
status, final URL, title, meta description, canonical, h1 count.

Requirements:
- Pause between requests. Honour Retry-After.
- If any request fails after retries, print an INCOMPLETE banner
  and exit non-zero. Do not summarise a partial crawl as clean.
- Write the results to CSV.

The failure requirement is not decoration. A crawler that hits rate limiting, silently drops nine of twenty-eight pages, and then reports "0 broken links" has told you nothing while sounding authoritative. That happened on this site. The fix was longer backoff and a distinct exit code for a partial run; the crawl then found nineteen more URLs than the throttled one had.

What falls straight out of the table:

  • Duplicate titles and descriptions — sort the column and look for repeats. This is where the most common real finding lives.
  • Missing descriptions — blank cells.
  • Broken links — anything that is not 200 or an intended redirect.
  • Redirect chains — where the final URL is two or more hops away.
  • Thin pages — word counts far below the rest.
  • Orphans — anything in the sitemap that the crawl never reached.

Pass 2: rendered HTML, not templates

Fetch one live page per template type — home, product, article, index, a policy page, the 404 — and read what actually came back.

Things that are only visible here:

Check Why the template will not tell you
noindex in the response Often injected by a plugin, a platform setting, or a header
Structured data validity Liquid or JSX that looks fine can emit malformed JSON
Entity leakage in meta tags Double-escaping only appears in the output
Canonical target Depends on request-time values, not the template
The real <title> Platform fallbacks fire when a setting is empty

That last row is worth an example. This store shipped with its homepage <title> set to the raw .myshopify.com domain, because the theme fell back to it when a setting was never filled in. In a browser tab it looked entirely normal. It was visible only by reading the response.

Validate every JSON-LD block by parsing it, not by looking at it. A block with a trailing comma is invisible to the eye and worthless to a search engine.

Pass 3: use the site

Open the site on a phone, on mobile data, and try to do the thing it wants you to do. Buy something. Send the form. Find the pricing.

This is the pass people skip, and it is the one that catches the expensive problems, because the expensive problems are usually not in the HTML at all. Some categories that only appear here:

  • A call-to-action that is present, valid, and invisible — text at low contrast against its own background
  • A button that links to a fragment which only exists on another page, so clicking it does nothing at all
  • A payment provider that is configured but not activated, where the failure notice is injected by JavaScript and absent from the initial HTML
  • A form that submits successfully and delivers nothing
  • A sticky bar that covers the primary action at 320 pixels

Claude Code can help here with a headless browser, but do not let it replace the human pass. A script checks the conditions you thought of. A person notices the thing nobody thought of.

Pass 4: read the code

Now, with a table of URLs, a set of rendered responses, and a list of things that felt wrong, the source becomes useful. You are not looking for problems any more; you are looking for the cause of problems you have already observed.

Here is the finding: on /pages/about the primary CTA renders with
text and background at the same colour.

Find the cause in the stylesheet. Show me the two rules involved and
which one wins, with the specificity of each. Do not change anything.

Asking for the mechanism rather than the fix is what keeps the audit an audit. It also produces a better fix later, because "a generic link rule outranks the button rule by one point of specificity" tells you something that "changed the colour" does not.

Prompts that produce evidence

Four patterns that reliably return facts instead of impressions.

Ask for the observation, not the verdict. "Is the SEO good?" produces an essay. "Fetch these twelve URLs and print status, title, description and canonical as a table" produces a table.

Ask what would have to be true. "What would have to be true for this check to pass while the feature is broken?" surfaces the gap between what you measured and what you concluded.

Ask for the counter-case. "Find a page where this does not hold." An assistant looking for confirmation finds it every time; one looking for a counter-example finds the exception.

Ask it to break its own check. Covered below, and the single highest-value habit in this entire method.

There is a longer set of these in the prompt library, including the discovery and debugging patterns this leans on.

Severity, and writing it up

Findings sorted by the section they came from are almost useless. Sort by severity.

Severity Test Examples
Critical Money, data, or reachability Cannot buy, cannot contact, data exposed, site not indexable
High A real user is blocked or misled Dead primary CTA, no delivery, keyboard trap, fabricated reviews
Medium Measurable cost, no blockage Duplicate titles, missing structured data, slow LCP, thin pages
Low Noticeable to you, not to them Spacing, copy nits, cosmetic validator warnings

Each finding gets five fields: URL, what was observed, how it was observed, why it matters, severity. The third field is the one that makes an audit reproducible, and the one most reports omit.

State plainly what you could not check and why. An audit that hides its own gaps is worse than a shorter one that admits them, because the reader assumes the gaps were covered.

Five findings from this site

This storefront was built with the method it sells, and audited the same way. Five real findings, all invisible to someone looking at the site:

  1. A primary call-to-action rendered invisible. Text at 1:1 contrast against its own background, because a generic link rule outranked the button rule by a single point of CSS specificity. Found by computing contrast in a rendered DOM, not by reading the CSS.
  2. The homepage title was the raw .myshopify.com domain. A theme fallback that fires when a setting is empty. Found by fetching the homepage and reading the title out of the response.
  3. Every call-to-action on every non-home page was dead. They linked to #buy, a fragment that only exists on the homepage. No error, no navigation. Found by resolving fragment links against the page they appear on.
  4. Checkout could not accept payments. The notice is injected by JavaScript and absent from the initial HTML, so every fetch-based check reported a healthy checkout. Found by rendering the page in a browser.
  5. A fulfilled order delivered nothing. The order was placed with a phone number and no email address, and the delivery app sends by email only. Every status the platform reported said success. Found by checking whether the order actually had an email field.

The pattern across all five: nothing was visibly wrong, and every one was found by fetching something and measuring what came back.

The audit that lies to you

The most dangerous output of an audit is a green check that was never capable of being red.

Every one of these happened while auditing this site, and each was caught only because the check was tested against a failing case afterwards:

  • A link crawler reported zero broken links across a run where nine of twenty-eight pages had returned 429.
  • A checkout check looked for wording in document.body.innerText that only ever appears in an input's placeholder attribute. It could not have fired.
  • A Liquid-error detector matched prose about Liquid errors in an article, and reported a clean page as broken.
  • A digital-delivery check passed on an order that delivered nothing, because it never looked at whether the order had an email address.

So: after a check passes, break the thing it checks and confirm it goes red. Delete a canonical tag. Point a link at a 404. Rename the file the script reads. If the check stays green, it was never a check.

This costs a minute per check and it is the difference between an audit and a document that looks like one.

How often to run it

The full four-pass audit is a project, not a routine. A sensible cadence:

When What to run
Every deploy The crawl, in CI, failing the build on a new 404 or duplicate title
Every template change Rendered HTML and structured data for the affected template
Monthly Search Console coverage, Core Web Vitals field data, dependency audit
Quarterly, or on inheriting a site All four passes

Moving the crawl into GitHub Actions is the highest-value single step, because it turns a thing you remember to do into a thing that happens.

Where to go next

The checklist this article describes running is at the website audit checklist, free and ungated, alongside a launch checklist for sites that have not shipped yet. For the underlying build method, start with how to build a website with Claude Code. For the SEO half specifically, the SEO workflow covers what to check and running a technical SEO audit covers how to prove you checked it. The rules that stop an assistant editing during an audit belong in CLAUDE.md.

Sources and further reading

More Claude Code guides

Free download

The CLAUDE.md Starter Kit, free

Four working CLAUDE.md files you can drop into a project today, plus the one-page checklist for what belongs in one and how to tell whether yours is actually working.

  • CLAUDE.md for a static marketing site
  • CLAUDE.md for a web application, with security and migration rules
  • CLAUDE.md for a Shopify theme, including the gotchas that cost hours
  • CLAUDE.md for a shared package in a monorepo
  • A one-page checklist, and how to test the file is actually working

The download appears here as soon as you submit. I will also email you when there is a new guide worth reading. No fixed schedule, no selling your address, unsubscribe from any email. See the privacy policy.