The audit I run on other people
I measure contractors’ websites for a living. So here is mine.
This is the same audit I send out unsolicited, run on my own site, published whether it flatters me or not. The numbers are measured, not estimated.
Some of it I found while building. The rest was found after the site was already live, which means it was live and broken while I was telling other people to check theirs. The last section is the one that matters: the faults still here, and why.
The schedule
25 findings on my own site
Worst first. Open any line for the whole story, including how I found it.
- Findings
- 25every one of them published
- Closed
- 20fixed and re-measured
- Still open
- 5listed below with the reason
- Cost me work
- 5enquiries I will never know about
-
01 The contact form threw every enquiry away Cost me work
It said “Thanks, I’ve got it” and sent nothing. Anyone who filled it in was told I had their details, and then never heard from me.
It had no action, no method, and no name attribute on a single field. On submit it hid itself and printed “Thanks, I’ve got it.” Nothing was sent anywhere. Anybody who filled it in would have been told I had their details, and then never heard from me again.
Two sections further down, the same site tells contractors to test their own contact form on the first of every month.
Fixed: it posts properly now, the success message only appears on a real confirmation from the server, and if the send fails it shows my phone number instead of pretending.
-
02 The portfolio links went to a page that was not the portfolio Cost me work
All three “open them on your phone” links opened an empty grey shell instead of the work.
All three “open them on your phone and time them yourself” links pointed at a host that returned an identical 14,716 byte shell for every one of them, titled Claude Artifact. The demonstration sites themselves never loaded.
That failed in front of exactly the person I most wanted to impress: the one who took me up on the invitation.
Fixed: all three now sit on this domain under /work/, with real titles, and deliberately hidden from search.
-
03 The site was invisible to everyone for the first hour Cost me work
The host was returning “unauthorised” to the entire world while I sat here thinking it was live.
Manually deployed sites on this host start private. The site returned HTTP 401 Unauthorized to the entire internet while appearing to work perfectly when I looked at it.
It was only caught by requesting the page from outside rather than trusting the browser tab that was already open.
-
04 The share image was saved as share.jpg.jpg Cost me work
Every time anybody shared the address, the preview came up as a blank grey box.
Windows hides known file extensions, so typing “share.jpg” produced share.jpg.jpg. The tag pointed at a file that did not exist. Every time this link was shared it would have rendered as an empty grey box.
Fixed: renamed, and verified live at 1200 × 630, 51 KB.
-
05 I published three numbers about my own speed, measured three different ways Told you something untrue
My own site claimed to be heavier than the demonstration sites I built to show off, under the words “measured just now.”
The tile said this page weighed 48 KB. That was the size of the file on disk. My host compresses everything before sending it, so what actually reaches you is 13 KB, which is what the live measurement underneath was showing. The demonstration cards quoted file sizes too.
So my own site claimed to be heavier than the demos I built to show off, on three numbers measured on two different bases, directly under the words “measured in your browser, just now.”
Fixed: every number now reports what actually crosses the wire, and the build recalculates them so they cannot go stale again.
-
06 The prices disagreed with themselves across three documents Told you something untrue
Nine contradictions between the website, the price sheet and the proposal. Any one of them, spotted in a meeting, ends the meeting.
Nine separate contradictions between the site, the price sheet and the proposal template. Build tiers, care plans, hourly rate, deposit split, discount percentage.
Fixed: one canonical set, and the price sheet and the proposal are now generated from the same numbers.
-
07 My robots file was quietly cancelling the instruction not to index the demos Told you something untrue
Three invented Milton companies were on course to appear in Google, which is the exact thing this site accuses other people of doing.
I had blocked search engines from fetching the three demonstration pages, believing that kept them out of results. It does the opposite. A blocked crawler never reads the “do not index this” instruction inside the page, and Google will still list a blocked address using nothing but the words other pages link to it with. My homepage links to all three by company name.
That would have put three invented Milton companies into search results, on the same site where I accuse other people of doing precisely that.
Fixed: the block is gone, so the instruction can be read and obeyed. The weaker control was cancelling the stronger one.
-
08 I deleted the rule that holds the layout together, and shipped it Made it harder to use
One wrong character in a script deleted the rule that gives every section its margins. The site went out with the text running off both edges of the screen.
Inserting one rule into the stylesheet, a script wrote a control character where it meant to write back what it had matched. The pattern found the .wrap selector, swallowed it, and left nothing behind. That one rule is what gives every section on the site its 1080px width and its margins.
Without it the entire site rendered edge to edge, headlines and body text clipped at both margins, on every page and every screen size. It went live like that.
Worse than the fault: my own checks passed it. Every one of them read the words on the page, and words cannot see that a stylesheet rule has stopped existing. I had also only looked at the site on a phone and a small laptop, where a missing width limit is nearly invisible because the screen is already about that wide. On a large monitor it was obvious. Drabya spotted it. I did not.
Fixed: the rule is back and checked at five screen widths. And there is now a separate check that reads the stylesheet as structure rather than as text. It fails the build on an unbalanced brace, a stray control character, a rule with no selector, or any one of a named list of rules the page cannot render without. It would have caught this in a second.
-
09 Every link in my own menu landed you in the wrong place, on a phone Made it harder to use
Tap any item in my menu on a phone and you landed with the heading you asked for hidden behind the header.
A rule hiding the desktop phone button on small screens lost a specificity contest to a rule further down the file that makes phone links tappable. One is worth 0,1,0, the other 0,1,1. The higher number wins, so the button I thought was hidden was on every phone, and my header was 166px tall.
On top of that, nothing on the page told the browser to leave room for that header when it jumped to a section. So tapping Prices scrolled you to a spot where the heading was completely underneath the header. Every menu item did it. Every button did it.
This is on a site that says I open your website on a real phone and measure what it does. I had not tapped my own menu on a phone.
Fixed: the header is 121px now, and every section leaves room for it. The three demonstration sites had the same fault and got the same fix.
-
10 The price section pushed the whole page wider than the phone Made it harder to use
The whole site slid sideways under your thumb, worst of all on the section where you decide whether to spend money.
The badge on the middle price reads “The one I’d build for you” and was set never to wrap. That is 268px of unbreakable text sitting beside a heading, which forced the card to 372px inside a 331px column, which pushed the page to 394px on a 375px screen.
Result: the whole site slid sideways under your thumb, worst of all on the section where you decide whether to spend money.
Fixed: the badge wraps, and the page now physically cannot grow wider than the screen.
-
11 The page took 1,511 milliseconds, and 1,242 of them were somebody else’s Made it harder to use
Four fifths of my loading time was spent waiting on somebody else’s font server.
The HTML itself downloaded in 5ms. Everything else was a blocking stylesheet request to Google Fonts.
On a slow connection a visitor could have seen a load time above my own guarantee, printed in my own hero, directly under a headline criticising slow websites.
Fixed: the font declarations are written into the page instead of fetched. 1,511ms to 33ms.
-
12 Dark mode failed contrast at 2.01 Made it harder to use
White text on pale amber. Effectively unreadable for anyone whose phone is set to dark, which after sunset is most people.
The recommended-tier badge and the mobile call button used white text on an accent colour. In dark mode that accent inverts to a light tone, so the white text sat at a contrast ratio of 2.01 against it. The minimum is 4.5.
Fixed: both now sit at 8.81. Every element on the site clears the threshold in both themes; the lowest is 4.55.
-
13 Lists broke into narrow vertical columns Made it harder to use
Bullet lists rendered as cramped stacked columns on the page where the packages are explained.
The list items were laid out as a two column grid. Any item containing a bold lead-in plus ordinary text is three things in a two column grid, so the trailing text dropped to a second row and got crushed into the narrow column.
It looked like a rendering fault on several of the price bullets, which is a poor advertisement on a page selling web design.
Fixed: the bullet is positioned absolutely and the text flows normally. 27 list items checked, none broken.
-
14 A script I wrote to tidy punctuation broke a font Made it harder to use
My own clean-up script corrupted a font address, and one demonstration site quietly lost its typeface.
It collapsed repeated characters, which turned a font’s optical size range 6..72 into 6.72 and quietly broke the URL. One demonstration site fell back to system fonts.
Four checks passed cleanly before this was found. The fifth compared the file sizes printed on the portfolio cards against the actual files, and a four kilobyte gap gave it away.
-
15 Six smaller ones, in the same sweep Made it harder to use
Six at once: a counter that could show the wrong number, two stray dashes, a black browser bar above a cream page, my email styled as an error, two contrast failures, and labels down at 9px.
The animated counters on the metric tiles could read the placeholder number instead of the measured one and then spend half a second writing it back, under the words “measured just now.” Deleted. A measurement should settle on a reading, not roll up like a fruit machine.
Two em dashes were still reaching visitors from inside the code, one of them on the second visit, which is the exact visit this site is built to earn.
The colour I gave your phone for the bar at the top of the screen was near black, above a cream page, and appears nowhere in the design.
My own email address was painted in the same colours as the error box, so the only way to reach me by writing looked like something had gone wrong.
The step numbers in the dark band sat at 4.05 against a requirement of 4.5, and the “still wrong” badge on this very page sat at 2.72 for anyone whose phone is set to dark, which after sunset is most people. Both fixed.
And the labels throughout were as small as 9px, on demonstration sites, in a typeface I chose specifically because it was designed to be readable by people with poor eyesight. Nothing is below 11.5px now.
-
16 The main button in the free audit section was painted the same colour as the wall behind it Cost me work
The loudest button on the page was painted the same colour as the wall behind it. Only the lettering showed, so the second-choice button beside it looked like the only real one.
That section has a dark background. In light mode the filled button was painted in the same dark ink as the section, and given a border in that same ink. Contrast between the button and its background: 1.0. Only the lettering showed.
So the loudest thing on the page read as floating text, while the second-choice button beside it was the only one that looked like a button.
Fixed. The button is now the brightest thing in that section, which is what it was always meant to be.
-
17 The telephone icon on all three demonstration sites was not a telephone Made it harder to use
A missing space inside the drawing instructions cut 37% of the handset off. The call button on all three demonstration pages carried a broken squiggle instead of a phone.
The same find-and-replace removed a single space inside the drawing instructions for the phone icon. Those instructions come in groups of six numbers; taking out the space joined two numbers into one and left a group of five.
When a browser meets a broken instruction in a drawing, it draws everything up to that point and then stops. So 37% of the icon was missing: what you saw was an open squiggle, not a handset. It was on the call button of all three demonstration pages, at every screen size, and I invite people to open those on their phones.
Fixed, and the build now checks every drawing on every page and fails if the instructions do not add up.
-
18 One demonstration page was three times heavier than it said it was Told you something untrue
The weight figures left the typefaces out, then sat beside a comparison against other sites' full weight. One page advertised 10 KB while pulling 272 KB of font.
The weight figures counted only the bytes coming from my own server. The typefaces come from Google, so they were left out, and then the number sat next to a comparison against other Milton sites’ full weight.
One demonstration page was pulling 272 KB of typeface while its card advertised 10 KB.
Fixed. Every figure now counts every byte, measured while the page is built rather than typed in by me. And one wasteful font request turned out to be pure waste: asking for a size range I never used was costing 168 KB. Removing it took that page from 282 KB to 171 KB with no visible change at all.
-
19 Thirty-one pieces of text and five buttons were too faint to read Made it harder to use
31 contrast failures across the three demonstration sites, worst of them the call buttons at 2.1 after dark, plus links too small to press reliably.
I checked every piece of text on all five pages against the readability standard, in both light and dark. 31 failures, every one of them on the three demonstration sites.
Nearly all of them traced to a single muted grey per site, picked by eye instead of measured. The worst were the call buttons: near-white lettering on a colour that turns pale after dark, 2.1 where 4.5 is the standard. That is the button people press to ring you, unreadable to anyone whose phone switches to dark in the evening.
Some links were also too small to hit reliably: 16 px tall where the guideline is 44.
Fixed. Every piece of text and every button on all five pages now passes in both light and dark, and nothing is smaller than 44 pixels to press.
-
20 My own demonstration banner was sitting on top of the header it was demonstrating Made it harder to use
My 'not a real company' banner and the site's own header were both pinned to the top, mine in front. Scrolling made the contractor's header disappear behind my label.
Each demonstration page carries a banner saying it is not a real company. Both that banner and the site’s own header were pinned to the top of the screen, and mine was in front. So the moment you scrolled, the contractor’s header, logo, menu and call button vanished behind my label. On a phone it covered it completely.
The header is the thing those pages exist to show.
Fixed. The banner now sits at the top of the page and scrolls away, and the header behaves the way it would on a real site.
Severity is what it meant for you, not how hard it was to fix. Cost me work means an enquiry died on the way to me. Told you something untrue means the page stated a thing that was false. Made it harder to use means it worked, badly.
Found and not fixed
The 5 still wrong with it
Publishing this is the whole point of the page. Anything I hid here, you would find anyway.
-
21 There is no photograph of me
A site selling a one-man service with no picture of the one man is weaker than it should be. I have not taken one yet. The slot is built and waiting.
-
22 There are no testimonials, because there are no clients
I could write something warm and unattributed. Every website you have ever mistrusted did exactly that. This section stays empty until somebody real fills it.
-
23 The fonts still come from a third party
Five requests leave every page on this site for Google’s font servers, and they weigh 95 KB. The pages themselves are 13 to 16 KB, so the typefaces are the larger part of what this site costs you.
It said “two requests” here until I actually counted them. Self-hosting a cut-down set would remove the dependency and most of the weight. It is a few hours of work and it has not happened yet.
-
24 The page is longer than it should be
About 14 phone screens. I have criticised contractor sites for exactly this. Mine has a reason for every section, which is what everybody says about their own long page.
-
25 There is a hosting badge in the corner
The free tier injects it after the closing tag, so it cannot be edited out. Removing it means paying for hosting or moving host. I have not decided it is worth either yet, and I would rather say so than have you spot it.
The method
What I actually measure
The same list, whether it is my site or yours.
- Can it be tapped
- Every phone number and email address, on a real handset. Not a desktop browser made narrow.
- Does the form work
- A real submission, sent from a phone that is not mine, and confirmed arriving.
- How long, and why
- Time to first byte, page weight, and which single resource is responsible for the delay.
- What Google thinks your town is
- Page titles, headings, image filenames and footer links. They frequently disagree with each other.
- Where your proof is
- Reviews, awards, credentials, and whether a visitor to the homepage ever sees any of it.
- Who is above you
- What is ranking for your trade in your town, and whether those companies are real.
- Contrast and tap targets
- Measured ratios in both light and dark, and every target checked against the 44 pixel minimum.
- What breaks with nothing
- How the page behaves with scripts off, animation off, and a cold cache.
I will do this for your site, free
Send me your web address and you get the same thing: a short video and a written list, yours to keep and hand to whoever manages your site, whether we ever speak again or not.
Send me your web addressAudited 26 August 2026. Re-run whenever the site changes.