I love the swipe left on my phone's home screen. Coffee in one hand, thumb swipes left, and I see what is going on in the world. It is one of the few phone habits I actually like.

What I don't like is what I see there. So I built my own feed, called it Samizdat, and put it exactly where Google Discover used to be.

In this post, I'll walk you through:

  • why Google Discover and Samsung News drove me crazy
  • the small hack to get my own widget on the left page of a Samsung phone
  • the Cloudflare setup behind it, and the one query that blew my free plan

The problem

I have a Samsung Galaxy S24 Ultra. On One UI the page left of your home screen can show exactly three things: Google Discover, Samsung Free (now Samsung News), or nothing. That's it.

I tried both. Both are bad in the same ways:

  • Paywalls everywhere. Every third story is a site I don't pay for. I tap, I get a "subscribe to continue" box. Why show it to me then?
  • Junk. Celebrity gossip, sports I don't follow, "you won't believe what this actor did". I never clicked on any of it and it keeps coming.
  • The same story five times. One press release, five sites, five cards.
  • No control. You can tap "not interested" all day long. A week later it is back. There's no place to say "no sports, nothing older than two days, I like long articles more than breaking news".

I read Czech news, tech and dev stuff, and a bunch of hobby niches: RTS games, space, Linux on Apple Silicon, Home Assistant, Blender, electronics. Discover kind of knows that, but it mixes it with whatever pays the bills.

So the idea was simple. I pick the sources, RSS like in the old days. An LLM reads every new article, throws out the junk and paywalls, merges duplicates and writes a short summary. My phone shows the top 30.

The left page hack

The first question was where to show it. I didn't want another app I have to open. The whole point is the swipe.

You can't put your own app on that left page on stock One UI. Custom launchers like Lawnchair, Neo Launcher or Nova with HomeFeeder can host a real feed page, but I didn't want to leave Samsung's launcher just for this.

The trick is a widget:

  1. Turn off the Discover page (long press the home screen, swipe left, switch it off).
  2. Add a new home screen page on the left of your main one.
  3. Put a widget on it and stretch it to full size.
  4. Keep your normal page set as home.

Now when I unlock the phone I land on my usual home screen, swipe left, and there is my feed. Same gesture, my content. You can't really tell it is not a "real" feed page.

The widget is built with Jetpack Glance, the Compose-style API for Android widgets. Every row is a small thumbnail, headline, source, age and "+3 sources" when a story got merged. The top story gets a bigger hero card. Tap opens the app on the AI summary first, then the clean full text, or the original if I really want it. Thumbs up, thumbs down, mute source, mute topic, read later.

Glance has its limits (you can't just load an image URL, you have to download it and turn it into a bitmap yourself), but for a list of 30 items it is fine.

The infrastructure

I wanted this to cost almost nothing and to need zero babysitting. Everything runs on Cloudflare:

  • Workers with Hono. One Worker serves the API (/api/*) and the settings web app as static assets. No separate Pages project.
  • Cron Triggers. At :00 and :30 it fetches about 70 feeds (with ETag and Last-Modified, so most fetches are cheap). At :15 and :45 it rebuilds the ranked feed. Once a night it cleans up anything older than 14 days.
  • Queues. Every new article goes to a queue and gets scored in batches of 10.
  • The scoring itself is one Claude Haiku call per article. It returns strict JSON: relevance against my rules, paywall verdict, topics, and a 2 to 3 sentence summary in the article's own language. Czech stays Czech. If Haiku is not available it falls back to Mistral Small on Workers AI and switches back on its own. (Fun fact: the fallback was the first thing that ran in production, because I forgot to top up my Anthropic credit.)
  • Workers AI + Vectorize. Every article gets a bge-m3 embedding (it is multilingual, which matters with Czech). That is how the same story from five sites becomes one item, and how "more like the stuff I thumbed up" works.
  • D1 for sources, articles, scores and my signals.
  • Cloudflare Access in front of everything. I log in with a one-time PIN to my email, the Android app uses a service token.

Ranking is nothing fancy: LLM score × freshness decay × my signals × source weight × similarity to what I liked. Rules are plain sentences like "no celebrity gossip" or "prefer in-depth over breaking", and they go straight into the prompt.

The settings app is a small Preact SPA where I manage feeds, import OPML, switch on curated packs (Czech news, Czech tech, AI, games, space, Linux, home automation and so on) and write the rules.

The query that ate my free plan

One lesson I want to share, because it can happen to you too.

To check if a feed item is new, I had this:

SELECT id FROM articles WHERE user_id = ? AND (url = ? OR (source_id = ? AND guid = ?)) 

Looks innocent. But an OR across different columns can't use an index in SQLite, so every check scanned the whole table. And D1 bills every scanned row as a row read. Run that for every item in every feed every few minutes and you get 8.9 million rows read in a day. The free plan has 5 million, per account. So it also took down my other app on the same account until midnight UTC.

The fix was an indexed lookup on the URL and skipping items older than the last fetch before touching the database at all. Two tips:

  • Run EXPLAIN QUERY PLAN on your hot queries. SCAN is bad, SEARCH ... USING INDEX is what you want.
  • wrangler d1 insights shows which query eats your reads.

I also added a daily budget in code. Every D1 result has meta.rows_read, so the Worker sums it and stops background jobs when it gets too high. And I moved to Workers Paid for $5 a month, which is a fair price for not thinking about it again.

How it was built

Honestly, most of the code was written by Claude Code. I did a brainstorm and a technical interview with it one evening, wrote down the decisions, and let it build the whole thing the next day: the Worker, the feed packs, the settings app, the Android app and the GitHub Actions pipeline that builds the APK (and now uploads to Google Play internal testing). My job was making decisions, unblocking things and reviewing.

From idea to a widget on my phone took about a day. A few years ago this would be a month of weekends, and I would give up somewhere around the Android widget part.

Wrap up

The real test is simple: do I stop opening Google Discover? Ask me in a month.

If you have a Samsung and you hate the left page too, the widget trick works with any feed reader widget, you don't need to build your own. But if you like building things, an LLM sitting between you and RSS is a really nice filter.

How do you read news on your phone? Drop a comment, I'm curious.