{"slug": "newsnest-self-hosted-news-reader-that-ranks-stories-by-my-interests", "title": "NewsNest – self-hosted news reader that ranks stories by my interests", "summary": "Developer lucifix published NewsNest, a self-hosted RSS and Atom news reader that uses Anthropic's Claude API to score each story on topic, importance and personal fit against a user-written interests file, with a default daily AI spending cap of $0.50. NewsNest groups coverage of the same event from multiple outlets into a single card, stores everything in one SQLite file, and ships as a multi-arch Docker image (linux/amd64 and linux/arm64) on GHCR and Docker Hub, running on port 3095. Without an API key the app still works, showing stories newest first, and it refuses all access unless a password is set.", "body_md": "**A self-hosted news feed that learns what you care about.**\n\nNewsNest gathers your RSS feeds into one calm stream, folds the same story from different outlets into a single card, and uses Claude to rank and summarise what matters to you.\n\n[Website](https://lucifix.github.io/newsnest/) · [Features](#features) · [Quick start](#quick-start) · [How it works](#how-it-works) · [Configuration](#configuration) · [Development](#development)\n\n| <sub>Feed, ranked for you</sub> | <sub>Swipe to sort</sub> | <sub>Dark mode, automatically</sub> | \n\n<sub>Outlets and headlines are made up. Photos from [Unsplash](https://unsplash.com) by\n[Mohammad Rahmani](https://unsplash.com/@afgprogrammer), [Gabriella Clare Marino](https://unsplash.com/@gabiontheroad)\nand [Amol Tyagi](https://unsplash.com/@amoltyagi2).</sub>\n\nChecking a dozen news sites every day is slow, and most of what you see isn't for you. Algorithmic feeds fix that by learning what keeps you scrolling, which is not the same as what you want to read.\n\nNewsNest is the opposite deal. **You choose the sources, you write down what interests you, and you can\nsee why every story ranks where it does.** It runs on your own machine, keeps everything in one SQLite\nfile, and talks to the Anthropic API with your own key.\n\n- 📰 **Your own sources.** Any RSS or Atom feed, plus GitHub release feeds for software you run. Import an\nOPML file, or try new feeds on probation: they only earn a place in your feed once you read them.\n- 🧠 **Ranked for you.** Claude scores each story on topic, importance and personal fit against an\ninterests file that you write yourself or have drafted from a few ratings.\n- 🧩 **One story, not five.** Coverage of the same event by several outlets is grouped into one card,\nand wide coverage lifts a story up.\n- ✨ **Key points on demand.** A one-line lede, a few bullets, a \"why this matters to you\" line, and a\nhint whether the full article is worth your time.\n- 👍 **It learns from you.** Likes, dislikes and opens shift what you see. Pick*more about* or*less from* for an outlet or topic, and review the weekly suggestions for your interests before they apply.\n- 🔎 **No black box.** Calibration mode shows every story with its scores and reasons, and*Missed this* lets you paste a link the feed should have shown you.\n- 🃏 **Swipe to sort.** A one-thumb deck to rate a backlog in minutes.\n- 💸 **A hard spending cap.** AI calls stop for the day when your budget is reached (default $0.50).\nWithout an API key everything still works, and stories are shown newest first.\n- 📱 **Installable and private.** A mobile-first web app with light and dark themes that installs to\nyour home screen. Password-protected, with a one-click database backup.\n- 🩺 **Knows when a feed breaks.** A status page and a`/health` endpoint report sources that fail or\ngo silent.\n\n## And more\n\n- Keyword **watches** that always surface a topic, plus mute and must-show keyword filters\n- Full-text **search** ,**saved** stories, a**read** history and a day-by-day**archive**\n- Per-source daily caps, so a firehose feed can't drown out everything else\n- Summaries in the language of your choice\n\nYou need [Docker](https://docs.docker.com/get-docker/) with Compose, and, for the AI features, an\n[Anthropic API key](https://console.anthropic.com/). Pull the published image (no clone needed, and the\none to use for a Portainer stack), or build from source.\n\nMulti-arch (`linux/amd64` + `linux/arm64`, so a Raspberry Pi or an ARM NAS works too):\n\n- GHCR: `ghcr.io/lucifix/newsnest`\n- Docker Hub: `docker.io/lucifix/newsnest`\n\nPaste this into Portainer (**Stacks → Add stack → Web editor**) or save it as `docker-compose.yml`\nanywhere. Only the password needs filling in:\n\n```\nservices:\n  newsnest:\n    image: ghcr.io/lucifix/newsnest:latest\n    container_name: newsnest\n    restart: unless-stopped\n    ports:\n      - 3095:8080\n    environment:\n      NEWSNEST_PASSWORD: change-me   # required: with no password the app refuses all access\n      ANTHROPIC_API_KEY: \"\"          # optional: enables ranking and summaries\n      TZ: UTC                        # your time zone, e.g. Europe/Ljubljana\n    volumes:\n      - newsnest-config:/config\n      - newsnest-data:/data\n\nvolumes:\n  newsnest-config:\n  newsnest-data:\n```\n\nFor the full file, with host folders you can open and edit instead of Docker volumes, use\n[`docker-compose.yml`](https://github.com/Lucifix/newsnest/blob/main/docker-compose.yml) from this repo:\n\n```\nmkdir newsnest && cd newsnest\ncurl -fsSLO https://raw.githubusercontent.com/Lucifix/newsnest/main/docker-compose.yml\ncurl -fsSL https://raw.githubusercontent.com/Lucifix/newsnest/main/.env.example -o .env\nmkdir -p config data     # so Docker doesn't create them as root\n# edit .env: set NEWSNEST_PASSWORD, and ANTHROPIC_API_KEY for AI\ndocker compose up -d\n```\n\n**Update:** `docker compose pull && docker compose up -d`. Set `NEWSNEST_IMAGE_TAG` in `.env` to pin a\nrelease such as `0.3.1`; the default is `latest`.\n\n```\ngit clone https://github.com/Lucifix/newsnest.git && cd newsnest\ncp .env.example .env     # set NEWSNEST_PASSWORD, and ANTHROPIC_API_KEY for AI\nmkdir -p config data     # so Docker doesn't create them as root\ndocker compose up -d --build\n```\n\n**Update:** `git pull && docker compose up -d --build`\n\nOpen [http://localhost:3095](http://localhost:3095), log in with your password, and tap **Set up my profile**:\n\n1. **Say where you live.** Your country and city tell Claude whose news is \"big\", and your time zone is\npicked up from the browser.\n2. **Add local news.** NewsNest offers the local pack for your country (Australia, Austria, Canada,\nCroatia, France, Germany, Italy, Slovenia, the United Kingdom and the United States so far), or add your\nown feeds under Local in**Settings → Feeds** .\n3. **Rate about 30 headlines** , and Claude drafts your interests from them.\n\nOn first start NewsNest copies a starter [`config.yaml`](https://github.com/Lucifix/newsnest/blob/main/config.example/config.yaml) into `config/`, with\ninternational news and tech feeds and no local ones. Change the feeds in **Settings → Feeds**, or edit\nthe file. It is re-read on every run, so there is nothing to restart.\n\nNote\n\nThe login is a single shared password over plain HTTP, which is fine on your home network. If you expose NewsNest to the internet, put it behind an HTTPS reverse proxy.\n\n``` php\nflowchart LR\n    A[\"RSS / Atom feeds<br/>GitHub releases\"] --> B[\"Fetch &<br/>de-duplicate\"]\n    B --> C[\"Group the same story<br/>across outlets\"]\n    C --> D[\"Claude scores<br/>topic · importance · fit\"]\n    D --> E[\"Rank<br/>score × freshness × what you like\"]\n    E --> F([\"Your feed\"])\n    F -- \"likes · opens · ratings\" --> E\n```\n\nA 60-second loop fetches the sources that are due, scores new stories in batches, and writes key points for the ones above your threshold. Scoring uses a small, cheap model with prompt caching; the rarer jobs (drafting your profile, the weekly suggestions) use a stronger one. Both are configurable.\n\n**What leaves your server:** headlines and snippets, and for key points the article text, go to the\nAnthropic API using your key. Your feed list, ratings and database stay on your machine, and NewsNest\nitself sends no telemetry.\n\nEverything lives in the `config/` folder, which is re-read on every run:\n\n| File | Purpose | \n|---|---|\n| `config.yaml` | Feeds, GitHub repos, watches, schedules, thresholds, models and the spending cap. Every option is explained in [`config.example/config.yaml`](https://github.com/Lucifix/newsnest/blob/main/config.example/config.yaml) . | \n| `interests.md` | What you care about and what to skip. Written on the Profile page, or by hand. | \n| `seed_examples.md` | About 20 example headlines marked `+` (want) or`-` (don't want). | \n\nEdits made in the Settings pages are written back to `config.yaml`, comments included.\n\nTip\n\nThe example config comes with international feeds, no region and the time zone `UTC`. Set where you\nlive in **Settings → General** (country, city, time zone), and NewsNest offers your country's local pack.\n\n**Sections.** Every feed belongs to one section, and the sections are the tabs along the bottom of the\nfeed. A new install starts with Local, World and Tech. In **Settings → Feeds → Sections** you can rename\nthem, add your own (Sports, Science, Cinema…), reorder them, and remove one (its feeds and stories move\nto a section you pick). Local and World are built in: they can be renamed but not removed, and share the\nNews tab. A section is a tab once it has a feed; at most four can be tabs, and any further section\nshows as a chip under **For you**. The list is the `sections:` key in `config.yaml`. A `config.yaml`\nfrom before sections were editable has none and keeps the old four (Tech, Local, World, Lifestyle) until\nyou change them, so nothing needs migrating and the database is untouched.\n\nNote\n\nOnce you edit sections, `config.yaml` has a `sections:` list that older NewsNest versions don't\nunderstand. To go back to an older image, restore the `config.yaml.bak` made by the last edit.\n\n## Environment variables\n\nSet these in `.env` (see [`.env.example`](https://github.com/Lucifix/newsnest/blob/main/.env.example)).\n\n| Variable | Default | Purpose | \n|---|---|---|\n| `NEWSNEST_PASSWORD` | – | **Required.** Password for the web UI. With none set, access is refused. | \n| `ANTHROPIC_API_KEY` | – | Turns on scoring, key points and the weekly suggestions. | \n| `TZ` | `UTC` | Container time zone (logs). The app itself uses `timezone` from`config.yaml` . | \n| `NEWSNEST_PORT` | `3095` | Port the web UI is published on. | \n| `NEWSNEST_CONFIG_PATH` | `/opt/newsnest/config` | Host folder for `config.yaml` and the profile files. | \n| `NEWSNEST_DATA_PATH` | `/opt/newsnest/data` | Host folder for the database. | \n| `PUID` /`PGID` | `1000` | User and group the container runs as. | \n| `NEWSNEST_LOG_LEVEL` | `INFO` | Log level. | \n| `NEWSNEST_SCHEDULER` | `on` | Set to `off` to disable background fetching (for development). | \n\n`.env.example` sets the two paths to `./config` and `./data`.\n\n## Backup and restore\n\n**Backup:** open **Settings → Install, backup & log out → Download database backup**. It gives you a\nsingle consistent `.db` file with all stories, ratings and history, and it is safe to take while the app\nis running. Copy the `config/` folder too: it holds your feeds and interests, which the download does\nnot include.\n\n**Restore:** stop the container, put the backup in your data folder as `newsnest.db`, and start it again.\nWith Docker volumes (the Option A snippet), copy it in while the container is stopped:\n`docker cp backup.db newsnest:/data/newsnest.db`.\n\n## Deploy with Portainer\n\n1. Create the host folders, owned by the container user:\n\n```\nsudo mkdir -p /opt/newsnest/config /opt/newsnest/data\nsudo chown -R 1000:1000 /opt/newsnest\n```\n\n2. **Stacks → Add stack → Repository** : use this repository's URL, reference`refs/heads/main` , compose\npath`docker-compose.yml` .\n3. Add the environment variables `NEWSNEST_PASSWORD` and`ANTHROPIC_API_KEY` .\n4. Deploy. Portainer pulls the published image from `ghcr.io` ; nothing is built on your server.\n5. Check `http://<server>:3095/health` , then open`http://<server>:3095/` .\n\nTo update, choose **Pull and redeploy** on the stack, with *Re-pull image* turned on. The config and\ndatabase live in `/opt/newsnest` and survive redeploys.\n\n## Install it as an app on your phone\n\nNewsNest is a progressive web app: it gets a home-screen icon, opens full screen, and keeps your most\nrecent pages available offline. Browsers only offer to install over **HTTPS**, so open it through an\nhttps address, for example one served by a reverse proxy, rather than `http://<server>:3095`.\n\n- **Android (Chrome):** menu →*Install app* , or**Settings → Install** inside NewsNest.\n- **iPhone (Safari):** Share →*Add to Home Screen* .\n\n```\npython3 -m venv .venv && .venv/bin/pip install -r requirements.txt pytest\n.venv/bin/python -m pytest                 # run the tests\nNEWSNEST_PASSWORD=dev NEWSNEST_SCHEDULER=off .venv/bin/python -m newsnest   # the app on :8080\n```\n\nThe first run copies `config.example/` to `./config/` (git-ignored). Two helpers are useful when\nadding or debugging sources:\n\n```\n.venv/bin/python -m newsnest.spike --source <feed-id>    # fetch one source and print parsed samples\n.venv/bin/python -m newsnest.runner --no-ai              # one fetch-and-store tick, without AI\n```\n\nThere is also a dev container with its own project name, port `3096` and the local `./config` and\n`./data` folders:\n\n```\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build\n```\n\n## Project layout\n\n```\nnewsnest/\n  web.py            FastAPI app: pages, settings, login, JSON endpoints\n  runner.py         the 60-second loop: fetch due sources, then the AI steps\n  fetchers/         RSS/Atom and GitHub-releases fetchers\n  pipeline.py       store items, de-duplicate by URL, record source health\n  grouping.py       group the same story across outlets\n  scoring.py        AI scoring and the final score\n  summaries.py      key points, fetched from the article text\n  feed.py           ranking and the home feed\n  profile*.py       interests, drafting, and the weekly suggestions\n  discovery.py      OPML import and sources on probation\n  db.py             SQLite schema and migrations\n  templates/        Jinja templates      static/  CSS, JS, fonts, icons\nconfig.example/     starter config, copied to config/ on first start\ntests/              pytest suite\n```\n\nPlanned work and known limits are tracked in [TODO.md](https://github.com/Lucifix/newsnest/blob/main/TODO.md).\n\nBug reports, ideas and pull requests are welcome. Found a bug? Settings → *About & report a bug* in the\napp opens a new issue with your version filled in. Please open an issue first for anything big. Run\n`python -m pytest` and `ruff check .` before you send a PR (CI runs the linter on every PR), and add\na test for what you change.\n\n**A local news pack for your country** is an easy first PR: add a `LocalPack` to `LOCAL_PACKS` in\n[`newsnest/packs.py`](https://github.com/Lucifix/newsnest/blob/main/newsnest/packs.py) with 8 to 10 national outlets across the spectrum, each checked\nwith `newsnest.discovery.check_feed` (https, working, posting in the last two weeks).\n\n[MIT](https://github.com/Lucifix/newsnest/blob/main/LICENSE), except the bundled fonts in [`newsnest/static/fonts/`](https://github.com/Lucifix/newsnest/blob/main/newsnest/static/fonts):\n[JetBrains Mono](https://github.com/JetBrains/JetBrainsMono) and\n[Space Grotesk](https://github.com/floriankarsten/space-grotesk) are licensed under the\n[SIL Open Font License 1.1](https://openfontlicense.org); their license files sit next to the fonts.", "url": "https://wpnews.pro/news/newsnest-self-hosted-news-reader-that-ranks-stories-by-my-interests", "canonical_source": "https://github.com/Lucifix/newsnest", "published_at": "2026-11-03 20:11:52+00:00", "updated_at": "2026-11-03 20:20:20.640347+00:00", "lang": "en", "topics": ["ai-products", "ai-tools", "large-language-models", "artificial-intelligence"], "entities": ["NewsNest", "lucifix", "Anthropic", "Claude", "Docker", "Portainer", "GitHub", "SQLite"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/newsnest-self-hosted-news-reader-that-ranks-stories-by-my-interests", "markdown": "https://wpnews.pro/news/newsnest-self-hosted-news-reader-that-ranks-stories-by-my-interests.md", "text": "https://wpnews.pro/news/newsnest-self-hosted-news-reader-that-ranks-stories-by-my-interests.txt", "jsonld": "https://wpnews.pro/news/newsnest-self-hosted-news-reader-that-ranks-stories-by-my-interests.jsonld"}}