A full-stack RSS feed aggregator. Follow feeds, and a background worker continuously scrapes them into a clean, unified timeline of posts.
Go · PostgreSQL · sqlc · Goose — React · TanStack · Tailwind · shadcn/ui
RSS Aggregator lets users sign up, add RSS feeds, follow the ones they care about, and read every post from those feeds in one place. A concurrent background worker polls followed feeds on a fixed interval, parses new items, and stores them — so the timeline stays fresh without any manual refreshing.
The project is split into two independent services:
server/— a Go REST API that owns auth, feeds, follows, posts, and the scraping worker.frontend/— a React single-page app that consumes the API.
- Authentication — signup/login with bcrypt-hashed passwords, and per-user API key auth for protected routes
- Feed management — add any RSS feed by URL, follow/unfollow feeds independently of who created them
- Background scraper — a goroutine pool polls due feeds on a timer, parses RSS/XML, and inserts new posts while skipping duplicates
- Personalized timeline — fetch posts only from the feeds the current user follows, plus single-post detail views
- Type-safe data layer — every SQL query is hand-written and compiled into type-safe Go with
sqlc; schema changes are version-controlled withgoosemigrations - Modern frontend — file-based routing, server-state caching, and an accessible component library out of the box
┌──────────────────┐ REST (JSON) ┌──────────────────┐
│ React + Vite │ ───────────────────────▶ │ Go API │
│ TanStack Router │◀─────────────────────── │ (chi router) │
│ TanStack Query │ └────────┬─────────┘
└──────────────────┘ │
│ sqlc-generated queries
▼
┌──────────────────┐
│ PostgreSQL │
└──────────────────┘
▲
│
┌─────────────────┴──────────────────┐
│ Background scraper goroutine │
│ polls feeds → parses RSS/XML │
│ → inserts posts │
└────────────────────────────────────┘
| Tool | Purpose |
|---|---|
| Go | API server & concurrent feed scraper |
| chi | Lightweight HTTP router & middleware |
| PostgreSQL | Primary datastore |
| sqlc | Generates type-safe Go from raw SQL queries |
| goose | Versioned SQL schema migrations |
| bcrypt | Password hashing |
| Tool | Purpose |
|---|---|
| React 19 | UI library |
| TanStack Router | Type-safe, file-based routing |
| TanStack Query | Server-state fetching & caching |
| Tailwind CSS v4 | Utility-first styling |
| shadcn/ui | Accessible, composable component primitives |
| Vite | Build tool & dev server |
- Docker Compose — spins up the API, frontend dev server, and a Postgres 17 container together
- GitHub Actions — lints (
golangci-lint) and runs the Go test suite on every push/PR
- Go 1.26+
- Bun (or Node.js) for the frontend
- PostgreSQL (or Docker)
- goose CLI for migrations
git clone https://github.com/Resham8/rss-aggregator.git
cd rss-aggregatorcp .env.example .envPORT=8080
DATABASE_URL=postgres://postgres:yourpassword@localhost:5432/rssagg?sslmode=disabledocker compose up --buildThis starts Postgres, the Go API, and the Vite dev server together.
Database migrations:
cd server/sql/schema
goose postgres "$DATABASE_URL" upAPI server:
cd server
go run .Frontend:
cd frontend
bun install
bun run devThe app will be available at http://localhost:5173, talking to the API on the port set in .env.
All routes are mounted under /v1. Authenticated routes expect:
Authorization: ApiKey <your_api_key>
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/v1/healthz |
– | Health check |
POST |
/v1/users |
– | Create a new user |
POST |
/v1/login |
– | Log in, returns user + API key |
GET |
/v1/users |
✅ | Get the current authenticated user |
POST |
/v1/feeds |
✅ | Create a new feed |
GET |
/v1/feeds |
– | List all feeds |
POST |
/v1/feed_follows |
✅ | Follow a feed |
GET |
/v1/feed_follows |
✅ | List the current user's followed feeds |
DELETE |
/v1/feed_follows/{feedFollowId} |
✅ | Unfollow a feed |
GET |
/v1/posts |
✅ | Get posts from followed feeds |
GET |
/v1/posts/{post_id} |
✅ | Get a single post |
cd server
go test -v -race ./...CI runs lint (golangci-lint) and the full test suite on every push and pull request via GitHub Actions.
- OPML import/export for bulk feed management
- Read/unread & favorite post tracking
- Feed categories / tags
This project is open source and available under the MIT License.