Keeps the Learning catalog from #6 and puts the Fun group after it, in the catalog and the README. Adds the end-to-end check #4 left for Fun: a custom Fun feed added on the Sources tab shows up in the Learn tab's Fun section, not in Today. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
253 lines
13 KiB
Markdown
253 lines
13 KiB
Markdown
# Tagesbyte
|
||
|
||
Your daily tech news in bytes. A Flutter app that collects the day's tech news
|
||
from German and English RSS/Atom feeds and uses AI to summarize single articles
|
||
or write a daily briefing. It's meant to replace the n8n → Discord workflow.
|
||
|
||
## Features (prototype)
|
||
|
||
- **Today**: all articles from the enabled sources in the last 12/24/48 h, newest
|
||
first. Filter by language or source, pull to refresh.
|
||
- **Learn**: articles from the enabled Learning sources (engineering blogs,
|
||
system design explainers, AI research write-ups) from the last 14 days, newest
|
||
first. Learning sources aren't part of the Briefing.
|
||
- **Reading in the app**: tapping an article opens a clean **reader view** (text,
|
||
headings, lists, quotes, images) without ads or cookie banners. The globe icon
|
||
switches to the **original page** in an in-app WebView, for paywalls or sites
|
||
that block reader view. **Summarize with AI** uses the same downloaded text, so
|
||
the summary is based on the full article, not just the RSS teaser. Links in the
|
||
briefing open the same way.
|
||
- **Briefing**: AI picks the 6–10 most important stories of the day, merges
|
||
coverage from different outlets, and links every topic to its sources. Every
|
||
briefing is saved on the device (`briefings.json` in the app's private
|
||
storage); the history button lists them by month, tap to read, swipe to delete
|
||
(with undo).
|
||
- **Paid articles and ads hidden**: heise+ and Golem `(g+)` are recognized by
|
||
their title; SPIEGEL+ and t3n Pro by a marker in the article page, which the app
|
||
checks once per new article in the background (it reads only until the marker,
|
||
and remembers results for 14 days). Sponsored posts (`Anzeige:`) are hidden too.
|
||
The feed header shows how many were hidden; both filters can be turned off.
|
||
- **Ad and cookie-banner blocking** in the original-page view: requests to ~80
|
||
ad/tracker hosts and the common consent managers (Sourcepoint, OneTrust,
|
||
consentmanager, Usercentrics, Didomi, Cookiebot, …) are blocked, and a
|
||
stylesheet hides leftover ad slots and banners. Nothing is accepted, so sites
|
||
treat it like a rejection. Golem redirects to a separate consent page instead
|
||
of showing a banner; with "Accept cookie walls" on (default), the app makes the
|
||
same request as Golem's own "Zustimmen" button (`/abo/setconsentcookie.php`,
|
||
valid for a day) and reuses the cookie for reader view and the in-app page.
|
||
With it off, the app shows the teaser and an "Open website anyway" option.
|
||
- **Sources**: 23 curated feeds (13 German, 10 English), toggle each one, or add any
|
||
RSS/Atom feed as a News, Learning or Fun source (it's validated before being
|
||
added). The tab groups Sources by kind, then by language.
|
||
- **Dark mode**: System / Light / Dark in Settings (applies instantly). The
|
||
original-page view follows it too: when the phone is dark, sites use their own
|
||
dark design or Android darkens them; when only the app is dark, the app inverts
|
||
the page colours and keeps photos and videos as they are.
|
||
- **Settings**: AI provider (off / Claude API / n8n webhook), model, summary
|
||
language (German/English, whatever the source language), time window, paid/ad
|
||
filters, ad and cookie-banner blocking.
|
||
|
||
## Running
|
||
|
||
```bash
|
||
flutter pub get
|
||
flutter run # pick an Android emulator/device
|
||
flutter test # unit tests (parser, Claude request/response handling)
|
||
LIVE_FEEDS=1 flutter test test/live_feeds_test.dart # checks every real feed
|
||
```
|
||
|
||
Platform notes:
|
||
|
||
- **Android / iOS**: work as-is (Android 6.0+).
|
||
- **Windows desktop**: requires Visual Studio with the "Desktop development with
|
||
C++" workload. Reader view works; "original page" opens the browser because
|
||
the WebView plugin has no Windows support.
|
||
- **Web**: browsers block cross-origin feed requests (CORS). Set a CORS proxy
|
||
prefix in Settings (only shown on web), or use the app on mobile/desktop.
|
||
|
||
## AI setup
|
||
|
||
### Option A: Claude API (direct)
|
||
|
||
1. Create a key at <https://console.anthropic.com/settings/keys>.
|
||
2. Settings → AI summaries → **Claude API** → paste the key → Save.
|
||
|
||
The key is stored in the platform keystore (`flutter_secure_storage`) and only
|
||
sent to `api.anthropic.com`. Model choices:
|
||
|
||
| Model | Use it for |
|
||
|---|---|
|
||
| `claude-opus-5-5` (default) | Best briefing quality |
|
||
| `claude-sonnet-5-5` | Balanced cost and quality |
|
||
| `claude-haiku-5-5` | Cheapest; good enough for single-article summaries |
|
||
|
||
Requests use low effort (summarizing is routine work) and, for the briefing,
|
||
structured JSON output so the result maps reliably to topics and links. On Opus
|
||
and Sonnet the app also enables Anthropic's server-side refusal fallback
|
||
(`fallbacks: "default"`): if a safety classifier declines a request, the API
|
||
retries it on a fallback model.
|
||
|
||
> Shipping the app to other people with your key inside isn't safe. For
|
||
> personal use a key you entered yourself is fine; for distribution, route
|
||
> requests through your own backend (e.g. the n8n option below).
|
||
|
||
### Option B: Your n8n workflow
|
||
|
||
Settings → AI summaries → **n8n webhook** → enter the production URL of a
|
||
*Webhook* trigger node (method POST, "Respond: Using 'Respond to Webhook' node").
|
||
The app sends JSON and expects JSON back.
|
||
|
||
**Daily briefing**
|
||
|
||
```jsonc
|
||
// Request
|
||
{
|
||
"action": "daily_briefing",
|
||
"language": "de", // "de" | "en"
|
||
"articles": [
|
||
{
|
||
"id": "a1",
|
||
"title": "…",
|
||
"url": "https://…",
|
||
"source": "heise online",
|
||
"language": "de",
|
||
"published": "2026-10-11T07:30:00.000Z",
|
||
"excerpt": "…"
|
||
}
|
||
]
|
||
}
|
||
|
||
// Response, option 1 (structured; topics link back to the articles)
|
||
{
|
||
"intro": "One or two sentences on the day.",
|
||
"topics": [
|
||
{ "title": "…", "summary": "…", "article_ids": ["a1", "a7"] }
|
||
]
|
||
}
|
||
|
||
// Response, option 2 (plain text, e.g. your existing Discord message)
|
||
{ "text": "…" }
|
||
```
|
||
|
||
**Single article**
|
||
|
||
```jsonc
|
||
// Request
|
||
{
|
||
"action": "summarize_article",
|
||
"language": "de",
|
||
"article": { "title": "…", "url": "…", "source": "…", "published": "…", "text": "extracted article body" }
|
||
}
|
||
|
||
// Response
|
||
{ "summary": "…" } // a plain-text body also works
|
||
```
|
||
|
||
Use a *Switch* node on `{{$json.body.action}}` to route the two cases to your
|
||
existing AI nodes.
|
||
|
||
## News sources
|
||
|
||
Every feed URL below was checked to load and parse. The ★ sources are enabled by
|
||
default: a small set of high-signal News sources. The others stay in the catalog
|
||
to switch on in the Sources tab.
|
||
|
||
| | Source | Feed | Focus |
|
||
|---|---|---|---|
|
||
| 🇩🇪 ★ | heise online | `heise.de/rss/heise-atom.xml` | Broad IT news, high volume (~150/day) |
|
||
| 🇩🇪 ★ | Golem.de | `rss.golem.de/rss.php?feed=ATOM1.0` | IT news for professionals |
|
||
| 🇩🇪 ★ | The Decoder | `the-decoder.de/feed/` | AI news: models, research, industry |
|
||
| 🇩🇪 | t3n | `t3n.de/rss.xml` | Digital business, startups, AI |
|
||
| 🇩🇪 | ComputerBase | `computerbase.de/rss/news.xml` | Hardware, software, gaming |
|
||
| 🇩🇪 | SPIEGEL Netzwelt | `spiegel.de/netzwelt/index.rss` | Mainstream news magazine view |
|
||
| 🇩🇪 | ZEIT Digital | `newsfeed.zeit.de/digital/index` | Digital policy and society |
|
||
| 🇩🇪 | netzpolitik.org | `netzpolitik.org/feed/` | Digital rights, privacy |
|
||
| 🇩🇪 | heise Security | `heise.de/security/rss/news-atom.xml` | Security section of heise online (turn heise online off to use it) |
|
||
| 🇩🇪 | heise Developer | `heise.de/developer/rss/news-atom.xml` | Developer section of heise online (turn heise online off to use it) |
|
||
| 🇩🇪 | Caschys Blog | `stadt-bremerhaven.de/feed/` | Consumer tech, smartphones |
|
||
| 🇩🇪 | derStandard Web | `derstandard.at/rss/web` | Austrian daily's tech section |
|
||
| 🇩🇪 | Borns IT- und Windows-Blog | `borncity.com/blog/feed/` | Windows, patches, admin topics |
|
||
| 🇬🇧 | The Verge | `theverge.com/rss/index.xml` | Consumer tech, policy |
|
||
| 🇬🇧 ★ | Ars Technica | `feeds.arstechnica.com/arstechnica/index` | In-depth tech and science |
|
||
| 🇬🇧 | TechCrunch | `techcrunch.com/feed/` | Startups, funding |
|
||
| 🇬🇧 ★ | Hacker News | `hnrss.org/frontpage?points=150` | Front page stories with 150+ points |
|
||
| 🇬🇧 ★ | Techmeme | `techmeme.com/feed.xml` | The day's top tech stories, picked by editors |
|
||
| 🇬🇧 ★ | Lobsters | `lobste.rs/rss` | Computing links, voted by a programmer community |
|
||
| 🇬🇧 ★ | Simon Willison | `simonwillison.net/atom/entries/` | LLMs and AI tools, tried out hands-on |
|
||
| 🇬🇧 | MIT Technology Review | `technologyreview.com/feed/` | AI, biotech, climate |
|
||
| 🇬🇧 | The Register | `theregister.com/headlines.atom` | Enterprise IT |
|
||
| 🇬🇧 | BleepingComputer | `bleepingcomputer.com/feed/` | Security, malware |
|
||
|
||
Reader view works for the publishers' own articles except ZEIT Digital, which
|
||
blocks non-browser requests, so the app shows the teaser and offers the original
|
||
page. Hacker News and Lobsters link to articles all over the web, so reader view
|
||
depends on the linked site. Techmeme links to its own summary page, which only
|
||
has the teaser; the original page links on to the full story.
|
||
|
||
## Learning sources
|
||
|
||
Evergreen reading for building skills: research, engineering depth and system
|
||
design rather than product news. The Learn tab shows their posts from the last
|
||
14 days. All are English; ★ marks the ones enabled by default.
|
||
|
||
| | Source | Feed | Focus |
|
||
|---|---|---|---|
|
||
| 🇬🇧 ★ | ByteByteGo | `blog.bytebytego.com/feed` | System design explained with diagrams |
|
||
| 🇬🇧 ★ | System Design One | `newsletter.systemdesign.one/feed` | System design case studies of real systems |
|
||
| 🇬🇧 ★ | The Pragmatic Engineer (blog) | `blog.pragmaticengineer.com/rss/` | How big tech and startups build software (free posts) |
|
||
| 🇬🇧 ★ | Martin Fowler | `martinfowler.com/feed.atom` | Software architecture, refactoring, delivery |
|
||
| 🇬🇧 ★ | Julia Evans | `jvns.ca/atom.xml` | Systems, networking and Unix tools, explained plainly |
|
||
| 🇬🇧 ★ | Dan Luu | `danluu.com/atom.xml` | Long, data-driven essays on computers and engineering |
|
||
| 🇬🇧 ★ | The Cloudflare Blog | `blog.cloudflare.com/rss/` | Networking, security, incident write-ups |
|
||
| 🇬🇧 ★ | Netflix Technology Blog | `netflixtechblog.com/feed` | Distributed systems, data, streaming at scale |
|
||
| 🇬🇧 ★ | Engineering at Meta | `engineering.fb.com/feed/` | Infrastructure, AI, production engineering |
|
||
| 🇬🇧 ★ | GitHub Blog: Engineering | `github.blog/engineering/feed/` | How GitHub builds and runs GitHub |
|
||
| 🇬🇧 ★ | Latent Space | `www.latent.space/feed` | AI engineering: interviews and deep dives |
|
||
| 🇬🇧 ★ | Import AI | `importai.substack.com/feed` | Weekly AI research digest by Jack Clark |
|
||
| 🇬🇧 ★ | Interconnects | `www.interconnects.ai/feed` | Language model training and research |
|
||
| 🇬🇧 ★ | Ahead of AI | `magazine.sebastianraschka.com/feed` | LLM research explained by Sebastian Raschka |
|
||
| 🇬🇧 ★ | Lilian Weng | `lilianweng.github.io/index.xml` | Thorough surveys of machine learning topics |
|
||
| 🇬🇧 | InfoQ | `feed.infoq.com/` | Architecture and engineering talks, high volume |
|
||
|
||
Left out on purpose: The Pragmatic Engineer newsletter (mostly paid), One Useful
|
||
Thing (applied AI), vendor blogs (OpenAI, DeepMind, Hugging Face) and Chip Huyen
|
||
(inactive since January 2025). Some feeds are long (Dan Luu ~130 posts, Lilian
|
||
Weng ~50); the 14-day window keeps the list short.
|
||
|
||
## Fun sources
|
||
|
||
Tech humour for the Fun section of the Learn tab, which reaches back 3 days. Fun
|
||
articles never show up in Today or the Briefing. ★ = enabled by default.
|
||
|
||
| | Source | Feed | Focus |
|
||
|---|---|---|---|
|
||
| 🇬🇧 ★ | xkcd | `xkcd.com/atom.xml` | Webcomic of romance, sarcasm, math and language |
|
||
| 🇬🇧 ★ | The Daily WTF | `thedailywtf.com/rss` | IT horror stories, bad code and error messages |
|
||
| 🇬🇧 | r/ProgrammerHumor | `reddit.com/r/ProgrammerHumor/top/.rss?t=day` | The day's top programming memes on Reddit |
|
||
|
||
Reader view shows comics and memes whole instead of as a cropped banner: xkcd
|
||
with its title text underneath, The Daily WTF's Error'd with its screenshots.
|
||
Reddit blocks reader view, so a meme shows the picture from the feed.
|
||
|
||
## Project layout
|
||
|
||
```
|
||
lib/
|
||
main.dart App entry, theme
|
||
data/default_sources.dart Curated feed list
|
||
models/ Article, NewsSource, DailyBriefing, AppSettings
|
||
services/
|
||
feed_parser.dart RSS 2.0 / RSS 1.0 / Atom parser, date parsing
|
||
feed_service.dart Parallel fetching, dedupe, time window
|
||
article_extractor.dart Article page → reader blocks + text for the AI
|
||
summarizer.dart Summarizer interface and shared prompt input
|
||
claude_summarizer.dart Claude Messages API over HTTP
|
||
n8n_summarizer.dart n8n webhook bridge
|
||
storage.dart Settings, sources, briefing persistence
|
||
paywall_service.dart Paid/sponsored detection (titles + page marker)
|
||
content_blocking.dart Ad/tracker/consent blocklists for the WebView
|
||
consent_service.dart Accepts consent walls (Golem) and keeps the cookies
|
||
state/app_state.dart ChangeNotifier holding app state
|
||
ui/ Screens (Today, Article, Briefing, Sources, Settings)
|
||
```
|