# Readest Architecture This document gives a system-level view of Readest: how the pieces fit together, which side of the wire each piece runs on, and what each module is responsible for. It complements [`code-layout.md`](./code-layout.md), which focuses on the directory layout. Read this one first if you want to understand the system; read that one when you need to find a specific file. The diagrams use [Mermaid](https://mermaid.js.org/) and render natively on GitHub. ## 1. High-level picture Readest is a single TypeScript/React codebase (`apps/readest-app`) compiled into multiple targets: - a **desktop app** (Windows / macOS / Linux) via Tauri v2 - a **mobile app** (Android / iOS) via Tauri v2 mobile - a **web app** running on Next.js / Cloudflare Workers (OpenNext) at [web.readest.com](https://web.readest.com) - two **side surfaces**: a "Send to Readest" browser extension (`apps/readest-app/extension/send-to-readest`) and a Windows thumbnail shell extension (`apps/readest-app/extensions/windows-thumbnail`) The same React UI runs in all targets. What differs is the **host shell** under the UI and the **set of services** that the UI binds to at runtime — see section 4. ```mermaid flowchart LR subgraph Clients Desktop["Desktop app
(Tauri shell + React UI)"] Mobile["Mobile app
(Tauri Android/iOS + React UI)"] Web["Web app
(Next.js + React UI)"] Ext["Browser extension
(Send to Readest)"] WinExt["Windows shell ext
(thumbnail provider)"] end subgraph Backend["Readest backend (Next.js routes + Cloudflare Worker)"] AppApi["src/app/api/*
(App Router)"] PagesApi["src/pages/api/*
(Pages Router)"] RuntimeCfg["/runtime-config.js
(server-injected config)"] Worker["workers/send-email
(Cloudflare Worker)"] end subgraph Cloud["External services"] Supabase["Supabase
(auth + Postgres)"] S3["Object storage
(S3 / R2)"] Stripe["Stripe
(billing)"] AI["AI providers
(OpenAI / Ollama / ...)"] Trans["Translators
(DeepL / Google / Azure / Yandex)"] Meta["Metadata providers
(Google Books / Open Library)"] Dict["Dictionary sources
(Wikipedia / Wiktionary / StarDict)"] OPDS["OPDS catalogs / Calibre"] Hardcover["Hardcover GraphQL"] Readwise["Readwise"] TTS["Edge TTS"] IAP["Apple / Google IAP"] end Desktop --> Backend Mobile --> Backend Web --> Backend Ext --> PagesApi WinExt -.reads files.-> Desktop PagesApi --> Supabase PagesApi --> S3 PagesApi --> Trans AppApi --> Supabase AppApi --> Stripe AppApi --> AI AppApi --> Meta AppApi --> OPDS AppApi --> Hardcover AppApi --> TTS AppApi --> IAP Web -.direct.-> Dict Desktop -.direct.-> Dict Mobile -.direct.-> Dict Web -.direct.-> Readwise Desktop -.direct.-> Readwise ``` The `Backend` box is **the same code on all clients**. In the web target it is deployed as a Cloudflare Worker (via `@opennextjs/cloudflare` and `wrangler.toml`). In the Tauri targets the same routes are served by a Next.js runtime, but most clients hit the production deployment over HTTPS. ## 2. Process boundaries There are three runtimes in play: ```mermaid flowchart TB subgraph Browser["Web runtime (browser / Tauri webview)"] UI["React UI
(src/app, src/components, src/hooks, src/store)"] Domain["Shared domain layer
(src/services, src/utils, src/libs)"] Foliate["foliate-js
(packages/foliate-js)"] SW["Service worker (sw.ts)"] TursoWasm["Turso WASM
(replica DB in browser)"] end subgraph Native["Tauri native host (Rust)"] TauriCore["src-tauri/src/lib.rs
(commands, dir_scanner, transfer_file, clip_url, discord_rpc)"] Plugins["Tauri plugins
(fs, dialog, http, oauth, deep-link, opener, updater,
native-bridge, native-tts, turso, webview-upgrade)"] end subgraph Server["Next.js server (Worker / Node)"] Routes["App Router + Pages Router routes"] Mw["middleware.ts
(CORS + COOP/COEP)"] RuntimeRoute["app/runtime-config.js
(server-rendered config script)"] end UI --> Domain Domain --> Foliate UI --> SW Domain --> TursoWasm Domain -- "@tauri-apps/api invoke()" --> TauriCore TauriCore --> Plugins Domain -- "fetch(/api/...)" --> Routes Browser -- "