Inspiration

I read the news every morning and felt worse every morning. Not because of what happened, but because of how it was written: twenty paragraphs of spin, panic, and padding around one sentence of fact. Then I found grugbrain.dev, the essay about a caveman programmer who thinks complexity is very very bad, and the Apple Design Award winning "grug" app that is nothing but big handwritten words on white paper.

The idea arrived whole: what if the news was written by grug? Same facts, same names, same numbers, same sources. Just no spin, no panic, and no articles. "openai tribe release gpt-5, say smartest thinking rock yet." That is the whole story. You either care or you do not, and either way you are done in ten breaths.

Grug News is satire of language, never of fact. That rule shaped everything.

What it does

Grug News is a daily news digest for iPhone and iPad.

  • Every morning: one small truth for the day, then the headlines, each retold in grug speak with its category mark.
  • Tap a headline for the short story, its closing line, and a link to the original article. Every story shows the publisher's real name.
  • Names, numbers and events are kept exactly as reported. Nothing is invented and nothing is exaggerated.
  • An editorial gate drops deaths, injuries and disasters before anything is rewritten. War is reported as a subject; casualty counts are not.
  • Today's news is free forever. Not a trial.
  • grug forever is a single non-consumable purchase through RevenueCat. It unlocks the archive of past days, four extra reading themes (night cave, sand cave, moss cave, berry cave), a home screen widget, and four alternate app icons.
  • No login. No ads. No tracking. Works offline: the last good day is always on the device.

How we built it

The content pipeline. A Cloudflare Worker runs twice a day. It pulls real reporting, runs an editorial filter (tragedy skip, deduplication against a D1 archive), rewrites each story into grug voice with an LLM against a strict voice spec, then validates the result: all lowercase, no articles, no subject pronouns, no em-dashes, one closing "sting" per story, a fixed dictionary (company is tribe, money is shiny rocks, AI is thinking rock, phone is glowing rectangle). Anything that fails validation is dropped. The last 30 days are rendered into one JSON file in KV, edge-cached with an ETag.

The app. Native SwiftUI, one third-party dependency. The app never sees the database: it revalidates one JSON file on launch and foreground, caches it atomically on disk, and renders. The widget reads the same cache through an App Group. Airplane mode is a supported reading room.

The design. The bar was the "grug" app's restraint: white paper, black ink, one accent, huge handwritten type (Gaegu, three weights for real hierarchy), zero system chrome. No navigation bars, no tab bars, no List styling. Every screen is one idea. The mascot, the underline, the sun that rises when you pull to refresh, are all drawn with one stroke width, as if grug had one stick and one color of ink. Paid themes are palette token swaps only; a theme that needs a new layout is scope creep.

The money. Purchases run on the RevenueCat SDK wrapping StoreKit 2, kept behind a four-method PurchaseBackend protocol so every entitlement rule is unit-tested against a fake shop. The store is authoritative on the entitlement; a local mirror is only a first-frame cache. RevenueCat receives the receipt and an anonymous identifier it generates itself: no account, no email, nothing about what is read. The sandbox purchase from TestFlight showed up in RevenueCat as ONE TIME, no expiration, customer ANONYMOUS, which is the privacy policy observed rather than claimed.

Challenges we ran into

  • Keeping the joke honest. A rewrite model wants to be funny by exaggerating. The voice validator and the prompt had to make the joke live entirely in grammar and vocabulary, never in the facts. "Satire of language, not of fact" is enforced by code, not by hope.
  • Not being a source of distressing news. The editorial gate that drops tragedy before rewriting is what let the app ship with an honest 13+ rating and a clear conscience, and it is the reason the app feels calm.
  • Designing by removing. Every screen went through rounds of taking things out. The hardest part of a design that looks like nothing is resisting the urge to add something.
  • Content Rights and App Review. Real publisher names, real links, headlines rewritten rather than reproduced, no publisher images. Getting that right the first time meant a clean review.

Accomplishments that we're proud of

  • Live on the App Store since August 19, 2026, approved on the first submission.
  • A news app a person can open, read in ten breaths, close, and go live their life.
  • Zero data collected about what anyone reads, proven at the RevenueCat dashboard level rather than promised.
  • A monetization model that respects the reader: today is free every day, and one purchase unlocks everything else forever.

What we learned

  • Restraint is a feature. Users read more when there is less.
  • A voice spec is a product spec. Writing the grammar rules down and validating against them is what makes the joke consistent day after day.
  • RevenueCat behind a tiny protocol cost nothing in complexity and made the purchase flow the least worrying part of the app.

What's next for Grug News

  • Watch what readers hide and which categories they keep, and tune the editorial mix.
  • More reading themes and icons for grug forever owners.
  • A web front page on grug-news.online rendered from the same JSON, so the day's truth is one link away for anyone.

Built With

  • cloudflare-d1
  • cloudflare-kv
  • cloudflare-workers
  • openai-api
  • revenuecat
  • storekit-2
  • swift
  • swiftui
  • typescript
  • widgetkit
Share this project:

Updates

Submission history