Omnivore is a self-hosted read-it-later platform designed for avid readers who want full control over their reading data. It solves the problem of fragmented reading experiences by offering a unified space to save, annotate, and revisit articles, newsletters, and PDFs with rich text features like highlighting and notes. Built for privacy-conscious users, it eliminates reliance on cloud services after its 2024 deprecation of the hosted version.
The application is built with a modern tech stack: the web interface uses Next.js, TypeScript, and Stitches, while the backend leverages GraphQL via Apollo and SWR for data fetching. It supports deployment via Docker Compose, includes a content-fetch microservice using Puppeteer, and integrates with PDF.js for PDF rendering. Native iOS and Android apps, browser extensions, and plugin ecosystems for Obsidian and Logseq extend its reach across platforms.
What You Get
- Full-text search with highlights - Search saved articles and view annotated highlights with context, enabling deep review of saved content.
- PDF support with native rendering - Save and read PDFs directly in the app using Mozilla’s PDF.js, preserving layout and enabling annotations.
- Email-based article saving (with Substack) - Add articles to your library by forwarding emails, including full Substack newsletter support without manual copy-paste.
- Logseq and Obsidian integration - Sync saved articles and highlights to Logseq and Obsidian via official plugins for knowledge management workflows.
- Keyboard-driven navigation - Navigate your reading list and articles using full keyboard shortcuts for efficient, distraction-free reading.
- Offline reading support - Access saved articles and PDFs without an internet connection, ideal for commuting or low-connectivity environments.
- Browser extensions for all major browsers - Save articles to Omnivore with one click using extensions for Chrome, Safari, Firefox, and Edge.
- Automatic reading position saving - The app remembers where you left off in long articles, even across devices or sessions.
- Text-to-speech (iOS only) - Listen to saved articles via native iOS text-to-speech functionality for hands-free consumption.
- Self-hosted deployment with Docker - Deploy the full stack (web, API, content-fetch, PostgreSQL) on your own server using provided Docker Compose files.
Common Use Cases
- Managing a research library - A graduate student saves academic papers and newsletters from email, highlights key passages, and syncs them to Obsidian for thesis writing.
- Running a paid newsletter - A journalist uses Omnivore to archive and annotate subscriber-only content from Substack, then shares highlights with paying readers via export.
- Building a personal knowledge base - A developer saves technical blog posts, uses highlights to tag key concepts, and links them to Logseq for building a connected knowledge graph.
- Reading on the go with offline access - A commuter saves articles during the day and reads them offline on their iPhone using the native app with text-to-speech enabled.
Under The Hood
Architecture
- Monorepo structure with clearly separated packages following domain-driven design, ensuring minimal cross-package dependencies and clear responsibility boundaries
- API layer implements GraphQL with code-generated resolvers and schema definitions, enforcing type safety and separating schema from business logic
- Service-layer architecture with dependency injection enables testable, decoupled business logic that interacts with data access layers without direct database calls
- Event-driven content fetching pipeline asynchronously processes URL ingestion, decoupling web crawling from core API and database operations
- Next.js frontend leverages server-side rendering and environment-aware configuration, tightly integrated with GraphQL via generated TypeScript clients for type-safe data flow
- Docker-compose orchestration enforces microservice isolation with health checks, enabling scalable deployment and clear component boundaries
Tech Stack
- Next.js frontend with TypeScript and GraphQL code generation for type-safe client queries
- Node.js API server powered by GraphQL and PostgreSQL, enhanced with vector embeddings for semantic search
- Multi-package monorepo managed by Lerna and Yarn, with dedicated packages for API, web, content-fetch, and appreader
- Redis used for caching and session management, integrated across content-fetch and API services
- Docker-based infrastructure with PostgreSQL primary-replica setup and automated migrations
- Vercel orchestrates web frontend deployment with optimized static asset caching and environment-aware configuration
Code Quality
- Extensive test suite exists but lacks meaningful assertions and validation logic, rendering most tests ineffective as verification tools
- Poor error handling with abundant try-catch blocks but no custom error classes or structured logging, leading to opaque failure modes
- Inconsistent naming conventions across services, entities, and test utilities, with mixed case styles and unclear patterns
- Type safety is partially enforced but compromised by loose partial types and unvalidated inputs in critical areas like test data creation
- Linting and code quality tooling are absent or unenforced, evident in malformed HTML fixtures and unstructured test data
- Test files contain raw HTML and JSON without assertions, suggesting they serve as data samples rather than verification mechanisms
What Makes It Unique
- Native EPUB reader with deep PSPDFKit integration for synchronized highlighting and annotations directly in the browser
- Two-way bi-directional sync with Notion and Readwise that auto-updates schemas and triggers exports without user intervention
- Unified cross-platform architecture sharing business logic between Next.js web and Compose Android while preserving native performance and UI
- Built-in text-to-speech and offline reading with seamless native iOS/macOS app integrations
- Custom GraphQL resolvers that dynamically instantiate third-party clients like Notion databases on-the-fly, reducing configuration friction
- Adaptive iOS install prompt UI that tailors layout and content based on user context, enhancing conversion without separate pages