A modern, Google Reader-style feed aggregator that combines traditional RSS feeds with Nostr's decentralized long-form content (NIP-23) and video content.
- Automatic bidirectional sync with category support
- Dual organization modes: Tags or Categories, with an Uncategorized fallback
- Chrome extension with feed detection, background sync, offline caching, and desktop notifications
- Admin Dashboard for managing the feed directory
- Go/Charm TUI client with a CLI development guide
- Readstr for Omarchy: a native Linux desktop app, now in development (plan)
- Configurable Nostr relays with the missing
nostrRelaysmigration restored - Fixes to organization mode switching and overall stability
Readstr is a full-stack web application built with Next.js that provides a unified reading experience for RSS feeds, Nostr long-form content, and video feeds from YouTube and Rumble. It features a clean, three-panel interface reminiscent of Google Reader, allowing users to subscribe to their favorite blogs, Nostr authors, and video channels in one place.
Readstr runs on the web, installs as a PWA, has a Chrome extension, and is getting a native desktop app for Linux and Omarchy. Your Nostr key keeps subscriptions and read state in sync across all of them.
- Subscribe to RSS/Atom feeds with automatic feed discovery
- Subscribe to Nostr users for their long-form content (NIP-23)
- Subscribe to video channels (YouTube and Rumble)
- Manual refresh or automatic feed updates
- Remove feeds with one click
- Unread count tracking per feed
- Dual organization modes: Tags or Categories
- Filter feeds by tags or categories
- Three-panel Google Reader-style interface
- Clean, readable content formatting for Markdown, HTML, and plain text
- Embedded video player for YouTube and Rumble content
- Mark articles as read/unread
- Configurable mark-as-read behavior (on open, after 10 seconds, or manual)
- Full-screen article view with proper typography
- Independent scrolling for feed list, article list, and content pane
- Favorites system - Star articles for later reading
- Dark mode support with optimized readability
- Sidebar view toggle: Switch between Feeds, Tags, Categories, and Favorites
- Tag-based filtering: Select one or more tags to filter feeds
- Category system: Create custom categories with colors and icons
- Unread counts per tag/category: See total unread items for each
- Feed counts per tag/category: Track how many feeds belong to each
- Tag sorting: Alphabetically or by unread count
- Smart tag management with visual pill interface
- Profile search across configured relays
- Popular user discovery
- Customizable relay configuration
- NIP-23 long-form content support
- NIP-94 video content support
- Display user names and profile information
- Share articles to Nostr with attribution
- Subscription sync via Nostr (kind 30404 events)
- Export subscriptions to Nostr relays
- Import subscriptions from Nostr relays
- Automatic sync detection on login
- Cross-app compatibility with documented sync protocol
- Intelligent feed discovery (supports homepage URLs)
- Checks common feed locations (/feed, /rss, /atom.xml, etc.)
- Parses HTML for feed links
- Supports RSS, Atom, and JSON Feed formats
- YouTube channel RSS feeds auto-discovery
- Rumble channel RSS feeds support
- YouTube video embedding with proper iframe integration
- YouTube Shorts support
- Rumble video embedding
- Video thumbnail extraction
- Clean video player interface
- NIP-07 signing via browser extensions (nos2x, Alby, etc.) on desktop
- NIP-46 remote signing (Nostr Connect) — pair a remote signer such as Amber with a
bunker://connection string, for Android and other browsers without an extension - Read-only npub view for browsing without a signer
- No centralized account system — your npub is your identity
- Public catalog of Nostr feeds for discovery
- Browse featured Nostr authors by topic
- Submit new feeds to the directory
- Featured feeds curation
- Installable as a mobile app
- Offline-capable service worker
- App manifest for home screen installation
- Browser toolbar access with unread count badge
- Feed detection on any web page with RSS/Atom links
- One-click subscribe via context menu or toolbar popup
- Background sync with configurable polling interval
- Offline support using IndexedDB for cached feeds and items
- Desktop notifications for new articles
- Nostr authentication via NIP-07 extension or nsec key
In development. Nothing below is released yet. This section describes the planned app; progress is tracked in the beads epic
readstr-gp3, and the full design is in docs/OMARCHY_APP_PLAN.md.
A native reader for RSS and Nostr on Linux and Omarchy, written in C++ and Qt Quick. Its three panes (sources, article list and reading view) keep your subscriptions and articles on your computer. If you sign in with your npub, it stays in sync with Readstr on the web, your phone and the Chrome extension.
- RSS, Atom and JSON Feed, with feed discovery from a site's homepage
- Nostr long-form (NIP-23) and video (NIP-94) from the authors you follow, plus YouTube and Rumble channels; videos play in
mpv - Sync over Nostr using the same events as the web app (kinds 30404, 30405 and 30406)
- Read-only with just an npub
- Publish changes with a NIP-46 remote signer (such as Amber) or a key kept in your system keyring
- Tags, categories, saved views and keyword filters, like on the web
- OPML import and export through the desktop file picker
- Full-text search across everything stored locally
- Follows your Omarchy theme and language as they change, and window corners match Hyprland's rounding
- Keyboard first, with every action on a key and
?to list them - Command line with
--jsonfor scripts, agents and the Omarchy bar - Free and local-first: no account required, no telemetry, nothing runs in the background after you close it. An optional paid Readstr account (through Flash) will add server-side extras later; reading always stays free.
Once released:
omarchy pkg add readstror use Omarchy menu → Install → Package. The app then shows up in the launcher (Super + Space).
An Omarchy bar widget, readstr-bar, will show your unread count:
omarchy plugin add <readstr-bar repo URL> --enableIt runs on any Linux desktop with Qt 6, not just Omarchy. Elsewhere it falls back to a built-in dark theme and your system language.
| Key | Action |
|---|---|
J / K or ↓ / ↑ |
Next / previous article |
N |
Next unread |
Space / Shift+Space |
Scroll forward / back |
M / S |
Toggle read / star |
O |
Open original in browser |
V |
Play video in mpv |
1–5 |
Feeds / Tags / Categories / Favorites / Views |
Ctrl+R / Ctrl+F |
Refresh / search |
Ctrl+N |
Add feed |
Ctrl+Shift+A / Ctrl+Z |
Mark view read / undo |
Ctrl+Shift+S |
Sync now |
Q |
Quit |
? |
Show all shortcuts |
readstr on its own opens the window. With a command it runs without a window, and every command takes --json:
readstr feeds | articles [--unread] | article <id> | search <query>
readstr subscribe <url|npub> | unsubscribe <id> | read|unread|star <id...>
readstr refresh | import <file.opml> | export | unread
readstr sync pull|push|status
Feed content is written by strangers, so scripts and AI agents should treat article text as untrusted input.
- Articles and settings live in
~/.local/share/readstr,~/.config/readstrand~/.cache/readstr. - Sync events are public Nostr events, as on the web: they link your npub to your subscriptions and read state.
- Signing keys never go in a config file. Use a remote signer, or the system keyring.
- Article scripts, frames and forms are never run. Loading remote images can be turned off.
- Next.js 16 - React framework with App Router
- TypeScript - Type safety throughout
- Tailwind CSS - Utility-first styling
- tRPC - End-to-end type-safe APIs
- TanStack Query - Data fetching and caching
- Next.js API Routes - Serverless functions
- Prisma - Type-safe database ORM
- PostgreSQL - Primary database
- tRPC - Type-safe API layer
- nostr-tools - Nostr protocol implementation
- SimplePool - Relay connection pooling
- Configurable relay support
- xml2js - RSS/Atom feed parsing
- cheerio - HTML parsing for feed discovery
- react-markdown - Markdown rendering
- rehype-sanitize - HTML sanitization
- remark-gfm - GitHub Flavored Markdown support
- Docker - Containerized deployment
- Docker Compose - Multi-container orchestration
- Caddy - Reverse proxy with automatic HTTPS
The overrides block in package.json pins transitive dependencies to patched
versions that remediate known advisories:
- serialize-javascript
^7.1.3— fixes RCE viaRegExp.flags/Date.prototype.toISOString()(GHSA-5c6j-r48x-rmvq, affected<= 7.0.2) and XSS via an unescaped</scriptat the end of a serialized function body (GHSA-m5mm-p8h7-m29v, affected< 7.1.3). - postcss
$postcss— forces transitive consumers (includingnext's pinned copy) onto the top-levelpostcss(^8.5.23), past the line-return parsing flaw (GHSA-7fh5-64p2-3v2j, affected< 8.4.31) and thesourceMappingURLarbitrary.mapfile reads (GHSA-r28c-9q8g-f849, affected<= 8.5.17; GHSA-fxqj-rqcc-2cmp, affected<= 8.5.22). - postcss-selector-parser
^6.1.5(scoped to@tailwindcss/typography, which pins6.0.10) — fixes quadratic-time parsing of flat selectors (GHSA-rj75-hqrm-r3gf, affected< 6.1.5) and uncontrolled AST recursion (GHSA-w9m9-85wc-3x92, affected>= 6.1.0, < 6.1.3).
- Node.js 18+
- PostgreSQL database
- Nostr browser extension (nos2x, Alby, etc.)
- Clone the repository:
git clone https://github.com/privkeyio/readstr.git
cd readstr- Install dependencies:
npm install- Set up environment variables:
Create a
.envfile in the root directory:
DATABASE_URL="postgresql://user:password@localhost:5432/readstr"- Initialize the database:
npx prisma generate
npx prisma db push- Run the development server:
npm run dev- Open http://localhost:3000 in your browser
- Copy the environment example:
cp .env.production.example .env.production-
Configure your environment variables in
.env.production -
Build and run with Docker Compose:
docker compose up -d- Click "Connect with Nostr" on the homepage
- Authorize the connection using your Nostr browser extension
- You'll be redirected to the feed reader
RSS Feeds:
- Click "Add Feed" in the sidebar
- Select "RSS Feed" tab
- Enter the feed URL (or website homepage)
- Optionally assign tags or a category
- The app will automatically discover and subscribe to the feed
Nostr Feeds:
- Click "Add Feed" in the sidebar
- Select "Nostr User" tab
- Search for users by name or NIP-05 address
- Or manually enter an npub
- Click on a profile to subscribe
Video Channels:
- Click "Add Feed" in the sidebar
- Select "Video Channel" tab
- Paste a YouTube or Rumble channel URL
- The app will discover and subscribe to the channel's RSS feed
- Click the ⋮ menu on a feed to see options
- Mark all items as read
- Set category (in categories mode)
- Edit tags (in tags mode)
- Delete the subscription
Tags Mode:
- Assign multiple tags to each feed
- Filter by selecting one or more tags
- Sort tags alphabetically or by unread count
Categories Mode:
- Create categories with custom icons and colors
- Assign one category per feed
- View feeds grouped by category in the sidebar
To switch modes:
- Open Settings (gear icon)
- Go to "Feed Organization" tab
- Choose Tags or Categories
- Click the gear icon in the sidebar
- Go to "Nostr Relays" tab
- Add or remove Nostr relays
- Use quick-add buttons for popular relays
- Click "Reset to Defaults" to restore default relays
- Open Settings (gear icon)
- Go to "Sync" tab
- Click "Export to Nostr" to save your subscriptions
- Click "Import from Nostr" to restore on another device
- Requires a Nostr browser extension
- Open Settings (gear icon)
- Go to "Reading" tab
- Choose when to mark articles as read:
- When you open an article
- After 10 seconds of reading
- Never (manual only)
Public API for accessing the Nostr feed directory. See GUIDE_API.md for full documentation.
Cross-app subscription sync using Nostr kind 30404 events. See SUBSCRIPTION_SYNC.md for implementation details.
The application uses the following main models:
- Feed - Stores RSS and Nostr feed information
- FeedItem - Individual articles/posts with video metadata
- Subscription - User subscriptions to feeds with tags/category
- Category - User-defined categories with colors and icons
- UserPreference - User settings including organization mode
- ReadItem - Tracks which items users have read
- Favorite - User's favorited articles
- GuideFeed - Public directory of Nostr feeds
- NostrRelay - Configurable relay list
src/
├── app/ # Next.js app router pages
│ ├── api/ # API routes
│ │ ├── guide/ # Guide directory API
│ │ ├── nostr-rss/ # Nostr-to-RSS converter
│ │ └── webhooks/ # External webhooks
│ ├── guide/ # Guide directory pages
│ ├── reader/ # Main feed reader
│ └── subscribe/ # Subscription management
├── components/ # React components
│ ├── feed-reader.tsx # Main reader interface
│ ├── add-feed-modal.tsx# Feed subscription UI
│ ├── settings-dialog.tsx# Settings with tabs
│ ├── formatted-content.tsx # Content renderer
│ └── video-embed.tsx # Video player component
├── contexts/ # React contexts
│ └── NostrAuthContext.tsx
├── lib/ # Utilities
│ ├── nostr-fetcher.ts # Nostr protocol interactions
│ ├── nostr-sync.ts # Subscription sync
│ ├── rss-parser.ts # RSS feed parsing
│ ├── feed-discovery.ts# RSS feed discovery
│ └── video-parser.ts # Video URL parsing
├── server/ # Backend code
│ └── api/
│ └── routers/
│ ├── feed.ts # Main feed router
│ ├── guide.ts # Guide directory router
│ └── subscription.ts
└── prisma/
└── schema.prisma # Database schema
chrome-extension/
├── src/
│ ├── background.ts # Service worker for sync and notifications
│ ├── content.ts # Feed detection on web pages
│ ├── nostr.ts # Nostr authentication helpers
│ └── db/ # IndexedDB caching layer
├── manifest.json # Extension manifest (V3)
└── dist/ # Built extension (load unpacked)
desktop/ # Readstr for Omarchy (in development)
├── src/ # C++ backend + QML interface
├── tests/ # Qt Test suite
└── pkgbuild/ # PKGBUILD, .desktop entry, icon
Contributions are welcome! Please feel free to submit a Pull Request.
MIT
- Originally based on Nostr-Feedz
- Inspired by Google Reader's clean interface
- Built on the Nostr protocol for decentralized identity
- Thanks to the T3 Stack for the excellent Next.js template
- The desktop app follows omafeed and Omarchy's app conventions