A self-hosted RSS reader for the open web — follow any site, even ones without a feed.
Hyprfeed is a self-hosted, multi-user RSS reader that turns the sites you follow into an elegant magazine. Paste any website URL — Hyprfeed discovers its feed, and if the site doesn't publish one, it can watch the page itself and turn new articles into stories.
- Three view modes — magazine (lead story + mixed grid), cards, and a compact list; switch from the topbar, per-user preference remembered
- Feed auto-discovery — paste
example.comand Hyprfeed finds the RSS or Atom feed for you - Page watcher — follow sites with no feed at all: Hyprfeed detects new article links on the page and enriches each story with the article's own title, image, description, and publish date
- Built-in reader — clean, sanitized article view with reading-time
estimate and
j/kkeyboard navigation - Multi-user — private subscriptions, read state, and saved stories per account; email-based sign-in
- Admin panel — the first registered account becomes admin: manage users, reset passwords, promote admins, and open/close registration at runtime
- Cloudflare Turnstile — optional bot protection on sign-in and sign-up
- Light & dark themes — follows your system or your choice, instant toggle
- Self-contained — Inter typeface embedded, no CDNs, no external services required, SQLite storage in a single Docker volume
-
Create a directory with this
docker-compose.yml(or download it:curl -O https://raw.githubusercontent.com/hyprlab/hyprfeed/main/docker-compose.yml):services: hyprfeed: image: hyprlab/hyprfeed:latest container_name: hyprfeed ports: # host:container — change the left side if 8098 is taken on your host - "8098:8000" environment: # Session signing key. If unset, one is generated and kept in the data volume. - SECRET_KEY=${SECRET_KEY:-} # Cloudflare Turnstile (optional — leave empty to disable the challenge) - TURNSTILE_SITE_KEY=${TURNSTILE_SITE_KEY:-} - TURNSTILE_SECRET_KEY=${TURNSTILE_SECRET_KEY:-} # Set to 0 to close sign-ups (the admin panel can also toggle this at runtime) - ALLOW_REGISTRATION=${ALLOW_REGISTRATION:-1} # How often feeds refresh in the background, in minutes - REFRESH_MINUTES=${REFRESH_MINUTES:-15} # How many stories each feed keeps; older ones are pruned - MAX_ENTRIES_PER_FEED=${MAX_ENTRIES_PER_FEED:-300} volumes: - hyprfeed-data:/data restart: unless-stopped volumes: hyprfeed-data:
-
(Optional) add a
.envfile next to it to set any of the variables above (.env.example) — everything works with the defaults for a first run. -
Start it:
docker compose up -d
-
Open http://localhost:8098 and create your account — the first account registered becomes the admin, so register yourself before opening the instance to others (or set
ALLOW_REGISTRATION=0after you're in, or flip the toggle in Settings → Admin).
Note: the downloaded compose file pulls the published image
hyprlab/hyprfeed. If yougit clonethe repository instead, the includeddocker-compose.override.ymlmakesdocker compose up -d --buildbuild the image from your local source automatically.
docker compose pull && docker compose up -dSchema migrations run automatically on startup. Your data lives in the
hyprfeed-data volume and survives updates.
Everything (database, generated secret key) is in the /data volume:
docker run --rm -v hyprfeed_hyprfeed-data:/data -v "$PWD":/backup alpine \
tar czf /backup/hyprfeed-backup.tgz -C /data .Most day-to-day settings (registration, refresh cadence, story retention) are managed in the app under Settings → Admin — the setup wizard seeds them on first run. Environment variables provide secrets and fresh-install defaults.
Example .env (same as .env.example):
# Session signing key. If unset, one is generated and stored in the data volume.
SECRET_KEY=
# Cloudflare Turnstile — leave both empty to run without the challenge.
TURNSTILE_SITE_KEY=
TURNSTILE_SECRET_KEY=
# ——— Fresh-install defaults (admins manage these at runtime afterwards) ———
ALLOW_REGISTRATION=1 # allow new sign-ups (0 to close)
REFRESH_MINUTES=15 # background refresh interval (0 pauses)
MAX_ENTRIES_PER_FEED=300 # stories kept per feed; older ones are pruned| Variable | Default | Purpose |
|---|---|---|
SECRET_KEY |
auto-generated in /data |
Session signing key — set one explicitly if you run replicas |
TURNSTILE_SITE_KEY / TURNSTILE_SECRET_KEY |
empty (disabled) | Cloudflare Turnstile bot protection |
ALLOW_REGISTRATION |
1 |
Fresh-install default; Settings → Admin toggle overrides at runtime |
REFRESH_MINUTES |
15 |
Fresh-install default; Settings → Admin overrides at runtime (0 pauses) |
MAX_ENTRIES_PER_FEED |
300 |
Fresh-install default; Settings → Admin overrides at runtime |
DATA_DIR |
/data |
Where SQLite and the secret key live |
- Create a widget in the Cloudflare dashboard for the domain you serve Hyprfeed on.
- Add both keys to
.env:TURNSTILE_SITE_KEY=0x... TURNSTILE_SECRET_KEY=0x... docker compose up -d
With the keys unset the challenge is skipped entirely — convenient for LAN-only or development use.
When you add a site and no RSS/Atom feed can be discovered, Hyprfeed offers "Follow without a feed." It then:
- scans the page for article-looking links (same site, wordy slugs, headline-length link text; navigation, tag, and author pages are filtered out),
- fetches each new article once (at most 8 per refresh cycle) and reads its Open Graph metadata for the title, lead image, description, and publish date,
- serves those stories like any other feed — unread counts, saving, and the reader all work the same.
Watched feeds are labeled with a "watcher" chip in Settings → Feeds. The reader shows the article's summary with a link out to the site, out of respect for publishers.
git clone https://github.com/hyprlab/hyprfeed.git && cd hyprfeed
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python run.py # http://localhost:8000Or build the container yourself: docker compose up -d --build.
Flask · SQLAlchemy · Flask-Login · feedparser · SQLite · gunicorn. No frontend framework and no CDN dependencies — the Inter variable font (SIL Open Font License) is bundled in the image.
Hyprfeed is built by a human maintainer working with generative AI as a development tool:
- Code — the large majority of the Python, JavaScript, and CSS in this repository was written with Anthropic's Claude (via Claude Code), working from the maintainer's direction. The maintainer decides what gets built, reviews the results, tests every release, and signs off on everything that ships.
- Text — documentation, release notes, and in-app copy are largely AI-drafted and human-edited.
- Artwork — the flat bolt logo and the app's visual design were created with the same AI assistance; the dimensional app icon artwork was provided by the maintainer.
- The app itself contains no AI. Hyprfeed has no AI features, makes no requests to AI services, and never sends your reading data anywhere — it talks only to the feeds and sites you choose to follow. AI was used to build the app, not to run it.
Bug reports and pull requests are welcome from humans and their AI tools alike; everything merged gets the same human review.
Hyprfeed is free software, released under the GNU Affero General Public License v3.0 (AGPL-3.0). You may run, study, share, and modify it. If you run a modified version as a network service, the AGPL requires you to offer its source code to your users — the "Source" link in the app's settings makes that easy to satisfy.
© 2026 Hyprlab
