Simon Willison's Weblog — site-wide review — sample audit, scored 6.9/10

← gallery
6.9/10
Open ↗

About this audit

simonwillison.net scored 6.9/10

Fast, clean, genuinely accessible — held under 7 by one dead feature on 25 archive pages and a machine-readable layer that is entirely absent.

This is a full example audit — 13 evidence-led findings across accessibility, performance, SEO, structured data, privacy and security, each with a measurement, a screenshot and a concrete fix. The headline issue: Tag cloud is dead on all 25 year archives — stale SRI hash blocks the script, container renders 560 × 0 px.

What we found

  1. criticalTag cloud is dead on all 25 year archives — stale SRI hash blocks the script, container renders 560 × 0 px

    Every year-archive page from /2002/ to /2026/ loads d3.layout.cloud.min.js with integrity="sha512-QOn5z8Fa63hvHWmu7Sp8XEAocATKiS8KcQRuLKNGS4+vi9oWH0ajPtb8ugJYP5JDxK56lX7/R1VlBNaUU2qc6g". The file jsDelivr actually serves now hashes to sha512-j+Ejktysd4IMdBjVqxfqHaqhyQMmXvIuKeOarPz7tPU50FatDq3FOxHP4MzA5ISwBaCOWrZ0nDCMCB

  2. warningSerious axe violation: horizontally-scrolling code blocks are unreachable by keyboard on mobile

    axe-core reports 1 serious violation on the homepage and 1 on /tags/generative-ai/, both at the mobile viewport: scrollable-region-focusable — *"Scrollable region must have keyboard access"* (WCAG 2.1.1 Keyboard, 2.1.3 Keyboard (No Exception), level A). The offending element on both pages is pre:nth-child(9), the Jinja

  3. warningNo landmark elements and no skip link — 21 tab stops before the first article on the homepage

    Checked live in the DOM: /2003/ contains zero <header>, <nav>, <main>, <footer>, <aside> or role="…" elements. The homepage has exactly one <nav> and no <main>. The article template (/2026/Jul/31/stateless-mcp/) has no <main> either. There is no skip link on any page — a[href^="#"] returns an empty list at the top of e

  4. warningEvery page's H1 reads Simon Willison's Weblog — the actual subject is demoted to H2

    On all six audited pages the <h1> is identical: <h1><a href="/">Simon Willison's Weblog</a></h1>, sitting inside .smallhead-inner — the site chrome, not the content. The real subject of the page is always the first <h2>: Archive for 2003, 1,916 posts tagged "generative-ai". Verified live beyond the audited set, the sam

  5. warning0 of 6 pages have a meta description; the homepage and archives share links with no preview at all

    meta[name=description] is absent on all six audited pages and on the article page checked live. Google will synthesise a snippet from body text, so this is not fatal — but on a homepage whose first body text is a pull-quote about Gas Town burning down, the snippet is being written by chance rather than by you. The shar

  6. warningZero JSON-LD blocks and zero <time datetime> elements site-wide — nothing here is machine-readable

    script[type="application/ld+json"] returns 0 on all six audited pages, and 0 on the article page and /about/ checked live. There is no invalid schema to fix — there is simply none. The AI-readiness crawl agrees: the no-JS view of the homepage finds 0 JSON-LD blocks in the raw HTML. Dates are in the same state. document

  7. warningPerformance is at ceiling — the only headroom left is 433 KiB of oversized images on the tag index

    Lighthouse mobile scores 100 on the homepage, 100 on /2003/ and 99 on /tags/generative-ai/. Homepage LCP 1,054 ms, FCP 1,054 ms, CLS 0, TBT 4 ms, TTI 1,107 ms, server response 68 ms. /2003/ LCP 1,834 ms, CLS 0, TBT 11 ms. /tags/generative-ai/ LCP 1,867 ms, CLS 0, TBT 0 ms. There is no speed problem to fix and nothing h

  8. mobile.beat-meta clips 91 px off the right edge at 375 px — three tag links vanish with no way to reach them

    All 11 .beat-meta rows on the homepage compute to white-space: nowrap with overflow-x: hidden. At 375 px one of them — the 29th Jul entry — has 446 px of content inside a 355 px box. The overflow is not scrollable and not indicated: the tags chatgpt, ai and llms render at x-positions 376 px, 421 px and 435 px, entirely

  9. mobileYear archives on mobile: 660 links, 20 px tall, 3 px apart, down an 18,634 px page with no search

    Measured live at 375 px on /2003/: 660 entry links in #primary, each 20 px tall, at a median 26 px line pitch with a median 3 px vertical gap between consecutive items, down a page 18,634 px long. /2002/ is comparable at 681 links / 18,627 px. That is roughly 23 phone screens of undifferentiated blue link text. The arc

  10. desktopArchive pages use 560 px of a 1440 px screen — the sidebar stops after 116 px and leaves 17,356 px empty

    Measured live on /2003/ at 1440 px: #wrapper is 940 px wide, leaving 250 px of dead margin on each side. Inside it #primary is 560 px wide and 17,472 px tall, while #secondary is 280 px wide and just 116 px tall — it holds the 25-year index and then stops. Below y = 222 px there is a 280 px × 17,356 px column of nothin

  11. warningEvery page except the homepage drops site search and the primary nav — a 35 px header with 2 links

    The homepage header carries About, Subscribe, TILs, Tools, five clickable tag chips and a site-wide search field. On /2003/ and on the article template, #smallhead is 35 px tall and contains exactly two links — the site name and Subscribe. input[name=q] returns false on both. Verified live at 1440 px and 375 px. So a r

  12. warningNo SPF record on a live Google Workspace mail domain, and DMARC is monitor-only (p=none)

    simonwillison.net receives mail — MX points at aspmx4.googlemail.com, aspmx3.googlemail.com and alt1.aspmx.l.google.com. The DNS lookup returns no SPF record at all. DMARC exists but is set to monitor: v=DMARC1; p=none; pct=100; rua=mailto:postmaster@simonwillison.net;. Without SPF, no receiving server has an authorita

  13. warningNo HSTS, CSP, X-Frame-Options or Permissions-Policy on any of the 6 pages

    All six pages are served over HTTPS with no mixed content — the padlock is clean. Two good headers are already set site-wide: X-Content-Type-Options: nosniff and Referrer-Policy: strict-origin-when-cross-origin. Four are absent everywhere: HSTS, CSP, X-Frame-Options and Permissions-Policy. These are passive surface obs