BUILD · SITE TRUTH MONITOR
Checking that the websites still tell the truth
A restaurant group plans dozens of dated things every quarter: events, promos, holiday hours, menu changes. The websites drift away from that plan quietly. I built a monitor that compares what each site actually shows with what it should show, and hands the team one list of what to fix.
Built for Burnt Ends Hospitality Group, September 2026. Scoped 21 September, built and first run 25 September. Running on its Monday and Thursday schedule since 28 September.
- 7
- brand sites and 9 Google listings checked
- 35
- issues flagged on the first full run, 3 urgent
- 40
- rules in code, every flag with its evidence
- 0
- logins or writes to any site
The problem
The group runs six websites on three different platforms, plus a set of Google Business Profile listings. Nothing breaks loudly. An event stays listed after it happens. A promo banner outlives the promo. A developer update knocks a row of cards out of line. Google lists a shop as closed on a day the website says it's open. Nobody's job is to look at every page twice a week, so customers find these before we do.
What it checks
Five checks, each a script with tests. Reachability: every domain, sitemap and shop feed. Layout: key pages rendered in a headless browser at desktop and phone width, measuring card edges and button positions rather than diffing pixels, so it can name the exact card that's out of line. Content on the one brand whose site is built in the browser from a CMS: event dates and times across the card, the description and the booking system, and whether the event can actually be booked on the day. Event pages and booking links on the WordPress sites. And Google listings against each website's own hours text. The output is one private tracker page: issues ranked P1 (wrong for customers now), P2 (broken, or wrong soon) and P3 (polish), each with where it is and the evidence, a 'coming up in the next 14 days' list, shared statuses, a form for the team to report what they've spotted by eye, a fixed log that keeps a year of what was cleared and when, and a button to run the whole check on demand.
What the first run found
35 issues across seven brands. Three were urgent: a sports screening the next day that couldn't be booked, nine of ten event pages on one site returning a server error, and a wine shop that Google showed as closed on Mondays when it was open. The rest ranged from a font file linked to a misspelled domain, to a card saying 6pm while its description said 7pm, to a homepage telling search engines that the site lives on its CMS vendor's domain.
How it's built
The core is deterministic. Every rule is code with a test, and Claude builds, runs and summarises the checks but never eyeballs a page and decides. That keeps runs repeatable and cheap. It was built and runs entirely in Claude Code's cloud sessions, with no local install. On Monday and Thursday mornings a scheduled Routine wakes a dedicated runner session, which follows a short runbook, commits its results to a git branch and republishes the tracker. The tracker keeps the team's statuses in its own database, so they survive every run. Everything it reads is public, and it reads without logging in. Where a system needs a login, such as the booking back office, it's out of scope on purpose. My Command Center has a reader for the results branch, built and tested, parked until I want the urgent items on its Today strip.
What I got wrong first
The HTML isn't the site. One brand loads its events in the browser from a CMS API, so the first layout check saw 'no events found' and nearly raised a false alarm. The fix was to detect blocked content hosts and mark those results unverified, then read the CMS API directly, which also turned out to be better data. Data isn't what visitors see either. The checker flagged text stored in the CMS that never appears on the page. Now a wording issue only counts if it's visible on screen. Anything the checker couldn't see is marked 'unverified' and capped at the lowest severity, because a monitor that cries wolf gets ignored. And the schedule failed on its first try. A routine created from a build session starts with no repository attached, so the first scheduled run couldn't even find the code. It now fires into a runner session that has the repo, and a flag only counts as fixed when the same check has run again over the same page and stopped seeing it. One more, from the first week of real runs: a page with a bot-check widget never goes quiet on the network, so a layout check that waited for silence timed out and reported a working page as broken. It now waits for the page to load, gives the network fifteen seconds to settle, and checks the page as it is if it never does.
What it proves
That I can turn a vague, recurring worry into a defined check with an owner, a schedule and evidence on every item. And that I'd rather ship the team-facing page early and let it shape the checks, because every finding then has to be explainable in one line.
Stack