Guardian
Angles

A look at how this was built — and a running log of everything that's changed along the way.

headlines indexed

The idea

Earlier this year someone sent me a thread by Ted Alcorn, a US journalist who'd built a tool called Below the Fold. It lets you rummage through 25 years of New York Times coverage — reporters, topics, sections, headlines — and watch different strands of the paper's journalism rise and fall over time. It's the kind of tool that sharpens what you instinctively feel about a publication into something you can actually look at, and it spread fairly quickly.

I've been playing with more expansive vibe coding recently and wanted specifically to play with the Guardian's API, so decided to scratch that itch by putting a spin on Ted's fantastic work. The version of this I had in my head was a bit different — no bylines, more weight given to tags and sections, probably a bit slower-paced. Guardian Angles is the result.

How it's made

A note that probably matters: I'm not a programmer. I haven't written a Python script from scratch, I find the command line weirdly intimidating and although I can now just about explain what a gzipped JSON shard is, I couldn't have a month ago.

Everything here was built through the Claude Code desktop app with me describing what I wanted and letting Claude do the rest. Conversations that went roughly: "could we show what the Guardian was publishing about this exact week, in every other year?" or "the month pill at the top of the chart is getting clipped on desktop — can we look at that?"

How it was built, more technically

An hourly GitHub Action fetches headlines from the Guardian's Open Platform API into compact gzipped JSON shards, one per month. A second step aggregates those into search-ready indexes at monthly, weekly and daily granularity, plus a 3,000-entry tag catalogue. The frontend is a set of vanilla JS modules — no framework, no database, no server — with canvas-rendered charts, the occasional Pretext typography effect, and the Guardian's colour palette throughout. The whole thing is a few megabytes of static files served from GitHub Pages.

It's open source. Everything that isn't an API key is in the repo.

How it developed

A rough chronological log of what went in when. The newest changes are at the top.

  1. The company chart learns to filter

    Once "the company it keeps" could draw a topic's companions year by year, the old "Travels with" sidebar next to it was saying the same thing, only flatter — the same tags, minus the time. So the chart has taken over its job, and the sidebar's gone. The chart is now the thing you act on: click a companion's name and the whole page filters to where the two overlap — every Farage headline also tagged Ukip, say. Click a single cell and it narrows to one year, which is the bit I find genuinely useful: on a Kanye West dive, antisemitism suddenly darkens in 2022, and now you can click straight into that one square and read just those. The cell trick is desktop-only — the squares are too small to poke accurately on a phone, so there the companion name is the way in. While I was rewiring it I let tone dives have the chart too (they didn't before): it turns out a decade of "Interview"-tagged pieces is, overwhelmingly, music. With the chart doing all this, "In these headlines" — the common-words list — inherited the freed column and now runs to twenty words on a wide screen. The old behaviour the name had, linking out to that companion's own deep dive, I dropped without much agonising: you can always start a fresh dive on anything, but filtering the search you're already in is a different, sharper move, and it's the one I kept reaching for.

  2. The company a word keeps

    "The company it keeps" — the heatmap on Deep dive that shows which tags travel alongside your topic, year by year — only worked when your topic was itself a tag. That's because it read a pre-built co-occurrence index, and words don't have one. But a word dive already does the hard part: it streams every headline containing your word into memory, each carrying its own tags and date. So the companions are right there. Now, when you dive on a word, the chart tallies the tags of those matching headlines and draws the same heatmap. Dive on "furlough" and you get the UK job furlough scheme, Rishi Sunak, economic policy, unemployment, HMRC and the TUC arranged across 2020–24; dive on "partygate" and 2022 fills with Boris Johnson, the Conservatives, the Met. No new index, no extra download — it's the data the page had already fetched, put to a second use. (Tone dives stay out of it for now; their "company" is a fuzzier thing.)

  3. Share any chart

    The Trends chart's export grew up and spread out. Every chart on the site now carries a small trio of icons — copy the image, download it, or copy a link to the exact view — so any of them can go straight into a colleague's email, a document or a blog. The copy-image one is the quiet workhorse: it writes a branded PNG to your clipboard, ready to paste. The image was restyled to match the masthead — paper, the navy Guardian Angles wordmark in the proper headline face, the navy-and-yellow rule — and, less visibly but more importantly, the export now waits for the fonts to load before it draws, which it never used to, so the lettering is finally right rather than quietly falling back to Georgia. Under the bonnet it's one shared component doing the work on all four chart views, so they can't drift apart.

  4. A different nine every time

    The Style page used to open with the same nine habit cards every visit. Now it deals nine at random from the whole ledger each time you land — so the page feels alive, and you keep meeting headline tics you'd not have gone looking for. There's a "Shuffle" if you want another nine on the spot. Every one of the eighty-odd habits now has its own hand-written caption — so whatever the deal turns up reads like a chosen example rather than a dictionary entry. "Money" isn't "contains a pound sign" but "money makes the world go round, and a fair few business and politics headlines besides"; the style-guide words quote the guide ribbing itself. The handful that cite a number ("up seventeenfold") count it live, so they never drift. While I was in there I moved the full ledger up above the first-name league, where it sits more naturally as the page's reference shelf.

  5. The words we're meant to avoid

    The Guardian's style guide keeps a wry, much-loved list of words it would rather we didn't reach for in headlines — iconic, massive, major, very, "ramp up", "perfect storm" — and the guide is funnier about its own failings than anyone else would dare to be ("this word is unnecessary, basically" is its actual entry for "basically"). So the Style ledger now quietly tracks a couple of dozen of them, sitting among all the other markers rather than in a naughty corner of their own. The data is, predictably and delightfully, a confession: nearly every one is rising. "Iconic" — the entry where the guide admits "our own writers rarely follow" its advice — is up more than tenfold. The important thing, and the reason this isn't a charge sheet: style is a living craft, the guide changes its own mind, and a rule worth breaking gets broken. I've tried hard to make these read as an affectionate nudge rather than a teacher with a red pen. A couple of the most-overused words (target, bid, signal) I left out entirely, because their innocent meanings would muddy the count, and an honest number matters more here than a good gotcha.

  6. The front page, rearranged

    Trends — the page this whole site started as — got the fresh-eyes treatment that every other view had this week. The honest diagnosis: the most emphatic object on the page was "I feel lucky", dressed in blue above the search boxes like the main event, while Compare — the actual point — sat further down sharing a row with Clear. And the four stacked search slots read like a form to be completed rather than an invitation. So the sidebar became a band: four inputs in a row across the top, the first carrying the example, the rest quietly offering "+ add another tag…", with Compare ending the line as the only blue thing in sight. The reading order is the instruction now, which meant the wordy prompts could go — the empty chart just says "Pick a topic above to begin." Lucky survives (of course it survives) but in quiet dotted capitals on the second row, demoted from headliner to pleasant surprise, and the Try suggestion lists are gone entirely. The prize for all this tidying: the chart now gets the full width of the page, which is where a decade of headlines always wanted to be drawn. A stowaway fix too — the year slider had been faintly haunting the empty state because of a CSS rule that out-ranked the hidden attribute. Exorcised.

  7. Deep dive loses a chart

    A removal I'd been putting off. Deep dive had two charts telling the same story — the monthly sparkline beside the stats and the weekly heatmap below it — and once the company-it-keeps grid arrived underneath, the page was showing volume-over-time three times in three styles. The weekly heatmap was the one I was fondest of and the one that had to go: the sparkline earns its place inside the stats row, and the company grid now provides the page's heatmap texture. Its genuinely useful trick survives the cut, though — click-to-filter has moved to the sparkline, so clicking a month narrows the headline list to that month, with the same yellow highlight the Trends chart uses. Months instead of weeks is a little coarser, but the filter box and year slider were always the precision tools. The page also sheds its heaviest block of DOM — 795 individually-shaded cells — which the older phones will appreciate. Fondness is not a reason to keep a chart.

  8. Style, rearranged — and the captions learn to count

    A reshuffle after using the page properly: the fun fact now opens the show (it's small and delightful, so it goes first), and the full ledger moves below the name league and shows its five biggest movers with the search box out in the open — the rest are one click away, so it can be browsed without dominating. The league learned surnames: each first name now carries its dominant companion, so 2022's Liz reads as Liz Truss, Taylor as Swift, Jane as Austen, and 2022's Elizabeth, with the archive's plainest poetry, as Elizabeth II. Names link through to their person's deep dive when one exists, and the word-markers in the ledger link to the actual headlines behind their lines. Two corrections of substance along the way. First, names are now counted only in the working part of the headline — the "| Columnist" signature is furniture, not a mention, and it had quietly handed every diffuse first name to whichever columnist signs most often. Second, the card captions now compute their own numbers from the live data instead of trusting me to keep prose up to date: my hand-written caption said quote-openings were one in 160 in 2012, and the data says one in 180. The captions will drift no more, because they can count.

  9. Counting inside the desks

    The Style page learned its best trick yet: a "Counting" control that re-counts everything within a single section or tone. The whole page — hero, cards, ledger — becomes a question you can point at a desk. Do Sport headlines swear more than Opinion? (No: nobody has ever sworn in a match report, while Opinion quietly leads.) How long is an Opinion headline? (Eighteen words, the longest on the paper.) The show-stopper is the Interview tone: seventeen words on average and a quote opening on 58% of headlines this year — an interview headline is now, more often than not, the interviewee talking. One small honesty rule: the card captions are written about all headlines, so when you're counting inside a desk they step aside rather than claim things about a slice they weren't written for. Scopes live in the URL too, so "swearing, in Opinion" is a link you can send someone.

  10. The full ledger

    The Style page's nine cards are now the front window of a much larger shop. Below them sits the full ledger: every headline habit we count — sixty-two and climbing — in one searchable list, sorted so the biggest movers come first, which turns out to make the list itself tell the story: "– video" dies, "…in pictures" dies, The Guardian view is born, twenty-word headlines rise twenty-seven-fold, the cartoon label disappears, the quote opening conquers. Click any row for its chart; every marker has a shareable address. The batch of new measurements includes the journalese drawer (set to, sparks, fears, boost and blow — political reporting's two kinds of weather), the attribution verbs (says, warns, insists, admits — "says" has more than doubled), "-gate" coinages with Southgate and Margate carefully excluded, and the new headline fact of the whole page: more than a quarter of Guardian headlines now contain quotation, up from one in thirteen in 2012. The headline used to describe the news; increasingly, it lets you hear it.

  11. Style, sharpened

    The Style page filled out within hours of launching. Two more habit cards complete a three-by-three grid: first-person headlines ("I", "my", "me" — twice as common as in 2012) and the five-word-or-fewer headline, which it turns out collapsed from one in seven to one in 31, most of it before 2015 — not concision dying so much as the headline changing jobs, since a headline that travels alone in a feed has to say what the story actually is. Below the grid, two things you can actually poke at. The first-name league ranks the first names appearing in the most headlines each year, in two tables — male and female — because one combined list buried the second story: pick 2022 and the men read Boris, John, David, Rishi while the women read Liz, Emma, Elizabeth, Taylor; the male league has had three leaders in fifteen years and the female one changes hands constantly (Margaret in 2013, the year Thatcher died; Theresa's reign; Liz's single year; Kamala's; Rachel's). Davids and Johns are eternal — John's podium place owes a little to John Lewis, the small print confesses. And "one more thing": a shuffled deck of facts computed fresh from the data each build — peak liveblog months, the wordiest month in the archive, each year's name of the year — one at a time, with a button for another. April 2020 remains the most numerical month the Guardian has ever had: 23% of headlines contained a digit, because for a while the news was counting.

  12. How the Guardian says it

    A seventh tab, and the first one that isn't about what the Guardian covered: Style measures how the headlines themselves are written, across 1.3 million of them. The headline stat is that the headline became a sentence — 9.1 words on average in 2012, 13.4 now, a climb so steady it barely wobbles for Brexit or the pandemic. But the chart I keep coming back to is the quote era: headlines that open with someone talking — the "'I was terrified': …" construction — were one in 160 in 2012 and are one in ten now, a seventeen-fold rise. I went in assuming the question mark would be the story; it turns out questions have barely moved (about one in thirteen, much as ever), which felt like the data gently correcting a prejudice. Also measured: "…as it happened" up eight-fold — with the sly footnote that closed live blogs get retitled, so that suffix rather than the word "live" is how the archive remembers live coverage; the colon, eternal at a third of all headlines; the 2020 bump in headlines containing digits, when the news became counting; and the fact that "Exclusive:" — the word the Guardian famously won't use — opens 99 headlines in 1.3 million. The whole index is five kilobytes and rebuilds in seven seconds, which for the page I suspect will get shared the most feels like good value.

  13. The company a topic keeps

    Deep dive grew a block I'd been wanting since the original sketch of this site: pick a topic, and see which other tags travelled with it on the same articles, year by year, as the company changes. Nigel Farage's grid is the demonstration piece: Ukip is a solid band from 2012 that simply stops in 2018; Reform UK runs in two stretches with a gap where his career went quiet; and 2023 belongs to two dark cells labelled Banking and I'm a Celebrity — the Coutts row and the jungle, which between them were most of what the Guardian wrote about him that year. The default ranking is "most distinctive": not which tags shared the most articles (Politics would win everything, every year, forever) but which ones were unusually over-represented with this topic — that's how the banking year surfaces. A toggle flips to raw counts for the stable view. Built on a new index that counts every pair of tags appearing on the same article, all 1.3 million headlines, fifteen years — which it turns out takes seventeen seconds and 800 kilobytes. Hover any cell for the numbers ("Banking — shared 60 of Nigel Farage's 106 articles, 2023"); every companion's name links to its own deep dive.

    Honesty requires recording that this took three goes in one day. It began life as a bump chart — companions as crossing rank lines — which produced thirty strands of spaghetti; a second pass weighted the lines by volume after I realised I couldn't explain why one of them was rising (rank hides magnitude: a top spot earned on five shared articles in a quiet year drew exactly like a four-hundred-article partnership). Better, still a tangle. The fix was admitting the lines themselves were the problem: it's now a heatmap — companions down the side in order of first appearance, years across, shade carrying the weight — which happens to match the weekly-volume grid further up the page, so Deep dive now speaks one visual language. Labels can't collide, phones get the same chart smaller, and nothing crosses anything.

  14. Every view is now a link

    Trends, Deep dive and This Week have always remembered themselves in the address bar — share the URL and the other person sees what you see. Topics and Newsroom didn't, and quietly reset on every visit. Now they hold their state too: the Topics table keeps your name filter, section chip, year range and sort; Newsroom keeps the absolute-or-proportional toggle, the year range, any section you've solo'd or hidden, and even an open month drilldown — send someone newsroom.html?solo=film&month=2018-06 and they land on June 2018's film desk, list of biggest tags and all. Defaults stay out of the URL, so nothing changes unless you've actually touched something.

  15. The views start talking to each other

    An odd thing about the site until today: five views, and the only route between them was the navigation bar. You could be looking at Keir Starmer's decade on the Trends chart with no way to say "now show me everything about him" short of retyping the search on another tab. Fixed with a family of small, quiet links. Every compared term on Trends now carries a "Deep dive →" under its stats; every row of the Topics table gets one on its slug line; the story of the week's hero card has one; and when you click a chart peak and the dispatches open, a link takes the same topic into Deep dive scoped to that year. Nothing new to learn — just dotted-underline escape hatches where your eye already is, each carrying your year range along with it.

  16. The repo goes on a diet

    A few months ago I learned what a gzipped JSON shard is; this week I learned what happens if you commit nine megabytes of them to git every hour for months. Each hourly build had been committing not just any new headlines but the entire set of search indexes rebuilt from them — files you can regenerate at any moment from what's already there — and git, which never forgets anything, had quietly grown the repository to 4.7 gigabytes, close to the point where GitHub starts sending concerned emails. Two changes. The indexes are now built fresh on every run and shipped straight to the site without ever touching the repository's history. And the current month's data — the one file that genuinely changes every hour — travels the same way, only joining the permanent archive once the month closes. We also caught a quiet accomplice: every refetch stamped a new timestamp into files whose actual content hadn't changed, so even nothing-happened runs looked like changes worth recording. The timestamps are gone, identical content now produces identical bytes, and history should grow by about a megabyte a month rather than ten an hour. The site looks exactly the same and updates exactly as often.

    Postscript, later the same day: with the bleeding stopped, we went after the existing 4.7 gigabytes too. Nobody but me had ever really cloned the repository, so there was nothing to break. A tool called git-filter-repo stripped the data files out of every old commit — at which point the 473 hourly bot commits, now changing nothing, simply ceased to exist — and the headline archive was re-landed on top as a single commit. The 115 commits of actual development survive untouched, the files at the end are verified byte-for-byte identical to what was there before, and the repository is 128 megabytes. The code history, it turns out, was 700 kilobytes of the 4.7 gigabytes all along.

  17. Chasing the mobile snap

    For a few days Trends on Chrome mobile had been crashing the tab on me when I compared words rather than tags — a long pause after hitting Compare, the page reloading with blank fields, then an immediate snap. Tag comparisons were fine. Took a couple of passes to find the actual culprit. Tags always hit a pre-built index so they're a direct array lookup. Words fall back to scanning every monthly shard if the term isn't in the top 5,000 — and our scan was loading all 163 monthly shards simultaneously, around 500MB of parsed JSON on a phone with roughly 400MB of tab memory. The rising-tags panel in the reading pane was also eagerly loading an 80MB daily tag index just to pick out the biggest tag from the last full day, which didn't help. Fixed both: the scan now loads four shards at a time and drops each from memory the moment it's finished counting matches; the trending-tag insert now reads from the weekly index that's already loaded for rising-tags, which costs nothing extra. And since the "Searching…" message used to live only on the reading panel — which on mobile is off-screen below the chart — it's now also shown where you're actually looking, as a small pulsing Guardian-blue dot in the chart's empty-state line.

  18. Deep dive, deeper

    The middle of the Deep dive page looked a bit hollow once the four summary stats landed, so I added four more blocks that fill the space with something the stats can't show you on their own. A weekly heatmap — one cell per ISO week, shaded by volume — that surfaces cluster shapes the monthly sparkline only hints at. First / Peak / Most recent dispatch cards showing the actual articles at those points, rather than just the dates. A peak-month drilldown that expands inline when you click the peak stat, listing up to twelve headlines from that month. And a sidebar block surfacing the content words that keep appearing in matched headlines, which turns out to be a nice read on framing — "emergency" and "warming" rising to the top on the climate crisis, "pledge" and "leader" on Keir Starmer. The yellow-bar highlight from Trends carries through too. Later: the sidebar blocks and the section-mix bars all became clickable filters. Click "Labour" in Travels-with or any of the section rows and the headline list narrows to that facet; click again to clear. A blue-ruled chip sits above the list to make the active filter obvious.

  19. Every tag gets its real name

    A reader spotted that the site was showing "Brexit Party" for a tag the Guardian has since renamed to "Reform UK". Tag slugs are immutable in the Guardian's CMS but the webTitle on a tag can change — and ours was derived from the slug, so renames were invisible to us. Wired up a small script that pulls every catalogued tag's current webTitle from the Guardian's /tags API and caches it; runs monthly on its own. Side effect: the hundred-odd smooshed-name overrides I'd been hand-maintaining are now mostly redundant, since CAPI returns "Margaret Thatcher" for a slug that's simply "politics/margaretthatcher".

  20. "Subjects" is now "Topics"

    Minor but niggling: "Subjects" is the Guardian CMS's internal word, not a reader's. Renamed the tab to "Topics", which reads more naturally for what the view actually does. While I was in the nav, I reshuffled it a bit — the three search surfaces (Trends, Topics, Deep dive) now cluster together on the left, with This Week and Newsroom as the editorial-frame tabs to the right. URL paths all stayed the same so shared links still work.

  21. Deep dive

    A fifth tab for when the question is about a single topic rather than a comparison. Pick a tag or a word, pick a date range, and you get the shape of coverage — total, peak month, first and last appearance, section mix, a volume sparkline — followed by every headline in that span streaming in newest-first, with the tags it tends to travel with in a sidebar. A filter box and a CSV export sit above the list. Compare-up-to-four is a great way in but the wrong shape when you want the whole story on one thing.

  22. The design audit

    I'd been staring at this thing long enough that I couldn't see it properly any more, so I asked Claude Design to go through the whole site and come back with things that weren't working — not functionality, but proportion, rhythm, contrast, the sins you can't see once you've built something. It returned a prioritised audit of thirteen fixes, which we then worked through with Claude Code one at a time. The masthead dek slimmed to a single sentence. The chart title split into a muted empty-state prompt and a proper serif headline, which are genuinely different jobs. Toggle controls unified on ink instead of drifting between ink and blue. Real paper grain via an SVG noise tile, replacing the dot lattice I'd been shipping that turned out to be effectively invisible on retina displays. Focus rings, ARIA labels on the chart canvases, a global respect for prefers-reduced-motion. Most usefully a proper mobile pass, which caught a horizontal-overflow bug I'd never noticed on desktop and a tap-target problem on almost every segmented control. While we were in there I noticed the About page read more like product marketing than anything I'd actually write, so rewrote it. What you're reading now is the result.

  23. guardian-angles.com

    Bought the domain, pointed the DNS at GitHub Pages, rewrote the OG image URLs on every page. The old github.io URL now redirects, so anything already shared still works.

  24. "I feel lucky", expanded

    The curated recipe list had come out quite heavily UK-weighted, which felt odd for a button partly meant to surface unexpected comparisons. Expanded to 250 word recipes and 225 tag recipes — more US politicians, more Latin American leaders, more of Asia, plus world cities, tourist wonders, rivers, cars, pop stars, actors, directors, and a couple of personal easter eggs I won't spoil here.

  25. Data ingestion, now resilient to me

    Twice on the same day the hourly backfill job fetched a batch of old 2015 shards, rebuilt the indexes, committed them, and then failed to push because I'd landed a design commit during its three-minute build window. Each failure threw away what it had fetched. Added a rebase-and-retry loop in the workflow so the data commit rebases on top of whatever else has landed and tries again. Also fixed This Week, which had been showing the previous week's "story of the week" one step behind on Mondays because the default-week logic assumed the last bucket in the index was always the partial one in progress.

  26. Extending back to 2012

    I'd been looking at the Newsroom chart and wondering what happens if we could see further back. Specifically, I remembered the Guardian went through a content-reduction moment around 2015 and I wanted it visible. Extended the backfill start date from 2016 to 2012 — covers the start of modern digital Guardian, the 2012 Olympics, Leveson, the Scottish referendum, Gamergate, and that 2015 editorial step-change. 48 extra months. The hourly CI job started chipping away.

  27. "Last updated" indicator

    A small pulsing green dot and italic "updated 17m ago" under the stat counter on every page. Tells you at a glance how fresh the data is. Hover for the exact timestamp. The relative format walks from minutes → hours → yesterday → days.

  28. Mobile polish pass

    I was worried the whole thing might not hold up on a phone, so we did a proper sweep. Eight specific fixes: chart axis labels no longer clip at the right edge; four-tag chart titles line-clamp to three lines instead of overflowing; the "Share as image" button goes full-width so the label doesn't truncate; Newsroom year labels switch to short format ('18, '20, '22) when cramped; Subjects article counts no longer lose their "k"; subnav now has a fade-out cue so you can tell there's more to scroll to; the hint copy says "hover or tap" instead of hover-only; the reading panel's CTA shrinks on narrow screens. The chart itself remains readable at 10+ years of monthly data on a phone — dense but not broken.

  29. "I feel lucky", proper randomness

    The curated recipe list had been firing too often, so I asked for it to feel more like an easter egg. Now 80% of picks are pure random from the top of the index, 20% are pre-baked combinations (including some deliberate odd-one-out comedy — "bread, butter, cheese, crumpet" / "pandemic, outbreak, epidemic, manflu"). The button itself moved to be the first thing you see in the sidebar, in the same styling family as the Compare button rather than a separate novelty card.

  30. Name fixes, accent fixes, grammar fixes

    A whole category of small embarrassments got fixed: words like "orb", "rgen", "nchez" were appearing in the random pool because the old tokenizer couldn't cross an accent boundary — rebuilt the index so "Orbán" indexes cleanly as "orban" (and a search for "orban" still finds "Orbán" in headlines). Possessives now fold together — "America" and "America's" count as one thing. UK and US section labels finally capitalise correctly. The Newsroom y-axis snaps to round values instead of the slightly awkward 5.1k / 7.6k / 10.2k steps it had before.

  31. About page + masthead polish

    This page. Cleaner favicon, OG share card redesigned to look like the real masthead rather than a dark blue block. Extra breathing room between the title and the blue/yellow rule on desktop.

  32. Every headline becomes a link

    Final API refetch across the decade captured each article's canonical URL. Clicking any headline anywhere in the site now opens the original Guardian article. Also shipped: the "I feel lucky" button redesigned to match the Compare button's editorial style; "Time machine" button replaces the random-week emoji.

  33. The full decade lands

    After a rate-limit saga lasting several days — the Guardian free tier was tighter than documented — a one-off quota bump from an engineer at the Guardian let us backfill the whole 124-month range from January 2016 to April 2026 in a single 25-minute burst.

  34. Pre-baked lucky recipes

    The "I feel lucky" button became curated. 131 word-based comparisons (from "happy, sad, joy, misery" to "bread, butter, cheese, crumpet") and 69 tag-based ones. Clicking it produces an instantly charted story rather than four random tags.

  35. PNG export

    Every Trends chart has a Share-as-image button that composites the current view into a branded PNG with the masthead, title, legend, and chart baked in — ready for Slack or social.

  36. Year-on-year overlay

    New toggle on the Trends chart: Timeline or Year-on-year. The latter overlays each year of a term's data on a shared January-to-December axis, making seasonal patterns and year-on-year shifts immediately visible. The "inflation" YoY view shows 2022 towering above every other year.

  37. This Week

    A fourth tab with an auto-generated dashboard: biggest Guardian tag this week, all-time peak, sample headline, weekly-sparkline, fastest risers and fallers, and "On this week in …" — the biggest tag in the same week of every year back to 2016. Later additions: arrow buttons to step through history; clickable year cards; a "Time machine" button that jumps to a random week.

  38. Newsroom

    A third tab: a stacked area chart of the Guardian's publishing output, broken down by section across the whole decade. Toggle sections on and off, switch to proportional view to see share-of-output, click any month to drill into tags. Reveals that Guardian output dropped from ~10k articles/month in 2016 to ~5-6k by 2024, and that World news holds a remarkably stable ~25–30% of output regardless of the news cycle.

  39. Subjects

    NYT-inspired table of every tag we index, ranked by volume, searchable and filterable. Tick up to four to launch them onto the Trends chart. Uses a dual-thumb year-range slider and section chips for filtering.

  40. Word-boundary search

    Fixed a subtle bug where the chart and the headline list disagreed. Searching "AI" used to return headlines containing "rain", "again", "Spain" in the explorer even though the chart only counted real "AI" mentions. Both now agree on word-boundary matching.

  41. Section filter, rising panel, trending

    Added a section filter so you can see "Starmer in Opinion only". The idle reading panel started showing "rising fastest" tags and words based on a 4-week vs 12-week baseline — a newsroom lens for what's spiking.

  42. Tags mode

    Words were never going to be enough. Switched the default search mode from free-text to Guardian's canonical editorial tags. Donald Trump, climate crisis, cost of living — all resolve to tag IDs that catch every article regardless of headline phrasing. 3,000 top tags indexed with autocomplete.

  43. The first shape

    Three views: masthead, search box, line chart, reading panel, headline explorer. Word search only. Monthly granularity. 2022–2024 data. Deployed to GitHub Pages. The whole thing was a single HTML file with three JS modules.

  44. The first prompt

    Before any of that, there was just a question, typed into Claude Code:

    I'm interested in building something like the tool shown in this screen capture of an X thread, but for the Guardian and using the Guardian's API and Pretext. The website is here: tedalcorn.github.io/nyt. How hard would this be, and would I be able to build it in a way that was quick to load for a user? The one thing I want to avoid is the emphasis on individual writers: I prefer tags and sections to avoid individuals being exposed for various reasons. I'm kind of picturing a Google Trends / Guardian Trends kind of idea. I don't want a perfect copy of the NYT one. I want it to feel distinct and interesting. But I love the headlines thing and being able to see individual coverage of people. All ideas welcome. Maybe we start with a solid foundation that's achievable and we can build on?

    Everything you've scrolled through above is what that question turned into.