refactor(docs): reorganize and enhance documentation structure
- Rename configuration.md to auth.md for clarity - Rename storage-and-blob-behavior.md to object-blob-storage.md - Split server library import into dedicated documentation page - Rename intro.md to introduction.md - Merge support.md into support-and-contributing.md - Add interactive tabs to configuration and setup guides - Improve cross-references and navigation between documentation pages - Update sidebar structure and Docusaurus config for new file paths
This commit is contained in:
parent
4e2d18962d
commit
63483e055e
14 changed files with 315 additions and 120 deletions
|
|
@ -15,5 +15,5 @@ This page covers application-level configuration for provider access and authent
|
||||||
- For the complete variable reference: [Environment Variables](../reference/environment-variables)
|
- For the complete variable reference: [Environment Variables](../reference/environment-variables)
|
||||||
- For TTS character limits and quota behavior: [TTS Rate Limiting](./tts-rate-limiting)
|
- For TTS character limits and quota behavior: [TTS Rate Limiting](./tts-rate-limiting)
|
||||||
- For provider-specific guidance: [TTS Providers](./tts-providers)
|
- For provider-specific guidance: [TTS Providers](./tts-providers)
|
||||||
- For storage/S3/SeaweedFS behavior: [Object / Blob Storage](./storage-and-blob-behavior)
|
- For storage/S3/SeaweedFS behavior: [Object / Blob Storage](./object-blob-storage)
|
||||||
- For database mode and migration commands: [Database and Migrations](./database-and-migrations)
|
- For database mode and migration commands: [Database and Migrations](./database-and-migrations)
|
||||||
|
|
@ -2,12 +2,15 @@
|
||||||
title: Database and Migrations
|
title: Database and Migrations
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
This page covers database mode selection and migration behavior for OpenReader WebUI.
|
This page covers database mode selection and migration behavior for OpenReader WebUI.
|
||||||
|
|
||||||
## Database mode
|
## Database mode
|
||||||
|
|
||||||
- Default mode: embedded SQLite at `docstore/sqlite3.db`
|
- SQLite (default): embedded DB at `docstore/sqlite3.db`; good for local/self-host single-instance setups.
|
||||||
- External mode: Postgres when `POSTGRES_URL` is set
|
- Postgres: enabled when `POSTGRES_URL` is set; recommended for production/distributed deployments.
|
||||||
|
|
||||||
## Startup migration behavior
|
## Startup migration behavior
|
||||||
|
|
||||||
|
|
@ -22,6 +25,10 @@ Startup migration phases:
|
||||||
- DB schema migrations (`pnpm migrate`)
|
- DB schema migrations (`pnpm migrate`)
|
||||||
- Storage/data migration (`pnpm migrate-fs`) for legacy filesystem content into S3 + DB rows
|
- Storage/data migration (`pnpm migrate-fs`) for legacy filesystem content into S3 + DB rows
|
||||||
|
|
||||||
|
:::info
|
||||||
|
In most setups, you do not need to run migration commands manually because startup handles this automatically.
|
||||||
|
:::
|
||||||
|
|
||||||
To skip automatic startup migrations:
|
To skip automatic startup migrations:
|
||||||
|
|
||||||
- Set `RUN_DRIZZLE_MIGRATIONS=false`
|
- Set `RUN_DRIZZLE_MIGRATIONS=false`
|
||||||
|
|
@ -33,6 +40,9 @@ Database variables are documented in [Environment Variables](../reference/enviro
|
||||||
|
|
||||||
In most cases, you do not need manual migration commands because startup runs migrations automatically.
|
In most cases, you do not need manual migration commands because startup runs migrations automatically.
|
||||||
|
|
||||||
|
<Tabs groupId="migration-commands">
|
||||||
|
<TabItem value="project-scripts" label="Project Scripts" default>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run pending migrations (uses Postgres config when POSTGRES_URL is set, otherwise SQLite)
|
# Run pending migrations (uses Postgres config when POSTGRES_URL is set, otherwise SQLite)
|
||||||
pnpm migrate
|
pnpm migrate
|
||||||
|
|
@ -47,7 +57,8 @@ pnpm migrate-fs:dry-run
|
||||||
pnpm generate
|
pnpm generate
|
||||||
```
|
```
|
||||||
|
|
||||||
## Manual Drizzle commands (advanced)
|
</TabItem>
|
||||||
|
<TabItem value="drizzle-direct" label="Drizzle Direct (Advanced)">
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Migrate SQLite
|
# Migrate SQLite
|
||||||
|
|
@ -62,3 +73,10 @@ pnpm exec drizzle-kit generate --config drizzle.config.sqlite.ts
|
||||||
# Generate Postgres migrations
|
# Generate Postgres migrations
|
||||||
pnpm exec drizzle-kit generate --config drizzle.config.pg.ts
|
pnpm exec drizzle-kit generate --config drizzle.config.pg.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
If you disable startup migrations, ensure your deployment process runs migrations before serving traffic.
|
||||||
|
:::
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
title: Object / Blob Storage
|
title: Object / Blob Storage
|
||||||
---
|
---
|
||||||
|
|
||||||
This page documents storage backends, blob upload routing, and Docker mount behavior.
|
This page documents storage backends, blob upload routing, and core Docker mount behavior.
|
||||||
|
|
||||||
## Storage backends
|
## Storage backends
|
||||||
|
|
||||||
- Default: embedded SQLite metadata + embedded SeaweedFS (`weed mini`) blobs
|
- Embedded (default): SQLite metadata + embedded SeaweedFS (`weed mini`) blobs.
|
||||||
- External option: Postgres + external S3-compatible object storage
|
- External: Postgres + external S3-compatible object storage.
|
||||||
|
|
||||||
Storage variables are documented in [Environment Variables](../reference/environment-variables) under the storage sections.
|
Storage variables are documented in [Environment Variables](../reference/environment-variables) under the storage sections.
|
||||||
|
|
||||||
|
|
@ -16,24 +16,23 @@ Storage variables are documented in [Environment Variables](../reference/environ
|
||||||
- `3003`: OpenReader app and API routes
|
- `3003`: OpenReader app and API routes
|
||||||
- `8333`: Embedded SeaweedFS S3 endpoint for direct browser blob access
|
- `8333`: Embedded SeaweedFS S3 endpoint for direct browser blob access
|
||||||
|
|
||||||
|
:::info
|
||||||
|
`8333` is only needed for direct browser presigned access to embedded SeaweedFS.
|
||||||
|
:::
|
||||||
|
|
||||||
## Upload behavior
|
## Upload behavior
|
||||||
|
|
||||||
- Primary path: browser uploads to presigned URL from `/api/documents/blob/upload/presign`
|
- Primary path: browser uploads to presigned URL from `/api/documents/blob/upload/presign`.
|
||||||
- Fallback path: `/api/documents/blob/upload/fallback` if direct upload fails or endpoint is unreachable
|
- Fallback path: `/api/documents/blob/upload/fallback` when direct upload fails/unreachable.
|
||||||
- Content serving path: `/api/documents/blob`
|
- Read/download path: blob/content serving route `/api/documents/blob` (not the upload fallback route).
|
||||||
|
|
||||||
## Recommended Docker mounts
|
## Recommended Docker mounts
|
||||||
|
|
||||||
| Mount | Type | Recommended | Purpose | Example |
|
| Mount | Type | Recommended | Purpose | Example |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| `/app/docstore` | Docker named volume | Yes (for persistence) | Persists SeaweedFS blob data, SQLite metadata DB, migrations, and local runtime temp state | `-v openreader_docstore:/app/docstore` |
|
| `/app/docstore` | Docker named volume | Yes (for persistence) | Persists SeaweedFS blob data, SQLite metadata DB, migrations, and local runtime temp state | `-v openreader_docstore:/app/docstore` |
|
||||||
| `/app/docstore/library` | Bind mount | Optional + `:ro` | Read-only source for server library import (files are copied/imported into client storage) | `-v /path/to/your/library:/app/docstore/library:ro` |
|
|
||||||
|
|
||||||
To import from mounted library: **Settings -> Documents -> Server Library Import**.
|
For server library mounts/import behavior, see [Server Library Import](./server-library-import).
|
||||||
|
|
||||||
:::note
|
|
||||||
Every file in the mounted library is imported into client browser storage. Keep the library reasonably sized.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Private blob endpoint mode
|
## Private blob endpoint mode
|
||||||
|
|
||||||
|
|
@ -43,6 +42,10 @@ If `8333` is not published externally:
|
||||||
- Reads/snippets continue through app API routes
|
- Reads/snippets continue through app API routes
|
||||||
- Direct presigned browser upload/download to embedded endpoint is unavailable
|
- Direct presigned browser upload/download to embedded endpoint is unavailable
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Without `8333`, expect higher app-server traffic because uploads/downloads go through API routes instead of direct object endpoint access.
|
||||||
|
:::
|
||||||
|
|
||||||
## Audiobook storage note
|
## Audiobook storage note
|
||||||
|
|
||||||
- In current versions, audiobook assets live in object storage (`audiobooks_v1` keyspace), not as durable files under `/app/docstore`.
|
- In current versions, audiobook assets live in object storage (`audiobooks_v1` keyspace), not as durable files under `/app/docstore`.
|
||||||
66
docs-site/docs/configure/server-library-import.md
Normal file
66
docs-site/docs/configure/server-library-import.md
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
---
|
||||||
|
title: Server Library Import
|
||||||
|
---
|
||||||
|
|
||||||
|
This page documents how server library import works and how to configure it.
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
Server library import lets you browse files from one or more server directories and import selected files into OpenReader.
|
||||||
|
|
||||||
|
- Import is user-driven via a selection modal
|
||||||
|
- Only selected files are imported
|
||||||
|
- Imported files become normal OpenReader documents
|
||||||
|
|
||||||
|
## Configure library roots
|
||||||
|
|
||||||
|
Library roots are resolved from environment variables:
|
||||||
|
|
||||||
|
- `IMPORT_LIBRARY_DIRS` (takes precedence): multiple roots separated by comma, colon, or semicolon
|
||||||
|
- `IMPORT_LIBRARY_DIR`: single root
|
||||||
|
- Fallback when neither is set: `docstore/library`
|
||||||
|
|
||||||
|
See [Environment Variables](../reference/environment-variables#import_library_dir) for details.
|
||||||
|
|
||||||
|
## Docker mount example
|
||||||
|
|
||||||
|
Mount a host folder to the default library path:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --name openreader-webui \
|
||||||
|
--restart unless-stopped \
|
||||||
|
-p 3003:3003 \
|
||||||
|
-v openreader_docstore:/app/docstore \
|
||||||
|
-v /path/to/your/library:/app/docstore/library:ro \
|
||||||
|
ghcr.io/richardr1126/openreader-webui:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Using `:ro` is recommended so the app treats the library as a read-only source.
|
||||||
|
|
||||||
|
## Import flow
|
||||||
|
|
||||||
|
1. Open **Settings -> Documents -> Server Library Import**.
|
||||||
|
2. Select files in the modal.
|
||||||
|
3. Click **Import**.
|
||||||
|
|
||||||
|
Selected files are fetched from the server library endpoint and imported into OpenReader storage.
|
||||||
|
|
||||||
|
:::warning Shared Library Roots
|
||||||
|
Library roots are configured at the server level (not per-user). Any user who can access Server Library Import can browse/import from the same configured roots.
|
||||||
|
|
||||||
|
Imported documents are still saved to the importing user's document scope.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Supported file types
|
||||||
|
|
||||||
|
- `.pdf`
|
||||||
|
- `.epub`
|
||||||
|
- `.html`, `.htm`
|
||||||
|
- `.txt`
|
||||||
|
- `.md`, `.mdown`, `.markdown`
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Library listing is capped per request (up to 10,000 files).
|
||||||
|
- When auth is enabled, library import endpoints require a valid session.
|
||||||
|
- The mounted library is a source; removing it does not delete already imported documents.
|
||||||
|
|
@ -2,47 +2,75 @@
|
||||||
title: TTS Providers
|
title: TTS Providers
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
OpenReader WebUI supports OpenAI-compatible TTS providers through a common API shape.
|
OpenReader WebUI supports OpenAI-compatible TTS providers through a common API shape.
|
||||||
|
|
||||||
## Supported provider patterns
|
:::tip
|
||||||
|
If you are running a self-hosted TTS server (Kokoro/Orpheus/etc.), use **Custom OpenAI-Like** in Settings.
|
||||||
|
:::
|
||||||
|
|
||||||
- OpenAI API
|
## Quick Setup by Provider
|
||||||
- DeepInfra
|
|
||||||
- Kokoro-FastAPI
|
|
||||||
- Orpheus-FastAPI
|
|
||||||
- Custom OpenAI-compatible endpoints
|
|
||||||
|
|
||||||
## Provider dropdown behavior
|
<Tabs groupId="tts-provider-setup">
|
||||||
|
<TabItem value="openai" label="OpenAI" default>
|
||||||
|
|
||||||
In Settings, the provider dropdown includes:
|
1. In Settings, choose provider: `OpenAI`.
|
||||||
|
2. Keep the default `API_BASE` (auto-filled).
|
||||||
|
3. Set `API_KEY` to your OpenAI key.
|
||||||
|
4. Choose model/voice.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="deepinfra" label="DeepInfra">
|
||||||
|
|
||||||
|
1. In Settings, choose provider: `Deepinfra`.
|
||||||
|
2. Keep the default `API_BASE` (auto-filled).
|
||||||
|
3. Set `API_KEY` to your DeepInfra key.
|
||||||
|
4. Choose model/voice.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="custom" label="Custom OpenAI-Like">
|
||||||
|
|
||||||
|
1. In Settings, choose provider: `Custom OpenAI-Like`.
|
||||||
|
2. Set `API_BASE` to your endpoint (example: `http://host.docker.internal:8880/v1`).
|
||||||
|
3. Set `API_KEY` if your provider requires one.
|
||||||
|
4. Choose model/voice.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
## Provider Dropdown Behavior
|
||||||
|
|
||||||
|
In Settings, provider options include:
|
||||||
|
|
||||||
- `OpenAI`
|
- `OpenAI`
|
||||||
- `Deepinfra`
|
- `Deepinfra`
|
||||||
- `Custom OpenAI-Like` (for Kokoro, Orpheus, and other compatible endpoints)
|
- `Custom OpenAI-Like` (Kokoro, Orpheus, and other OpenAI-compatible endpoints)
|
||||||
|
|
||||||
`API_BASE` guidance:
|
`API_BASE` guidance:
|
||||||
|
|
||||||
- For `OpenAI` and `Deepinfra`, OpenReader auto-fills the default endpoint.
|
- `OpenAI` and `Deepinfra` auto-fill default endpoints.
|
||||||
- For `Custom OpenAI-Like`, set `API_BASE` to your server endpoint.
|
- `Custom OpenAI-Like` requires setting `API_BASE` manually.
|
||||||
- In practice, you usually only set `API_BASE` when using a provider/endpoint that is not directly covered by the built-in dropdown defaults.
|
|
||||||
|
|
||||||
## Custom provider compatibility
|
:::info OpenAI-Compatible API Shape
|
||||||
|
Custom providers should expose:
|
||||||
For custom providers, OpenReader expects these endpoints:
|
|
||||||
|
|
||||||
- `GET /v1/audio/voices`
|
- `GET /v1/audio/voices`
|
||||||
- `POST /v1/audio/speech`
|
- `POST /v1/audio/speech`
|
||||||
|
:::
|
||||||
|
|
||||||
If your provider exposes this interface, it can be used as an OpenAI-compatible TTS backend.
|
:::warning Server-Reachable API Base
|
||||||
|
TTS requests are sent from the Next.js server, not directly from the browser. `API_BASE` must be reachable from the server runtime.
|
||||||
|
:::
|
||||||
|
|
||||||
## Setup flow
|
## Related Guides
|
||||||
|
|
||||||
1. Select your provider in the OpenReader Settings modal.
|
- [Environment Variables](../reference/environment-variables)
|
||||||
2. If using `Custom OpenAI-Like` (or overriding a default), set `API_BASE`.
|
- [TTS Rate Limiting](./tts-rate-limiting)
|
||||||
3. Set `API_KEY` if required by your provider.
|
- [Auth](./auth)
|
||||||
4. Choose model and voice.
|
- [Kokoro-FastAPI](../integrations/kokoro-fastapi)
|
||||||
|
- [Orpheus-FastAPI](../integrations/orpheus-fastapi)
|
||||||
For environment variables, see [Environment Variables](../reference/environment-variables).
|
- [Deepinfra](../integrations/deepinfra)
|
||||||
For TTS quota behavior, see [TTS Rate Limiting](./tts-rate-limiting).
|
- [OpenAI](../integrations/openai)
|
||||||
For auth behavior, see [Auth](./configuration).
|
- [Custom OpenAI](../integrations/custom-openai)
|
||||||
For provider-specific integration guides, see [Kokoro-FastAPI](../integrations/kokoro-fastapi), [Orpheus-FastAPI](../integrations/orpheus-fastapi), [Deepinfra](../integrations/deepinfra), [OpenAI](../integrations/openai), and [Custom OpenAI](../integrations/custom-openai).
|
|
||||||
|
|
|
||||||
|
|
@ -47,5 +47,5 @@ IP backstop daily limits:
|
||||||
## Related docs
|
## Related docs
|
||||||
|
|
||||||
- Full variable list: [Environment Variables](../reference/environment-variables)
|
- Full variable list: [Environment Variables](../reference/environment-variables)
|
||||||
- Auth configuration: [Auth](./configuration)
|
- Auth configuration: [Auth](./auth)
|
||||||
- Provider setup: [TTS Providers](./tts-providers)
|
- Provider setup: [TTS Providers](./tts-providers)
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
id: intro
|
|
||||||
title: Introduction
|
|
||||||
slug: /
|
|
||||||
---
|
|
||||||
|
|
||||||
OpenReader WebUI is an open source text-to-speech document reader built with Next.js. It provides a read-along experience with narration for **EPUB, PDF, TXT, MD, and DOCX documents**.
|
|
||||||
|
|
||||||
It supports multiple TTS providers including OpenAI, DeepInfra, and custom OpenAI-compatible endpoints such as [Kokoro-FastAPI](https://github.com/remsky/Kokoro-FastAPI) and [Orpheus-FastAPI](https://github.com/Lex-au/Orpheus-FastAPI).
|
|
||||||
|
|
||||||
## Highlights
|
|
||||||
|
|
||||||
- Multi-provider TTS support
|
|
||||||
- [Kokoro-FastAPI](https://github.com/remsky/Kokoro-FastAPI) (including multi-voice combinations)
|
|
||||||
- [Orpheus-FastAPI](https://github.com/Lex-au/Orpheus-FastAPI)
|
|
||||||
- Custom OpenAI-compatible endpoints (`/v1/audio/voices` and `/v1/audio/speech`)
|
|
||||||
- Cloud providers such as [DeepInfra](https://deepinfra.com/models/text-to-speech) and [OpenAI API](https://platform.openai.com/docs/pricing#transcription-and-speech)
|
|
||||||
- Server-side sync and storage
|
|
||||||
- External library import from a server-mounted folder
|
|
||||||
- Sync documents between browser and server for multi-device use
|
|
||||||
- Server-side audiobook export in `m4b`/`mp3`, with resumable chapter-based export
|
|
||||||
- Read-along highlighting for PDF and EPUB
|
|
||||||
- Optional word-by-word highlighting using server-side timestamps from [whisper.cpp](https://github.com/ggml-org/whisper.cpp)
|
|
||||||
- Sentence-aware narration that merges across pages/chapters for smoother playback
|
|
||||||
- Optimized Next.js TTS proxy with caching for faster repeat playback
|
|
||||||
- Customizable themes, TTS settings, and document handling
|
|
||||||
|
|
||||||
## Start Here
|
|
||||||
|
|
||||||
- [Docker Quick Start](./start-here/docker-quick-start)
|
|
||||||
- [Local Development](./start-here/local-development)
|
|
||||||
- [Environment Variables](./reference/environment-variables)
|
|
||||||
- [Auth](./configure/configuration)
|
|
||||||
- [Database and Migrations](./configure/database-and-migrations)
|
|
||||||
- [Object / Blob Storage](./configure/storage-and-blob-behavior)
|
|
||||||
- [TTS Providers](./configure/tts-providers)
|
|
||||||
|
|
||||||
## Source Repository
|
|
||||||
|
|
||||||
- GitHub: [richardr1126/OpenReader-WebUI](https://github.com/richardr1126/OpenReader-WebUI)
|
|
||||||
48
docs-site/docs/introduction.md
Normal file
48
docs-site/docs/introduction.md
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
id: intro
|
||||||
|
title: Introduction
|
||||||
|
slug: /
|
||||||
|
---
|
||||||
|
|
||||||
|
OpenReader WebUI is an open source text-to-speech document reader built with Next.js. It provides a read-along experience with narration for **EPUB, PDF, TXT, MD, and DOCX documents**.
|
||||||
|
|
||||||
|
It supports multiple TTS providers including OpenAI, DeepInfra, and custom OpenAI-compatible endpoints such as [Kokoro-FastAPI](https://github.com/remsky/Kokoro-FastAPI) and [Orpheus-FastAPI](https://github.com/Lex-au/Orpheus-FastAPI).
|
||||||
|
|
||||||
|
## ✨ Highlights
|
||||||
|
|
||||||
|
- 🎯 **Multi-Provider TTS Support**
|
||||||
|
- [**Kokoro-FastAPI**](https://github.com/remsky/Kokoro-FastAPI): supports multi-voice combinations (for example `af_heart+af_bella`)
|
||||||
|
- [**Orpheus-FastAPI**](https://github.com/Lex-au/Orpheus-FastAPI)
|
||||||
|
- **Custom OpenAI-compatible**: any TTS API with `/v1/audio/voices` and `/v1/audio/speech` endpoints
|
||||||
|
- **Cloud TTS providers**:
|
||||||
|
- [**DeepInfra**](https://deepinfra.com/models/text-to-speech): Kokoro-82M and other hosted models
|
||||||
|
- [**OpenAI API**](https://platform.openai.com/docs/pricing#transcription-and-speech): `tts-1`, `tts-1-hd`, and `gpt-4o-mini-tts`
|
||||||
|
- 🛜 **Server-side Document Storage**
|
||||||
|
- Documents are persisted in server blob/object storage for consistent access
|
||||||
|
- 📚 **External Library Import**
|
||||||
|
- Import documents from server-mounted folders
|
||||||
|
- 🎧 **Server-side Audiobook Export** in `m4b`/`mp3` with resumable chapter generation
|
||||||
|
- 📖 **Read Along Experience**
|
||||||
|
- Real-time highlighting for PDF/EPUB, with optional word-level [whisper.cpp](https://github.com/ggml-org/whisper.cpp) timestamps
|
||||||
|
- 🔐 **Auth Optional by Design**
|
||||||
|
- Run no-auth for local use, or enable auth with user isolation and claim flow
|
||||||
|
- 🗂️ **Flexible Storage and Database Modes** with embedded defaults or external S3/Postgres
|
||||||
|
- 🚀 **Production-ready Server Behavior** with TTS caching/retries/rate limits and startup migrations
|
||||||
|
- 🎨 **Customizable Experience**
|
||||||
|
- Theme, TTS, and document handling controls
|
||||||
|
|
||||||
|
## 🚀 Start Here
|
||||||
|
|
||||||
|
- [Docker Quick Start](./start-here/docker-quick-start)
|
||||||
|
- [Vercel Deployment](./start-here/vercel-deployment)
|
||||||
|
- [Local Development](./start-here/local-development)
|
||||||
|
- [Environment Variables](./reference/environment-variables)
|
||||||
|
- [Auth](./configure/auth)
|
||||||
|
- [Database and Migrations](./configure/database-and-migrations)
|
||||||
|
- [Object / Blob Storage](./configure/object-blob-storage)
|
||||||
|
- [Server Library Import](./configure/server-library-import)
|
||||||
|
- [TTS Providers](./configure/tts-providers)
|
||||||
|
|
||||||
|
## Source Repository
|
||||||
|
|
||||||
|
- GitHub: [richardr1126/OpenReader-WebUI](https://github.com/richardr1126/OpenReader-WebUI)
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
title: Docker Quick Start
|
title: Docker Quick Start
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- A recent Docker version installed
|
- A recent Docker version installed
|
||||||
|
|
@ -13,7 +16,10 @@ If you have suitable hardware, you can run Kokoro locally with Docker. See [Koko
|
||||||
|
|
||||||
## 1. Start the Docker container
|
## 1. Start the Docker container
|
||||||
|
|
||||||
Minimal setup (auth disabled, embedded storage ephemeral, no library import):
|
<Tabs groupId="docker-start-mode">
|
||||||
|
<TabItem value="minimal" label="Minimal" default>
|
||||||
|
|
||||||
|
Auth disabled, embedded storage ephemeral, no library import:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run --name openreader-webui \
|
docker run --name openreader-webui \
|
||||||
|
|
@ -23,7 +29,10 @@ docker run --name openreader-webui \
|
||||||
ghcr.io/richardr1126/openreader-webui:latest
|
ghcr.io/richardr1126/openreader-webui:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
Fully featured setup (persistent storage, embedded SeaweedFS `weed mini`, optional auth):
|
</TabItem>
|
||||||
|
<TabItem value="full" label="Full Setup">
|
||||||
|
|
||||||
|
Persistent storage, embedded SeaweedFS `weed mini`, optional auth, optional library mount:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run --name openreader-webui \
|
docker run --name openreader-webui \
|
||||||
|
|
@ -39,21 +48,38 @@ docker run --name openreader-webui \
|
||||||
ghcr.io/richardr1126/openreader-webui:latest
|
ghcr.io/richardr1126/openreader-webui:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
You can remove `/app/docstore/library` if you do not need server library import.
|
</TabItem>
|
||||||
You can remove either `BASE_URL` or `AUTH_SECRET` to keep auth disabled.
|
</Tabs>
|
||||||
|
|
||||||
Quick notes:
|
:::tip
|
||||||
|
Remove `/app/docstore/library` if you do not need server library import.
|
||||||
|
:::
|
||||||
|
|
||||||
- `API_BASE` should point to your TTS server base URL.
|
:::tip
|
||||||
- Expose `8333` for direct browser access to embedded SeaweedFS presigned URLs.
|
Remove either `BASE_URL` or `AUTH_SECRET` to keep auth disabled.
|
||||||
- If `8333` is not exposed, uploads still work through `/api/documents/blob/upload/fallback`.
|
:::
|
||||||
- To enable auth, set both `BASE_URL` and `AUTH_SECRET`.
|
|
||||||
- DB migrations run automatically during container startup via the shared entrypoint.
|
|
||||||
|
|
||||||
For all environment variables, see [Environment Variables](../reference/environment-variables).
|
:::tip TTS API Base
|
||||||
For app/auth behavior, see [Auth](../configure/configuration).
|
Set `API_BASE` to your reachable TTS server base URL.
|
||||||
For database startup and migration behavior, see [Database and Migrations](../configure/database-and-migrations).
|
:::
|
||||||
For blob behavior and mounts, see [Object / Blob Storage](../configure/storage-and-blob-behavior).
|
|
||||||
|
:::warning Port `8333` Exposure
|
||||||
|
Expose `8333` for direct browser presigned upload/download with embedded SeaweedFS.
|
||||||
|
|
||||||
|
If `8333` is not reachable from the browser, direct presigned access is unavailable. Uploads can still fall back to `/api/documents/blob/upload/fallback`, and document reads/downloads continue through `/api/documents/blob`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::info Auth and Migrations
|
||||||
|
- Auth is enabled only when both `BASE_URL` and `AUTH_SECRET` are set.
|
||||||
|
- DB/storage migrations run automatically at container startup via the shared entrypoint.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::info Related Docs
|
||||||
|
- [Environment Variables](../reference/environment-variables)
|
||||||
|
- [Auth](../configure/auth)
|
||||||
|
- [Database and Migrations](../configure/database-and-migrations)
|
||||||
|
- [Object / Blob Storage](../configure/object-blob-storage)
|
||||||
|
:::
|
||||||
|
|
||||||
## 2. Configure settings in the app UI
|
## 2. Configure settings in the app UI
|
||||||
|
|
||||||
|
|
@ -70,4 +96,8 @@ docker image rm ghcr.io/richardr1126/openreader-webui:latest || true && \
|
||||||
docker pull ghcr.io/richardr1126/openreader-webui:latest
|
docker pull ghcr.io/richardr1126/openreader-webui:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
If you use a mounted volume for `/app/docstore`, your persisted data remains after image updates.
|
||||||
|
:::
|
||||||
|
|
||||||
Visit [http://localhost:3003](http://localhost:3003) after startup.
|
Visit [http://localhost:3003](http://localhost:3003) after startup.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
title: Local Development
|
title: Local Development
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Node.js (recommended with [nvm](https://github.com/nvm-sh/nvm))
|
- Node.js (recommended with [nvm](https://github.com/nvm-sh/nvm))
|
||||||
|
|
@ -14,10 +17,21 @@ npm install -g pnpm
|
||||||
- A reachable TTS API server
|
- A reachable TTS API server
|
||||||
- [SeaweedFS](https://github.com/seaweedfs/seaweedfs) `weed` binary (required)
|
- [SeaweedFS](https://github.com/seaweedfs/seaweedfs) `weed` binary (required)
|
||||||
|
|
||||||
|
<Tabs groupId="seaweedfs-install">
|
||||||
|
<TabItem value="macos" label="macOS" default>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
brew install seaweedfs
|
brew install seaweedfs
|
||||||
```
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="linux" label="Linux">
|
||||||
|
|
||||||
|
Install the `weed` binary from the [SeaweedFS releases](https://github.com/seaweedfs/seaweedfs/releases) and ensure it is available on `PATH`.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
Optional, depending on features:
|
Optional, depending on features:
|
||||||
|
|
||||||
- [libreoffice](https://www.libreoffice.org) (required for DOCX conversion)
|
- [libreoffice](https://www.libreoffice.org) (required for DOCX conversion)
|
||||||
|
|
@ -39,7 +53,7 @@ cmake --build build -j --config Release
|
||||||
echo WHISPER_CPP_BIN="$(pwd)/build/bin/whisper-cli"
|
echo WHISPER_CPP_BIN="$(pwd)/build/bin/whisper-cli"
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note
|
:::tip
|
||||||
Set `WHISPER_CPP_BIN` in your `.env` to enable word-by-word highlighting.
|
Set `WHISPER_CPP_BIN` in your `.env` to enable word-by-word highlighting.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -66,10 +80,8 @@ cp .env.example .env
|
||||||
|
|
||||||
Then edit `.env`.
|
Then edit `.env`.
|
||||||
|
|
||||||
Auth is enabled when both are set:
|
- No auth mode: leave `BASE_URL` or `AUTH_SECRET` unset.
|
||||||
|
- Auth enabled mode: set both `BASE_URL` (typically `http://localhost:3003`) and `AUTH_SECRET` (generate with `openssl rand -base64 32`).
|
||||||
- `BASE_URL` (for local dev, typically `http://localhost:3003`)
|
|
||||||
- `AUTH_SECRET` (generate with `openssl rand -base64 32`)
|
|
||||||
|
|
||||||
Optional:
|
Optional:
|
||||||
|
|
||||||
|
|
@ -77,9 +89,12 @@ Optional:
|
||||||
- Stable S3 credentials via `S3_ACCESS_KEY_ID` and `S3_SECRET_ACCESS_KEY`
|
- Stable S3 credentials via `S3_ACCESS_KEY_ID` and `S3_SECRET_ACCESS_KEY`
|
||||||
- External S3 storage by setting `USE_EMBEDDED_WEED_MINI=false` and related S3 vars
|
- External S3 storage by setting `USE_EMBEDDED_WEED_MINI=false` and related S3 vars
|
||||||
|
|
||||||
|
:::info
|
||||||
For all environment variables, see [Environment Variables](../reference/environment-variables).
|
For all environment variables, see [Environment Variables](../reference/environment-variables).
|
||||||
For app/auth behavior, see [Auth](../configure/configuration).
|
:::
|
||||||
For storage configuration, see [Object / Blob Storage](../configure/storage-and-blob-behavior).
|
|
||||||
|
For app/auth behavior, see [Auth](../configure/auth).
|
||||||
|
For storage configuration, see [Object / Blob Storage](../configure/object-blob-storage).
|
||||||
For database mode and migrations, see [Database and Migrations](../configure/database-and-migrations).
|
For database mode and migrations, see [Database and Migrations](../configure/database-and-migrations).
|
||||||
|
|
||||||
4. Run DB migrations.
|
4. Run DB migrations.
|
||||||
|
|
@ -91,21 +106,32 @@ For database mode and migrations, see [Database and Migrations](../configure/dat
|
||||||
pnpm migrate
|
pnpm migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note
|
:::info
|
||||||
If `POSTGRES_URL` is set, migrations target Postgres; otherwise local SQLite is used. To disable automatic startup migrations, set `RUN_DRIZZLE_MIGRATIONS=false` and/or `RUN_FS_MIGRATIONS=false`. You can run storage migration manually with `pnpm migrate-fs`.
|
If `POSTGRES_URL` is set, migrations target Postgres; otherwise local SQLite is used. To disable automatic startup migrations, set `RUN_DRIZZLE_MIGRATIONS=false` and/or `RUN_FS_MIGRATIONS=false`. You can run storage migration manually with `pnpm migrate-fs`.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
5. Start the app.
|
5. Start the app.
|
||||||
|
|
||||||
|
<Tabs groupId="local-run-mode">
|
||||||
|
<TabItem value="dev" label="Dev" default>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Or build + start production mode:
|
</TabItem>
|
||||||
|
<TabItem value="prod" label="Build + Start">
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm build
|
pnpm build
|
||||||
pnpm start
|
pnpm start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
:::warning API Base Reachability
|
||||||
|
`API_BASE` must be reachable from the Next.js server process, not just your browser.
|
||||||
|
:::
|
||||||
|
|
||||||
Visit [http://localhost:3003](http://localhost:3003).
|
Visit [http://localhost:3003](http://localhost:3003).
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,24 @@
|
||||||
title: Vercel Deployment
|
title: Vercel Deployment
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
This guide covers deploying OpenReader WebUI to Vercel with external Postgres and S3-compatible object storage.
|
This guide covers deploying OpenReader WebUI to Vercel with external Postgres and S3-compatible object storage.
|
||||||
|
|
||||||
## What works on Vercel
|
## What works on Vercel
|
||||||
|
|
||||||
- Documents (PDF/EPUB/TXT/MD) work with `POSTGRES_URL` + external S3 storage.
|
- Documents (PDF/EPUB/TXT/MD) work with `POSTGRES_URL` + external S3 storage.
|
||||||
- Audiobook routes work on Node.js serverless functions using `ffmpeg-static`/`ffprobe-static`.
|
- Audiobook routes work on Node.js serverless functions using `ffmpeg-static`/`ffprobe-static`.
|
||||||
- `docx` conversion requires `soffice` (LibreOffice), which is not available in a standard Vercel runtime.
|
|
||||||
|
|
||||||
## 1. Required environment variables
|
:::warning DOCX Conversion Limitation
|
||||||
|
`docx` conversion requires `soffice` (LibreOffice), which is not available in a standard Vercel runtime.
|
||||||
|
:::
|
||||||
|
|
||||||
Set these in your Vercel project:
|
## 1. Environment Variables
|
||||||
|
|
||||||
|
<Tabs groupId="vercel-env-setup">
|
||||||
|
<TabItem value="required" label="Required" default>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
POSTGRES_URL=postgres://...
|
POSTGRES_URL=postgres://...
|
||||||
|
|
@ -26,7 +33,8 @@ S3_FORCE_PATH_STYLE=true
|
||||||
S3_PREFIX=openreader
|
S3_PREFIX=openreader
|
||||||
```
|
```
|
||||||
|
|
||||||
Optional but common:
|
</TabItem>
|
||||||
|
<TabItem value="common" label="Common Optional">
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
BASE_URL=https://your-app.vercel.app
|
BASE_URL=https://your-app.vercel.app
|
||||||
|
|
@ -36,15 +44,26 @@ NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT=true
|
||||||
NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT=true
|
NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT=true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
:::tip
|
||||||
For all variables and defaults, see [Environment Variables](../reference/environment-variables).
|
For all variables and defaults, see [Environment Variables](../reference/environment-variables).
|
||||||
|
:::
|
||||||
|
|
||||||
## 2. FFmpeg/ffprobe packaging in Vercel functions
|
## 2. FFmpeg/ffprobe packaging in Vercel functions
|
||||||
|
|
||||||
`ffmpeg-static` and `ffprobe-static` binaries must be included in function traces. This repo already does that in `next.config.ts` via `outputFileTracingIncludes` for:
|
`ffmpeg-static` and `ffprobe-static` binaries must be included in function traces. This repo already does that in `next.config.ts` via `outputFileTracingIncludes` for:
|
||||||
|
|
||||||
- `/api/audiobook(.*)`
|
- `/api/audiobook`
|
||||||
|
- `/api/audiobook/chapter`
|
||||||
|
- `/api/audiobook/status`
|
||||||
- `/api/whisper`
|
- `/api/whisper`
|
||||||
|
|
||||||
|
:::info
|
||||||
|
`serverExternalPackages` should include `ffmpeg-static` and `ffprobe-static` so package paths resolve at runtime instead of being bundled into route output.
|
||||||
|
:::
|
||||||
|
|
||||||
If you change route paths or split handlers, update `outputFileTracingIncludes` accordingly.
|
If you change route paths or split handlers, update `outputFileTracingIncludes` accordingly.
|
||||||
|
|
||||||
## 3. Function memory sizing
|
## 3. Function memory sizing
|
||||||
|
|
@ -66,7 +85,7 @@ Adjust memory per route if your files are larger or your plan differs.
|
||||||
## 4. Runtime expectations and caveats
|
## 4. Runtime expectations and caveats
|
||||||
|
|
||||||
- Audiobook APIs require S3 configuration; otherwise they return `503`.
|
- Audiobook APIs require S3 configuration; otherwise they return `503`.
|
||||||
- `better-sqlite3` remains in `serverExternalPackages` for mixed/self-host setups, but production Vercel should use `POSTGRES_URL`.
|
- For production Vercel deploys, use `POSTGRES_URL` instead of SQLite.
|
||||||
- Filesystem-to-object-store migrations run via server scripts/entrypoint (`scripts/migrate-fs-v2.mjs`), not API routes.
|
- Filesystem-to-object-store migrations run via server scripts/entrypoint (`scripts/migrate-fs-v2.mjs`), not API routes.
|
||||||
- Vercel deployments do not run `scripts/openreader-entrypoint.mjs`, so run `pnpm migrate-fs` in a controlled environment when migrating legacy filesystem data.
|
- Vercel deployments do not run `scripts/openreader-entrypoint.mjs`, so run `pnpm migrate-fs` in a controlled environment when migrating legacy filesystem data.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ const config: Config = {
|
||||||
{
|
{
|
||||||
title: 'Community',
|
title: 'Community',
|
||||||
items: [
|
items: [
|
||||||
{ label: 'Support', to: '/project/support' },
|
{ label: 'Support', to: '/project/support-and-contributing' },
|
||||||
{ label: 'GitHub Discussions', href: 'https://github.com/richardr1126/OpenReader-WebUI/discussions' },
|
{ label: 'GitHub Discussions', href: 'https://github.com/richardr1126/OpenReader-WebUI/discussions' },
|
||||||
{ label: 'Issues', href: 'https://github.com/richardr1126/OpenReader-WebUI/issues' },
|
{ label: 'Issues', href: 'https://github.com/richardr1126/OpenReader-WebUI/issues' },
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,11 @@ const sidebars: SidebarsConfig = {
|
||||||
label: 'Configure',
|
label: 'Configure',
|
||||||
items: [
|
items: [
|
||||||
'configure/tts-providers',
|
'configure/tts-providers',
|
||||||
{
|
'configure/auth',
|
||||||
type: 'doc',
|
|
||||||
id: 'configure/configuration',
|
|
||||||
label: 'Auth (Reccomended)',
|
|
||||||
},
|
|
||||||
'configure/tts-rate-limiting',
|
'configure/tts-rate-limiting',
|
||||||
'configure/database-and-migrations',
|
'configure/database-and-migrations',
|
||||||
'configure/storage-and-blob-behavior',
|
'configure/object-blob-storage',
|
||||||
|
'configure/server-library-import',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -45,7 +42,7 @@ const sidebars: SidebarsConfig = {
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
label: 'Project',
|
label: 'Project',
|
||||||
items: ['project/support', 'project/acknowledgements', 'project/license'],
|
items: ['project/support-and-contributing', 'project/acknowledgements', 'project/license'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue