Product Design · Full Stack · AI2026

Traffic isn't
the problem.
Your landing page
is.

PageAudit runs two independent AI audits — UX conversion and AI citability — and tells you exactly what to change. Built solo in 5 weeks. The conversion expert SMBs couldn't afford, until now.

2live audits in parallel
5 wksconcept → shipped
1person
pageaudit.app
UX Conversion
Needs Work
3Crit
2High
4Med
1Good
AI Citability
Good Foundation
Structured Data62
Extractability74
Discoverability55
CriticalCTA Optimisation
CTA reads "Submit" — names the action, not the outcome
Change to "Get My Free Audit" — this phrasing typically lifts CTR 20–40% by making the value explicit before the click.
01The Problem

Generic audits give
generic advice

Store owners don't need a score. They need the element, the fix, and the expected uplift — specific enough to hand to a developer or implement themselves that afternoon. That gap is PageAudit.

Generic audit tool
PageAudit
"Improve your CTA"
"CTA text 'Submit' names the action, not the outcome — change to 'Get My Free Audit'"
"Add schema markup"
Exact JSON-LD block, copy-paste ready, mapped to your page type and product category
Score drops 4 points — no explanation
Score computed from finding severities — deterministic, never changes on re-run
One audit. Hope it covers the right things.
UX conversion + AI citability — different disciplines, different owners, both fire simultaneously
12→150K
HTML characters sent to AI — raised 12× after Shopify pages returned blank generated output. The entire product section was being truncated before Claude even started.
3
Root causes behind blank generated pages — truncation, lazy-loaded images, protocol-relative CDN URLs — each one hiding the next. Fixed in sequence over three debugging sessions.
Who this is for

A local barber — good reviews, working website, booked solid on Fridays, invisible on Saturdays. No marketing budget. No idea why the shop down the road shows up when someone asks ChatGPT "best barber near me."

AEO awareness — 10 business owner conversations
8 / 10hadn't heard of AEO — not aware the discipline exists
1 / 10had heard of it but didn't know how to start
1 / 10was actively working on AI citability
Informal research sprint · May 2026
02The Build
01Discovery
02Architecture
03Design
04Build
05Fix Generator
06Polish
07Deploy
Phase 01
Discovery
What I found
Three free tools auditing the Greenscents product page — all measuring technical performance. Zero findings on conversion or AI visibility. The only AEO tool available required a business email.
0 tools audited UX or AI visibility for a single page.
Phase 02
Architecture
Obstacle — CommonJS vs ESM
node-fetch v3 is ESM-only. Switching the whole project to ESM meant refactoring every file — instead, one dynamic import wrapper.
const fetch = (...args) => import('node-fetch').then(({ default: f }) => f(...args));
One line. CommonJS stays, node-fetch works, nothing else changes.
Phase 03
Design
Obstacle — Broken symmetry
The two verdict cards rendered at unequal widths — one two-thirds, one third. For a tool presenting scored results side by side, the layout looked broken and undermined trust in the scores.
grid-template-columns: 1fr 1fr — equal cards, trustworthy scores.
Phase 04
Build
Obstacle — Non-deterministic scores
Claude returning different scores on re-runs of the same page — 62, then 58, no findings changed. Score stripped from Claude output and computed server-side from finding severity counts. Both audits fire in parallel — UX findings and AI citability score (31/100) returned together.
Same input, same output — every time. Both audits fire in parallel via Promise.allSettled.
Phase 05
Fix Generator
The challenge
The third output would hand the client a working improved HTML file — not a list of recommendations: an actual deliverable. First run: blank white page. The problem wasn't the prompt. It was the data going in.
Pages load. Three root causes fixed in sequence — truncation, lazy images, protocol-relative URLs.
Phase 06
Polish
Obstacle — False Critical finding
Claude flagged Greenscents' delivery information as Critical — "no delivery timeframe shown" — when it was present on the page. Added extractPageFacts(): Puppeteer extracts verifiable DOM facts before Claude analyses anything.
Delivery finding flipped from false Critical to correctly marked Good.
Phase 07
Deploy
Decision
Launch UX audit + AEO audit without the generator. Generator quality not ready for public use — the honest call was to ship what works rather than what looks impressive on paper.
Shipping constrained scope is a product decision, not a failure.
Discovery Image 1Discovery Image 2
Discovery Image 3Discovery Image 4
package.json
{
  "name": "2026-ai",
  "version": "1.0.0",
  "main": "index.js",
  "type": "commonjs",
  "dependencies": {
    "@anthropic-ai/sdk": "^0.91.1",
    "cors": "^2.8.6",
    "dotenv": "^17.4.2",
    "express": "^5.2.1",
    "node-fetch": "^3.3.2",
    "puppeteer": "^24.43.0"
  },
  "scripts": {
    "dev": "nodemon src/server.js",
    "start": "node src/server.js"
  }
}
BeforeDesign Image 1
AfterDesign Image 2
Score systemBuild Image 1
Deterministic scoringBuild Image 2
✕ v1 — blank pageFix Generator — blank page
False CriticalPolish Image 1
Correctly GoodPolish Image 2
Deploy
02The Build

Seven phases,
seven obstacles.

Tap a phase to explore the problem and fix.

01
Discovery
No UX or AEO tools found
What I found
Three free tools auditing the Greenscents product page — all measuring technical performance. Zero findings on conversion or AI visibility. The only AEO tool available required a business email.
0 tools audited UX or AI visibility for a single page.
Tool 1Tool 2
Tool 3Tool 4
02
Architecture
CommonJS vs ESM conflict
Obstacle — CommonJS vs ESM
node-fetch v3 is ESM-only. Switching the whole project to ESM meant refactoring every file — instead, one dynamic import wrapper.
const fetch = (...args) => import('node-fetch').then(({ default: f }) => f(...args));
One line. CommonJS stays, node-fetch works, nothing else changes.
package.json
{
  "name": "2026-ai",
  "version": "1.0.0",
  "main": "index.js",
  "type": "commonjs",
  "dependencies": {
    "@anthropic-ai/sdk": "^0.91.1",
    "cors": "^2.8.6",
    "dotenv": "^17.4.2",
    "express": "^5.2.1",
    "node-fetch": "^3.3.2",
    "puppeteer": "^24.43.0"
  },
  "scripts": {
    "dev": "nodemon src/server.js",
    "start": "node src/server.js"
  }
}
03
Design
Verdict cards unequal width
Obstacle — Broken symmetry
The two verdict cards rendered at unequal widths — one two-thirds, one third. For a tool presenting scored results side by side, the layout looked broken and undermined trust in the scores.
grid-template-columns: 1fr 1fr — equal cards, trustworthy scores.
BeforeDesign before
AfterDesign after
04
Build
Scores vary on re-run
Obstacle — Non-deterministic scores
Claude returning different scores on re-runs of the same page — 62, then 58, no findings changed. Score stripped from Claude output and computed server-side from finding severity counts. Both audits fire in parallel — UX findings and AI citability score (31/100) returned together.
Same input, same output — every time. Both audits fire in parallel via Promise.allSettled.
Score systemBuild 1
DeterministicBuild 2
05
Fix Generator
Three chained input failures
The challenge
The third output would hand the client a working improved HTML file — not a list of recommendations: an actual deliverable. First run: blank white page. The problem wasn't the prompt. It was the data going in.
Pages load. Three root causes fixed in sequence — truncation, lazy images, protocol-relative URLs.
✕ v1 — blank pageBlank page
06
Polish
False Critical on delivery
Obstacle — False Critical finding
Claude flagged Greenscents' delivery information as Critical — "no delivery timeframe shown" — when it was present on the page. Added extractPageFacts(): Puppeteer extracts verifiable DOM facts before Claude analyses anything.
Delivery finding flipped from false Critical to correctly marked Good.
False CriticalPolish before
Correctly GoodPolish after
07
Deploy
Ship without the generator
Decision
Launch UX audit + AEO audit without the generator. Generator quality not ready for public use — the honest call was to ship what works rather than what looks impressive on paper.
Shipping constrained scope is a product decision, not a failure.
Deploy
03Honest Assessment

The Generator:
working isn't the same as good

Three engineering problems fixed. The output still isn't ready to ship.


The generator went through three rounds of debugging — truncated HTML, lazy-loaded images, broken CDN URLs — each fix revealing the next problem. That story is in ↑ Build — Phase 05. This section is about what came after the fixes.

The generator works. Pages load, images appear, layout holds. The question is whether the output is good enough to put in front of a client.


Result — Greenscents product page
Original pageOriginal Greenscents pagegreenscents.co.uk — product page with full image gallery
Generator outputGenerated pageGenerated page — main image loads; gallery row missing
Honest note: The generated page loads and the main product image appears. But the product image gallery is gone — the row of alternate views below the hero, standard on the original, disappears entirely. Shopify's gallery is JavaScript-driven; strip the JS and the thumbnail carousel goes with it. For a product page, that's a meaningful loss. The generated page is functional — but it's worse than the original.

Output quality failures
Quality gap
Logo redrawn, not copied
The prompt instructs Claude to copy the logo verbatim — paste the img src or inline the SVG unchanged. When the original doesn't load cleanly from the screenshot, Claude fills the gap by redrawing it: a geometric approximation with similar colours and vague letterforms. The brand mark, with its specific proportions and typeface, gets replaced with something plausible at a glance but visibly wrong up close. A client notices immediately.
Original logo
Original
Claude redrawn
Generated
Quality gap
Reads as AI-generated
Beyond specific missing elements, the output doesn't meet professional standard. Typography defaults to safe ratios rather than the brand's own rhythm. Spacing becomes templated — even, predictable, characterless. Layout patterns collapse toward familiar defaults regardless of what the original chose. The model makes safe bets where a designer made decisions. Anyone who works with agencies or in-house design teams will identify it immediately — and for a product built on design credibility, that's the disqualifier.

The decision
🔒
Why the generator is hidden for launch
The audits are strong. The generator isn't ready.
Shipping a generator that produces pages worse than the originals would undermine everything the audits build — a reputation for precision. The generator is in the codebase and improving, but it needs to be demonstrably better than the original before a client sees it. The UX audit and AEO audit stand on their own as a launch product. Hiding the generator was the right call.
04Reflection

Three things
this project settled

On data pipelines, design intent, and when to ship less.

01
AI tools that make claims about reality need a verification layer

The most meaningful improvement to the audit — more than any prompt change — was adding extractPageFacts(): a Puppeteer step that measures the page directly before Claude analyses anything. CTA position, delivery text, return policy, review count. Ground truth first, inference second.

The result was immediate: a finding that had been marked Critical for months flipped to Good in the first run. Not because the model got smarter — because it stopped having to guess at things that were directly measurable.

This pattern generalises beyond this product. Any AI tool making claims about observable reality needs a verification step before inference. The model is operating on a compressed representation of reality. The verification layer is the difference between an audit and an impression.

If I were building this again, the data pipeline would be designed first. The prompts come second.
02
Design intent doesn't survive HTML serialisation

The generator's failure isn't a prompting problem. It's a category problem.

A product page's spacing decisions, typographic hierarchy, and visual rhythm were made by a designer for reasons that aren't encoded in the markup. The HTML records what was produced, not why. Asking Claude to improve that page while preserving its design intent is asking it to infer a decision-making process from its output — with no access to the brief, the brand guidelines, or the constraints the original designer worked within.

The generator can reproduce structure. It can't reproduce intent. What it produces is a page that satisfies the same functional requirements with different — usually worse — aesthetic decisions. Professional designers notice this in seconds.

The fix isn't better prompting. It's a different product model: the AI handles production, the designer retains authorship.
03
Constrained scope is product strategy, not a failure to finish

Shipping UX audit + AEO audit without the generator wasn't a compromise. It was a recognition that each part of the product makes a different promise.

The audits promise precision — specific, verifiable findings backed by DOM data. The generator promises transformation: a better version of your page, ready to use. That's a much stronger claim, and the current output doesn't support it. Shipping both together would have meant the generator's failures discrediting the audit's accuracy in the same session.

Product credibility is harder to rebuild than it is to establish. A client who receives a generated page with a redrawn logo and a missing gallery doesn't then trust the Critical findings in the audit above it.

The constrained launch is the strategy. The generator ships when it's better than the original.
Closing thought

What this project settled: the value a designer adds to an AI product isn't visual — it's architectural. Knowing what to verify before the model sees it, what intent can't be extracted from structure, and when to constrain scope to protect credibility — those are design decisions. The prompts are the easy part.

Thank you

Thank you

© Copyright 2026

© Copyright 2026

© Copyright 2026