Really Simple Syndication Service
See rsss.space.
npm startReads are always via IndexedDB.
loadFeeds(),loadItems(),loadCounts()read exclusively fromIndexedDB.- Works identically whether online or offline
State.sync()callslocalAdapter.sync()which hits/api/sync?since=<lastSyncTime>and upserts any new/updated feeds and items intoIndexedDB- Called automatically on app startup (when authenticated + online)
- Called automatically when the browser comes back online (online event)
- Bluesky OAuth authentication (AT Protocol)
- Session management with encrypted cookies
- Route requests to user-specific Durable Objects
- Static asset serving for the Preact frontend
- Uses SQLite storage for feeds and items
- Uses the Hibernation API (extends DurableObject)
- Alarms for periodic feed refreshing (every 10 minutes)
- Complete RSS/Atom feed parser
- Login page with Bluesky OAuth
- Feed management (add/delete/refresh)
- Item list with filtering (unread/starred/by feed)
- Item reader with read/star toggles
- Responsive design
src/
├── server/
│ ├── index.ts # Main Hono worker
│ ├── auth/oauth.ts # Bluesky OAuth implementation
│ └── durable-objects/
│ └── collie-user.ts # Per-user DO with SQLite
└── client/
├── index.ts # Main Preact entry
├── state.ts # State management & API client
├── style.css # All styles
└── routes/
├── login.ts # Login page component
└── feed-reader.ts # Main feed reader UI
npm run start # Start dev serverThen access http://localhost:8888 and use the "Dev Login" button in
development mode.
- Create a KV namespace for sessions:
wrangler kv:namespace create SESSIONS- Update wrangler.jsonc with the KV ID
- Set secrets:
wrangler secret put SESSION_SECRET- Deploy:
wrangler deployopenssl rand -base64 32sqlite3 /Users/nick/code/rsss/.wrangler/state/v3/do/rsss-UserDO/5ccaac5db5efdc5e2ac84cd63b9141cf9dcf247c7a410cc13ce1f9d1ebbc1410.sqliteconst { usage, quota } = await navigator.storage.estimate();
console.log(usage / (1024 * 1024).toFixed(2));
console.log(quota / (1024 * 1024).toFixed(2));