Open-source RSS reader with AI-powered clustering, full-text extraction, and smart digests. Self-host on any machine for free.
| 3-Pane Reader | Article View |
|---|---|
![]() |
![]() |
| Source Management | Mobile |
![]() |
![]() |
git clone https://github.com/CodesWhat/rss-wrangler.git && cd rss-wrangler
cp infra/.env.example infra/.env
# Edit infra/.env — set AUTH_JWT_SECRET and AUTH_PASSWORD at minimum
docker compose -f infra/docker-compose.yml up --build -dOpen http://localhost:3001 and log in.
What gets started
| Service | Description | Default Port |
|---|---|---|
| postgres | PostgreSQL 16 | 5433 |
| migrate | One-shot SQL migration runner (exits after success) | — |
| api | Fastify REST API | 4001 |
| worker | Feed polling, clustering, AI enrichment, digests | — |
| web | Next.js frontend | 3001 |
Local development (no Docker)
Requires Node.js >= 22 and PostgreSQL.
npm install
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/rss_wrangler
sh db/run-migrations.sh
# In separate terminals:
npm run dev:api # Fastify on :4000
npm run dev:worker # Background jobs
npm run dev:web # Next.js on :3000| Sidebar + article list + reader pane. Keyboard shortcuts (j/k/s/o/Esc). Smart feeds: All, Unread, Starred. | Deduplication via simhash + Jaccard similarity. Multiple outlets covering the same story get grouped into one cluster. | Automatic full-text fetch from article URLs. Read complete articles without leaving the app. |
| Topic classification, story summaries, and smart digests. Multi-provider: OpenAI, Anthropic, or local Ollama. | 500+ curated feeds in a browsable directory. Category-based suggestions based on your subscriptions. | Mute-with-breakout filter system. Auto-suppress noise, surface important stories that break through. |
| Bring your feeds from any reader. Export anytime. No lock-in. | Postgres FTS with tsvector/tsquery. Search across titles, sources, and article content. | Auto-generated digest of top stories when you've been away. Optional AI narrative summaries. |
| Hamburger sidebar overlay, stacked layout on small screens. PWA installable. | Row-level security with Postgres RLS. Invite members to shared workspaces. | GDPR-ready consent manager. Data export and account deletion built in. |
All features are unlocked when self-hosted. No license keys, no feature gates, no phone-home.
Docker Compose on any Linux server, NAS (Synology, QNAP, etc.), or cloud VM. Runs on ARM64 and AMD64.
Environment variables
| Variable | Required | Description |
|---|---|---|
AUTH_JWT_SECRET |
Yes | JWT signing secret (min 32 chars) |
AUTH_USERNAME |
Yes | Admin username |
AUTH_PASSWORD |
Yes | Admin password |
DATABASE_URL |
Yes | PostgreSQL connection string |
APP_BASE_URL |
No | Base URL for email links (default: http://localhost:3001) |
REQUIRE_EMAIL_VERIFICATION |
No | Require verified email before login (default: false) |
RESEND_API_KEY |
No | Resend API key for transactional emails |
WORKER_POLL_MINUTES |
No | Feed poll interval (default: 60) |
OPENAI_API_KEY |
No | OpenAI key for AI features |
ANTHROPIC_API_KEY |
No | Anthropic key for AI features |
AI_PROVIDER |
No | openai, anthropic, or ollama |
OLLAMA_BASE_URL |
No | Ollama server URL for local AI |
Reverse proxy (Caddy, nginx, Traefik)
Set NEXT_PUBLIC_API_BASE_URL to your public API URL and rebuild the web container:
# In infra/.env
NEXT_PUBLIC_API_BASE_URL=https://api.your-domain.com
APP_BASE_URL=https://your-domain.com
docker compose -f infra/docker-compose.yml up --build -dNEXT_PUBLIC_* vars are inlined at build time by Next.js, so a rebuild is required when changing them.
apps/
web/ Next.js 14 frontend (React 18, custom CSS)
api/ Fastify 5 REST API (JWT auth, Postgres RLS)
worker/ pg-boss background jobs (polling, clustering, AI, digests)
packages/
contracts/ Shared TypeScript types and Zod schemas
db/
migrations/ Sequential SQL migrations (applied on startup)
infra/
docker-compose.yml
Tech stack
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, React 18, custom CSS (Brutalist Mono design system) |
| API | Fastify 5, PostgreSQL 16, JWT auth (Better Auth) |
| Worker | pg-boss (Postgres-backed job queue) |
| AI | Multi-provider: OpenAI, Anthropic, Ollama |
| Search | Postgres FTS (tsvector/tsquery) |
| Resend (transactional) | |
| Shared | TypeScript, Zod schemas, Biome linter |
Scripts
| Command | Description |
|---|---|
npm run dev:web |
Next.js dev server |
npm run dev:api |
Fastify dev server (tsx watch) |
npm run dev:worker |
Worker dev server (tsx watch) |
npm run build |
Build all packages |
npm test |
Run tests (Vitest) |
npm run typecheck |
Type-check all packages |
npm run lint |
Lint with Biome |
| Tier | Price | Highlights |
|---|---|---|
| Free | $0 | 50 feeds, 500 items/day, 30d retention, 60min refresh |
| Pro | $7/mo ($70/yr) | Unlimited feeds, 1yr retention, 10min refresh, full-text search |
| Pro + AI | $14/mo ($140/yr) | AI summaries, topic classification, smart digests |
Self-hosted users get all Pro + AI features for free.
| Phase | Theme | Status |
|---|---|---|
| 0 | Platform hardening, Docker Compose, CI/CD | Done |
| 1 | 3-pane reader, full-text extraction, reader mode | Done |
| 2 | Ranking personalization, mark-read tuning | Next |
| 3 | AI enrichment pipeline (multi-provider) | Done |
| 4 | Feed discovery engine | Partial |
| 5 | Notifications (push, email digest) | Partial |
| 6 | Billing integration (Lemon Squeezy) | Wired |
| 7 | Mobile PWA polish | Planned |
| 8 | Annotations and highlights | Done |
| 9 | Privacy, GDPR, data export | Done |



