A modern, self-hosted RSS/feed reader with support for RSS, YouTube, Reddit, and Podcasts.
- Multi-source support (RSS, YouTube, Reddit, Podcasts)
- Full-text search with FTS5
- Starred items and OPML import/export
- Reader view and exponential backoff
- Modern glassy UI with dark mode
Ubuntu Server:
git pull
./scripts/deploy.shSee DEPLOY.md for complete deployment instructions.
- Frontend: SvelteKit + TypeScript (static output)
- Backend: Fastify + TypeScript + SQLite
- Deployment: Docker Compose + Caddy (with Tailscale)
FeedStream-PWA/
├── web/ # SvelteKit frontend
│ ├── src/
│ │ ├── routes/ # Pages and layouts
│ │ └── app.html # HTML template
│ ├── static/ # Static assets (icons, manifest, service worker)
│ └── build/ # Production build output (generated)
├── api/ # Fastify backend
│ ├── src/
│ │ └── index.ts # Main server file
│ └── Dockerfile
├── scripts/
│ └── deploy.sh # Automated deployment script
├── docker-compose.yml
├── Caddyfile
├── DEPLOY.md # Deployment guide
└── .gitignore
# Frontend
cd web
npm install
# Backend
cd ../api
npm install
cd ..Test locally before building for production:
# Terminal 1 - Backend
cd api
npm run dev
# Terminal 2 - Frontend
cd web
npm run devVisit http://localhost:5173 (frontend dev server will proxy /api to backend).
# Build frontend static files
cd web
npm run build
# This creates web/build/ folder
# Build backend (optional - Docker will do this)
cd ../api
npm run build
cd ..# From FeedStream-PWA/ root
docker-compose up -dWhat to expect:
- API will be available at http://127.0.0.1:3000/health (locally)
- Caddy will serve the app at https://feedstream.swallow-cliff.ts.net
- SQLite database will persist in a Docker volume at
/data/feedstream.sqlite - Service worker will register on first visit (production only)
Visit https://feedstream.swallow-cliff.ts.net in your browser:
- You should see "FeedStream - Private feed reader"
- Click "Health check" button
- You should see JSON response:
{ "ok": true, "time": "..." }
# View all logs
docker-compose logs -f
# View specific service
docker-compose logs -f api
docker-compose logs -f caddydocker-compose down
# To also remove volumes (database will be deleted!)
docker-compose down -v- Static Output: The frontend builds to
web/build/as configured insvelte.config.js - API Prefix: Caddy strips
/apiprefix before proxying to backend - Service Worker: Only registers in production builds (not in dev mode)
- Icons: Replace placeholder files in
web/static/icons/with actual PNG icons - Database: Persists in Docker volume; survives container restarts
- Change hostname: Edit
Caddyfileline 1 - Change port: Edit
docker-compose.ymlAPI service environment - Add routes: Create new files in
web/src/routes/ - Add API endpoints: Edit
api/src/index.ts