A calm iPhone & iPad reader for Hacker News. On-device AI summaries, a hands-free audio queue, zero tracking. The whole thing runs on your phone.
Site: getspool.news Platform: iPhone & iPad, iOS 26+ Stack: SwiftUI, SwiftData, Apple Foundation Models, AVSpeechSynthesizer
- Every HN feed — Top / New / Best / Ask / Show / Jobs, plus Trending (computed locally from score snapshots) and Best-of windows for today / week / month / year.
- On-device AI summaries. Tap Summarize on any story. Apple's Foundation Models LLM produces a structured take on the article and a sentiment-aware digest of the discussion. No data leaves your phone, no API keys, no cloud fallback.
- The Spool — your audio queue. Add stories to your Spool, then
hit Play All. The on-device model reads each one's article +
comments as conversational prose. Sentence-by-sentence highlighting
follows the spoken text. Pre-rendered to a cached
.cafso playback is instant; runs throughMPNowPlayingInfoCenterso AirPods, CarPlay, and the lock screen all work. - Editable AI prompts. Every system prompt — article summary, comments summary, audio variants, Q&A — is editable in Settings. Stored on-device, versioned against the bundled default.
- Threaded comments with collapsible subtrees, ask-questions-of- the-thread, and a sentiment-aware comments summary.
- Configurable widget. Pin Top / New / Best / Ask HN / Show HN / Jobs to your home screen. Long-press to switch the feed.
- Sign in to vote / submit / reply. Cookie auth scraped from the
HN web flow; tokens live in
URLSession.shared.httpCookieStorage, never on disk, never in the codebase. - Mentions background-refresh notifications for replies to your comments. Off by default; opt-in toggle in Settings.
- Saved stories, read tracking, Spotlight indexing, share extension, Siri shortcuts.
- iPad — three-column Liquid Glass. Native
NavigationSplitView, no custom drawers. - No telemetry.
NSPrivacyTracking: falseinPrivacyInfo.xcprivacy. No analytics SDKs. No third-party scripts.
Spool.xcodeproj is generated by XcodeGen.
brew install xcodegen # one-time
git clone https://github.com/<you>/spool.git
cd spool
xcodegen generate
open Spool.xcodeprojYour team ID lives in Configs/Signing.xcconfig, not in project.yml.
After cloning:
# Edit Configs/Signing.xcconfig — set DEVELOPMENT_TEAM to your Apple Dev team ID
git update-index --skip-worktree Configs/Signing.xcconfigThe skip-worktree flag keeps your local team ID from getting picked
up as a pending change. To pull updates to the file later, reverse it
with --no-skip-worktree.
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer \
xcodebuild -project Spool.xcodeproj -scheme Spool \
-destination 'generic/platform=iOS Simulator' buildIf your xcode-select points at CommandLineTools (no xcodebuild on
PATH), the DEVELOPER_DIR prefix above force-points at Xcode.app.
The app is pure SwiftUI + Foundation. No third-party dependencies.
| Layer | Stack |
|---|---|
| UI | SwiftUI (NavigationSplitView root, iPhone collapse to NavigationStack) |
| Persistence | SwiftData (@Model for SavedStory, ReadStory, SpooledStory, FollowedUser, SeenMention, ScoreSnapshot) |
| LLM | Apple Foundation Models — LanguageModelSession. Errors classified by SummaryError.classify(_:) |
| TTS | AVSpeechSynthesizer.write(_:toBufferCallback:) for offline render; AVAudioPlayer for cached playback |
| HN data | Firebase API (Realtime DB) via HNAPI, Algolia for search / best-of |
| Auth | Cookie-based, scraping auth / hmac tokens from HN's web flow |
Spool/
SpoolApp.swift @main; ModelContainer setup, splash, deep-links
Theme.swift design tokens (Opacity, AnimationDuration, Spacing, CornerRadius, Layout) + Typography
Models/ domain types
HNItem.swift API item + HNStoryFeed
HNUser.swift profile shape
MainFeedSource.swift sidebar source enum (category / trending / bestOf / saved / spool / archive / following / mentions)
AppRouter.swift cross-view deep-link router (spool://story/<id>, spool://feed/<keyword>)
Persistence.swift @Model entities
SettingsKeys.swift centralized @AppStorage keys
Sentence.swift script splitter for the now-playing scroller
Networking/ actors wrapping HN / Algolia / TTS / LLM
HNAPI.swift Firebase reader (NSCache-backed)
HNSearchService.swift Algolia search
HNAuthService.swift cookie auth + vote/submit/reply
HNUserService.swift user profile + activity
HNMentionsService.swift replies to your comments
ArticleFetcher.swift HTML strip → plain text for summarizer
ImageFetcher.swift og:image lookup + thumbnails
DominantColor.swift per-row accent extraction
SummaryService.swift Foundation Models wrapper
SummaryPrompts.swift editable prompt resolution
SummaryPrefetcher.swift background text + audio prefetch for the Spool queue
AudioRenderer.swift offline TTS render → .caf
AudioCache.swift per-key on-disk cache with global render queue
SpoolPlayer.swift playback (AVAudioPlayer for cached, AVSpeech fallback) + MPNowPlayingInfo + RemoteCommands
PrefetchGate.swift foreground-vs-background coordination for the LLM session
MarkdownStripper.swift markdown → plain text for TTS
MentionsNotifier.swift background-refresh check
TrendingService.swift local score snapshots → velocity
SavedStoryIndexer.swift Spotlight integration
ViewModels/ @MainActor ObservableObjects
StoryListViewModel.swift / StoryDetailViewModel.swift
SummaryViewModel.swift / CommentsSummaryViewModel.swift / ThreadQuestionViewModel.swift
AlgoliaFeedViewModel.swift / TrendingFeedViewModel.swift / FollowingFeedViewModel.swift / MentionsFeedViewModel.swift
AuthViewModel.swift / UserProfileViewModel.swift
Views/ SwiftUI views
AppIntents/ Siri shortcuts
Assets.xcassets multi-appearance AppIcon (light / dark / tinted)
PrivacyInfo.xcprivacy
SpoolWidget/ home-screen widget (configurable via AppIntent)
SpoolShareExtension/ system share-sheet target
tools/
make_icon.swift Core Graphics AppIcon generator
landing/showcase/ marketing site (deployed at getspool.news)
NSPrivacyTracking: falseinPrivacyInfo.xcprivacy.- No analytics SDK. No third-party scripts. No proxy server.
- HN login is cookie-based directly to
news.ycombinator.com. Cookies live inURLSession.shared.httpCookieStorage(system keychain), never on disk, never in the codebase. - The on-device LLM is gated on Apple Intelligence being enabled in iOS Settings. If it's off, summary features show a Settings deep- link instead of failing silently.
MIT — see LICENSE.
Issues and PRs welcome at github.com/ctaloi/spool.