Dev.to AI 🤖 Ai 👁 0 📖 4 min read

I Built My Own RSS Reader in an Afternoon, With AI Doing the Typing

For years my RSS setup was a compromise. I never wanted to pay for a desktop reader, so I stayed on The Old Reader: a perfectly fine service, but it felt like visiting a website, because that's what it was. What I actual

I Built My Own RSS Reader in an Afternoon, With AI Doing the Typing

For years my RSS setup was a compromise. I never wanted to pay for a desktop reader, so I stayed on The Old Reader: a perfectly fine service, but it felt like visiting a website, because that's what it was. What I actually wanted was simple: a native Mac app, feeds stored locally, no account, no subscription, and fast enough to triage a hundred articles from the keyboard.

So I stopped wishing and built it. LumenAI is a local-first RSS reader for macOS with AI summaries, taken from an empty folder to a notarizable DMG in about an hour of wall-clock time, with me as product owner and build verifier while the AI wrote the code.

LumenAI main window, three-pane layout in dark mode

Ask me questions first

My pitch to the AI was one paragraph: a local RSS reader for Mac, a premium feel, and treat it like a real engineering project, with clear phases, and ask me questions before making decisions. That last sentence mattered most.

Instead of a wall of code, it interviewed me: stack, what v1 includes, what it excludes, how refresh works, what "premium" means concretely. A few rounds of multiple-choice later we had a spec.

  • v1 goals: subscribe, full article extraction, fast local search, OPML import/export, saved views, dedup, offline reading, AI summaries, keyboard-first navigation, themes, typography controls, reading progress.
  • v1 non-goals: semantic search, topic clustering, multi-device sync, social anything.

Writing down the non-goals felt ceremonial. It wasn't: every time scope tried to creep, that list ended the discussion in one line.

The stack

Every choice optimised for native feel, local data, no servers.

  • Swift + SwiftUI on macOS 14.
  • SQLite via GRDB.swift, chosen over SwiftData for FTS5, so search across every article ever downloaded is instant and offline.
  • FeedKit behind a normaliser layer, so RSS, Atom and JSON Feed land in one model.
  • Readability.js (Firefox's reader-mode engine) in a hidden WKWebView with page JavaScript disabled, for full-text extraction.
  • XcodeGen from YAML, so the AI and Xcode never fought over a .xcodeproj.

The part I'm proudest of is the AI layer: one SummaryProvider protocol with six implementations (Apple Intelligence on-device, Ollama, Claude, OpenAI, Gemini, and Disabled). Swapping providers is a dropdown; keys live in the macOS Keychain.

LumenAI architecture

Eight phases, numbered from zero

  • 0, Scaffold. Three-pane shell on sample data. The first build died on Swift's "unable to type-check this expression in reasonable time"; the too-clever closure became a boring for loop.
  • 1, Data layer. Schema, an FTS5 index kept in sync by triggers, and three-tier dedup identity (guid, else normalised URL with tracking params stripped, else content hash). Ten unit tests before any networking existed.
  • 2, Feed engine. Conditional GET so unchanged feeds cost a 304, feed auto-discovery from <link> tags, one canonical model for every feed format.
  • 3, Core UI. Folders, favicons, unread badges, and j/k/space/s/m keyboard navigation.
  • 4, Reading. Full-text fetch on select, typography controls, reading progress. Best bug of the project: saving scroll position regenerated the reader HTML, which reloaded the page, which reset the scroll. The AI caught that loop in review before I ever built it.
  • 5, Search, saved views, OPML. My subscriptions finally walked out of The Old Reader with folders intact.
  • 6, AI summaries. A deliberately boring prompt: two or three specific sentences, no "this article discusses". It's for triage, not for replacing reading.
  • 7, Polish. Programmatic app icon, dock badge, list render caching, and a one-command signed DMG script.

What the loop felt like

Every phase went the same way: the AI proposed decisions and asked questions, wrote the code and tests, then stopped, because its sandbox is Linux and can't build a Mac app. So I was the build machine: ⌘U, ⌘R, report back.

That constraint turned into a feature. It forced a human checkpoint between phases instead of a firehose of unverified code. Of three failures in the whole project, my builds caught two and the AI caught one re-reading its own code. Final tally: 38 Swift files, 27 tests, zero runtime crashes encountered.

If you're tempted

Treat it like an engineering project, not a magic trick. Phases, a non-goals list, tests, and a check-in after every phase are why this took an hour instead of unravelling over a weekend. The AI typed every line; the spec, the taste and the "no, simpler" calls were the human part, and the project needed both.

That's the whole idea behind what I write on Curious Bit: you learn a stack by shipping something real in it, not by watching a syllabus. If you'd rather learn infrastructure-side AI the same way, I've also put together AICademy, built around doing the job rather than reading about it.

Full write-up with the screenshot gallery: I Built My Own RSS Reader in an Afternoon

Originally published on Curious Bit.

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.