docs: reorganize documentation structure and fix word highlight behavior

This commit is contained in:
Richard R 2026-02-11 06:03:51 -07:00
parent 63483e055e
commit 852092c558
30 changed files with 528 additions and 263 deletions

View file

@ -12,8 +12,9 @@ This page covers application-level configuration for provider access and authent
## Related docs ## Related docs
- For the complete variable reference: [Environment Variables](../reference/environment-variables) - For auth environment variables: [Environment Variables](../reference/environment-variables#auth-and-identity)
- 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](./object-blob-storage) - 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: [Database](./database)
- For migration behavior and commands: [Migrations](./migrations)

View file

@ -0,0 +1,26 @@
---
title: Database
---
This page covers database mode selection for OpenReader WebUI.
## Database mode
- SQLite (default): embedded DB at `docstore/sqlite3.db`; good for local/self-host single-instance setups.
- Postgres: enabled when `POSTGRES_URL` is set; recommended for production/distributed deployments.
## What the database stores
- Document and audiobook metadata/state used by server routes.
- Auth/session tables when auth is enabled.
## Related variables
- `POSTGRES_URL`
For database variable behavior, see [Environment Variables](../reference/environment-variables#database-and-object-blob-storage).
## Related docs
- [Migrations](./migrations)
- [Object / Blob Storage](./object-blob-storage)

View file

@ -1,16 +1,11 @@
--- ---
title: Database and Migrations title: Migrations
--- ---
import Tabs from '@theme/Tabs'; import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem'; import TabItem from '@theme/TabItem';
This page covers database mode selection and migration behavior for OpenReader WebUI. This page covers migration behavior for both database schema and storage data in OpenReader WebUI.
## Database mode
- SQLite (default): embedded DB at `docstore/sqlite3.db`; good for local/self-host single-instance setups.
- Postgres: enabled when `POSTGRES_URL` is set; recommended for production/distributed deployments.
## Startup migration behavior ## Startup migration behavior
@ -34,17 +29,28 @@ To skip automatic startup migrations:
- Set `RUN_DRIZZLE_MIGRATIONS=false` - Set `RUN_DRIZZLE_MIGRATIONS=false`
- Set `RUN_FS_MIGRATIONS=false` - Set `RUN_FS_MIGRATIONS=false`
Database variables are documented in [Environment Variables](../reference/environment-variables). :::warning
If you disable startup migrations, ensure your deployment process runs migrations before serving traffic.
:::
## Common project commands ## Apply migrations
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"> `pnpm migrate` applies migrations for one database target:
- Postgres when `POSTGRES_URL` is set
- SQLite when `POSTGRES_URL` is unset
You can always override the target explicitly with `--config`.
<Tabs groupId="apply-migration-commands">
<TabItem value="project-scripts" label="Project Scripts" default> <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 for one target:
# - Postgres if POSTGRES_URL is set
# - SQLite if POSTGRES_URL is unset
pnpm migrate pnpm migrate
# Run storage migration (filesystem -> S3 + DB) # Run storage migration (filesystem -> S3 + DB)
@ -52,13 +58,10 @@ pnpm migrate-fs
# Dry-run storage migration without uploading/deleting # Dry-run storage migration without uploading/deleting
pnpm migrate-fs:dry-run pnpm migrate-fs:dry-run
# Generate new migration files for both SQLite and Postgres outputs
pnpm generate
``` ```
</TabItem> </TabItem>
<TabItem value="drizzle-direct" label="Drizzle Direct (Advanced)"> <TabItem value="drizzle-direct" label="Manual Drizzle Cmd">
```bash ```bash
# Migrate SQLite # Migrate SQLite
@ -66,7 +69,34 @@ pnpm exec drizzle-kit migrate --config drizzle.config.sqlite.ts
# Migrate Postgres # Migrate Postgres
pnpm exec drizzle-kit migrate --config drizzle.config.pg.ts pnpm exec drizzle-kit migrate --config drizzle.config.pg.ts
```
</TabItem>
</Tabs>
## Generate migrations
`pnpm generate` creates migration files for both configs in one run:
- `drizzle.config.sqlite.ts`
- `drizzle.config.pg.ts`
:::note
Most users do not need to run `pnpm generate`. Use it when contributing or when you have changed Drizzle schema files and need new migration files.
:::
<Tabs groupId="generate-migration-commands">
<TabItem value="project-script" label="Project Script" default>
```bash
# Generate migration files for both SQLite and Postgres outputs
pnpm generate
```
</TabItem>
<TabItem value="drizzle-direct" label="Manual Drizzle Cmd">
```bash
# Generate SQLite migrations # Generate SQLite migrations
pnpm exec drizzle-kit generate --config drizzle.config.sqlite.ts pnpm exec drizzle-kit generate --config drizzle.config.sqlite.ts
@ -77,6 +107,8 @@ pnpm exec drizzle-kit generate --config drizzle.config.pg.ts
</TabItem> </TabItem>
</Tabs> </Tabs>
:::warning ## Related docs
If you disable startup migrations, ensure your deployment process runs migrations before serving traffic.
::: - [Database](./database)
- [Object / Blob Storage](./object-blob-storage)
- [Migration Environment Variables](../reference/environment-variables#migration-controls)

View file

@ -2,6 +2,9 @@
title: Object / Blob Storage title: Object / Blob Storage
--- ---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
This page documents storage backends, blob upload routing, and core Docker mount behavior. This page documents storage backends, blob upload routing, and core Docker mount behavior.
## Storage backends ## Storage backends
@ -9,7 +12,7 @@ This page documents storage backends, blob upload routing, and core Docker mount
- Embedded (default): SQLite metadata + embedded SeaweedFS (`weed mini`) blobs. - Embedded (default): SQLite metadata + embedded SeaweedFS (`weed mini`) blobs.
- External: 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#database-and-object-blob-storage).
## Ports ## Ports
@ -26,13 +29,22 @@ Storage variables are documented in [Environment Variables](../reference/environ
- Fallback path: `/api/documents/blob/upload/fallback` when direct upload fails/unreachable. - Fallback path: `/api/documents/blob/upload/fallback` when direct upload fails/unreachable.
- Read/download path: blob/content serving route `/api/documents/blob` (not the upload fallback route). - Read/download path: blob/content serving route `/api/documents/blob` (not the upload fallback route).
## Recommended Docker mounts ## FS / Volume Mounts
| Mount | Type | Recommended | Purpose | Example | ### App data mount
| --- | --- | --- | --- | --- |
| `/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` |
For server library mounts/import behavior, see [Server Library Import](./server-library-import). - Target: `/app/docstore`
- Recommended: yes, for persistence
- Purpose: persists SeaweedFS blob data, SQLite metadata DB, migrations, and local runtime temp state
- Mount string: `-v openreader_docstore:/app/docstore`
### Library source mount (optional)
- Target: `/app/docstore/library`
- Recommended: optional, use read-only (`:ro`)
- Purpose: exposes host files as a source for server library import
- Mount string: `-v /path/to/your/library:/app/docstore/library:ro`
- Details: [Server Library Import](./server-library-import)
## Private blob endpoint mode ## Private blob endpoint mode
@ -46,7 +58,39 @@ If `8333` is not published externally:
Without `8333`, expect higher app-server traffic because uploads/downloads go through API routes instead of direct object endpoint access. 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 Debug Commands
- In current versions, audiobook assets live in object storage (`audiobooks_v1` keyspace), not as durable files under `/app/docstore`. Audiobook assets are stored in object storage under the `audiobooks_v1` keyspace. Use these commands to inspect and download objects for debugging.
- Local filesystem usage for audiobook routes is temporary processing only.
<Tabs groupId="audiobook-storage-access-cli">
<TabItem value="aws-s3" label="AWS S3" default>
```bash
# List all audiobook objects
aws s3 ls "s3://$S3_BUCKET/$S3_PREFIX/audiobooks_v1/" --recursive
# Filter to one book id (replace <book-id>)
aws s3 ls "s3://$S3_BUCKET/$S3_PREFIX/audiobooks_v1/" --recursive | grep "<book-id>-audiobook/"
# Download one object by full key
aws s3 cp "s3://$S3_BUCKET/$S3_PREFIX/audiobooks_v1/<path>/<file>.m4b" "./audiobook.m4b"
```
</TabItem>
<TabItem value="s3-compatible" label="Embedded / MinIO / R2 / etc">
```bash
# List all audiobook objects
aws s3 ls "s3://$S3_BUCKET/$S3_PREFIX/audiobooks_v1/" --recursive --endpoint-url "$S3_ENDPOINT"
# Filter to one book id (replace <book-id>)
aws s3 ls "s3://$S3_BUCKET/$S3_PREFIX/audiobooks_v1/" --recursive --endpoint-url "$S3_ENDPOINT" | grep "<book-id>-audiobook/"
# Download one object by full key
aws s3 cp "s3://$S3_BUCKET/$S3_PREFIX/audiobooks_v1/<path>/<file>.m4b" "./audiobook.m4b" --endpoint-url "$S3_ENDPOINT"
```
Embedded default example: `S3_ENDPOINT=http://127.0.0.1:8333` (or your mapped host/port).
</TabItem>
</Tabs>

View file

@ -12,30 +12,21 @@ Server library import lets you browse files from one or more server directories
- Only selected files are imported - Only selected files are imported
- Imported files become normal OpenReader documents - Imported files become normal OpenReader documents
## Configure library roots ## FS / Volume Mounts
Library roots are resolved from environment variables: ### App data mount
- `IMPORT_LIBRARY_DIRS` (takes precedence): multiple roots separated by comma, colon, or semicolon - Target: `/app/docstore`
- `IMPORT_LIBRARY_DIR`: single root - Recommended: yes, for persistence
- Fallback when neither is set: `docstore/library` - Purpose: stores app runtime data, metadata DB, and embedded storage state
- Mount string: `-v openreader_docstore:/app/docstore`
See [Environment Variables](../reference/environment-variables#import_library_dir) for details. ### Library source mount
## Docker mount example - Target: `/app/docstore/library`
- Recommended: yes for this feature, use read-only (`:ro`)
Mount a host folder to the default library path: - Purpose: exposes host files as import candidates in Server Library Import
- Mount string: `-v /path/to/your/library:/app/docstore/library:ro`
```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 ## Import flow
@ -59,6 +50,17 @@ Imported documents are still saved to the importing user's document scope.
- `.txt` - `.txt`
- `.md`, `.mdown`, `.markdown` - `.md`, `.mdown`, `.markdown`
## Optional: Configure Library Roots
You only need this when the default mounted path is not what you want.
By default, OpenReader uses `docstore/library` as the import root. You can override that with environment variables:
- `IMPORT_LIBRARY_DIRS` (takes precedence): multiple roots separated by comma, colon, or semicolon
- `IMPORT_LIBRARY_DIR`: single root
See [Environment Variables](../reference/environment-variables#library-import) for variable details.
## Notes ## Notes
- Library listing is capped per request (up to 10,000 files). - Library listing is capped per request (up to 10,000 files).

View file

@ -0,0 +1,40 @@
---
title: Custom OpenAI
---
Use any custom OpenAI-compatible TTS service with OpenReader.
Use this integration when your endpoint is not directly covered by built-in dropdown defaults.
## Provider
- Provider: `Custom OpenAI-Like`
- `API_BASE`: required (your service base URL)
- `API_KEY`: set if required by your service
Custom providers should expose:
- `GET /v1/audio/voices`
- `POST /v1/audio/speech`
## OpenReader setup
1. In OpenReader Settings, choose provider `Custom OpenAI-Like`.
2. Set `API_BASE` to your service base URL (typically ending with `/v1`).
3. Set `API_KEY` if your service requires authentication.
4. Choose a model and voice supported by your backend.
## Notes
:::warning Compatibility required
Custom providers must implement OpenAI-compatible TTS endpoints, including `GET /v1/audio/voices` and `POST /v1/audio/speech`.
:::
:::info Voice troubleshooting
If voices do not load, verify the `/v1/audio/voices` response shape and that the endpoint is reachable from the OpenReader server.
:::
## References
- [TTS Providers](../tts-providers)
- [TTS Environment Variables](../../reference/environment-variables#tts-provider-and-request-behavior)

View file

@ -0,0 +1,33 @@
---
title: Deepinfra
---
Use Deepinfra as a hosted OpenAI-compatible TTS provider.
## Provider
- Provider: `Deepinfra`
- Default endpoint: `https://api.deepinfra.com/v1/openai` (auto-filled)
- `API_KEY`: required for authenticated DeepInfra usage
## OpenReader setup
1. In OpenReader Settings, choose provider `Deepinfra`.
2. Keep the default `API_BASE`.
3. Set `API_KEY`.
4. Choose your model and voice.
## Notes
:::tip Built-in endpoint
`Deepinfra` is a built-in provider, so OpenReader auto-fills the default `API_BASE`.
:::
:::info Model support
DeepInfra exposes multiple TTS models, including Kokoro-family options.
:::
## References
- [TTS Providers](../tts-providers)
- [TTS Environment Variables](../../reference/environment-variables#tts-provider-and-request-behavior)

View file

@ -0,0 +1,68 @@
---
title: Kokoro-FastAPI
---
You can run the Kokoro TTS API server directly with Docker.
:::warning
For Kokoro issues and support, use the upstream repository: [remsky/Kokoro-FastAPI](https://github.com/remsky/Kokoro-FastAPI).
:::
## Provider
- Provider: `Custom OpenAI-Like`
- Typical model: `Kokoro`
- `API_BASE`: required (typically your Kokoro URL ending with `/v1`)
- `API_KEY`: set only if your deployment requires one
## Run Kokoro (CPU)
```bash
docker run -d \
--name kokoro-tts \
--restart unless-stopped \
-p 8880:8880 \
-e ONNX_NUM_THREADS=8 \
-e ONNX_INTER_OP_THREADS=4 \
-e ONNX_EXECUTION_MODE=parallel \
-e ONNX_OPTIMIZATION_LEVEL=all \
-e ONNX_MEMORY_PATTERN=true \
-e ONNX_ARENA_EXTEND_STRATEGY=kNextPowerOfTwo \
-e API_LOG_LEVEL=DEBUG \
ghcr.io/remsky/kokoro-fastapi-cpu:v0.2.4
```
## Run Kokoro (GPU)
```bash
docker run -d \
--name kokoro-tts \
--gpus all \
--user 1001:1001 \
--restart unless-stopped \
-p 8880:8880 \
-e USE_GPU=true \
-e PYTHONUNBUFFERED=1 \
-e API_LOG_LEVEL=DEBUG \
ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.4
```
## OpenReader setup
1. Start Kokoro using either the CPU or GPU image.
2. In OpenReader Settings, choose provider `Custom OpenAI-Like`.
3. Set `API_BASE` to your Kokoro endpoint (for Docker Compose, commonly `http://kokoro-tts:8880/v1`).
4. Set `API_KEY` only if your deployment requires one.
5. Choose model `Kokoro`.
## Notes
:::tip Runtime guidance
GPU mode requires NVIDIA Docker support and is best on NVIDIA hardware. CPU mode is a good default on Apple Silicon and modern x86 CPUs.
:::
## References
- [remsky/Kokoro-FastAPI](https://github.com/remsky/Kokoro-FastAPI)
- [TTS Providers](../tts-providers)
- [TTS Environment Variables](../../reference/environment-variables#tts-provider-and-request-behavior)

View file

@ -0,0 +1,33 @@
---
title: OpenAI
---
Use OpenAI directly as an OpenAI-compatible TTS provider.
## Provider
- Provider: `OpenAI`
- Default endpoint: `https://api.openai.com/v1` (auto-filled)
- `API_KEY`: required for OpenAI access
## OpenReader setup
1. In OpenReader Settings, choose provider `OpenAI`.
2. Keep the default `API_BASE`.
3. Set `API_KEY`.
4. Choose your model and voice.
## Notes
:::tip Built-in endpoint
`OpenAI` is a built-in provider, so OpenReader auto-fills the default `API_BASE`.
:::
:::info Server-side requests
OpenReader sends TTS requests from the server runtime, not directly from the browser.
:::
## References
- [TTS Providers](../tts-providers)
- [TTS Environment Variables](../../reference/environment-variables#tts-provider-and-request-behavior)

View file

@ -0,0 +1,36 @@
---
title: Orpheus-FastAPI
---
Use Orpheus-FastAPI as an OpenAI-compatible TTS backend for OpenReader.
## Provider
- Provider: `Custom OpenAI-Like`
- Typical model: `Orpheus`
- `API_BASE`: required (usually your Orpheus URL ending with `/v1`)
- `API_KEY`: set only if your deployment requires one
## OpenReader setup
1. Start your Orpheus-FastAPI server.
2. In OpenReader Settings, choose provider `Custom OpenAI-Like`.
3. Set `API_BASE` to your Orpheus base URL (typically ending with `/v1`).
4. Set `API_KEY` only if your Orpheus deployment requires one.
5. Choose model `Orpheus` (or another model exposed by your deployment).
## Notes
:::info OpenAI-compatible API
OpenReader expects OpenAI-compatible audio endpoints when using Orpheus through `Custom OpenAI-Like`.
:::
:::tip Endpoint shape
Use an `API_BASE` that points at the Orpheus API root (typically ending with `/v1`).
:::
## References
- [Lex-au/Orpheus-FastAPI](https://github.com/Lex-au/Orpheus-FastAPI)
- [TTS Providers](../tts-providers)
- [TTS Environment Variables](../../reference/environment-variables#tts-provider-and-request-behavior)

View file

@ -64,13 +64,16 @@ Custom providers should expose:
TTS requests are sent from the Next.js server, not directly from the browser. `API_BASE` must be reachable from the server runtime. TTS requests are sent from the Next.js server, not directly from the browser. `API_BASE` must be reachable from the server runtime.
::: :::
## Related Guides ## Provider Guides
- [Environment Variables](../reference/environment-variables) - [Kokoro-FastAPI](./tts-provider-guides/kokoro-fastapi)
- [Orpheus-FastAPI](./tts-provider-guides/orpheus-fastapi)
- [DeepInfra](./tts-provider-guides/deepinfra)
- [OpenAI](./tts-provider-guides/openai)
- [Custom OpenAI-Like](./tts-provider-guides/custom-openai)
## Related Configuration
- [TTS Environment Variables](../reference/environment-variables#tts-provider-and-request-behavior)
- [TTS Rate Limiting](./tts-rate-limiting) - [TTS Rate Limiting](./tts-rate-limiting)
- [Auth](./auth) - [Auth](./auth)
- [Kokoro-FastAPI](../integrations/kokoro-fastapi)
- [Orpheus-FastAPI](../integrations/orpheus-fastapi)
- [Deepinfra](../integrations/deepinfra)
- [OpenAI](../integrations/openai)
- [Custom OpenAI](../integrations/custom-openai)

View file

@ -46,6 +46,6 @@ IP backstop daily limits:
## Related docs ## Related docs
- Full variable list: [Environment Variables](../reference/environment-variables) - TTS/rate-limit environment variables: [Environment Variables](../reference/environment-variables#tts-provider-and-request-behavior)
- Auth configuration: [Auth](./auth) - Auth configuration: [Auth](./auth)
- Provider setup: [TTS Providers](./tts-providers) - Provider setup: [TTS Providers](./tts-providers)

View file

@ -95,7 +95,8 @@ For all environment variables, see [Environment Variables](../reference/environm
For app/auth behavior, see [Auth](../configure/auth). For app/auth behavior, see [Auth](../configure/auth).
For storage configuration, see [Object / Blob Storage](../configure/object-blob-storage). 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, see [Database](../configure/database).
For migration behavior and commands, see [Migrations](../configure/migrations).
4. Run DB migrations. 4. Run DB migrations.

View file

@ -2,9 +2,6 @@
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
@ -18,8 +15,7 @@ This guide covers deploying OpenReader WebUI to Vercel with external Postgres an
## 1. Environment Variables ## 1. Environment Variables
<Tabs groupId="vercel-env-setup"> Recommended production setup (auth enabled):
<TabItem value="required" label="Required" default>
```bash ```bash
POSTGRES_URL=postgres://... POSTGRES_URL=postgres://...
@ -28,24 +24,42 @@ S3_ACCESS_KEY_ID=...
S3_SECRET_ACCESS_KEY=... S3_SECRET_ACCESS_KEY=...
S3_BUCKET=... S3_BUCKET=...
S3_REGION=us-east-1 S3_REGION=us-east-1
S3_ENDPOINT=https://...
S3_FORCE_PATH_STYLE=true
S3_PREFIX=openreader S3_PREFIX=openreader
```
</TabItem>
<TabItem value="common" label="Common Optional">
```bash
BASE_URL=https://your-app.vercel.app BASE_URL=https://your-app.vercel.app
AUTH_SECRET=... AUTH_SECRET=...
NEXT_PUBLIC_NODE_ENV=production NEXT_PUBLIC_NODE_ENV=production
NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT=true # Optional client/runtime feature overrides:
NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT=true # NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT=false
# NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT=true
# Optional (non-AWS S3-compatible providers):
# S3_ENDPOINT=https://...
# S3_FORCE_PATH_STYLE=true
``` ```
</TabItem> :::info `NEXT_PUBLIC_*` feature flags
</Tabs> - `NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT=false`: hides audiobook export UI entry points.
- `NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT=true`: enables word-highlight UI and timestamp alignment requests.
:::
:::warning `NEXT_PUBLIC_NODE_ENV` behavior
Use `NEXT_PUBLIC_NODE_ENV=production` on Vercel unless you explicitly want dev-oriented client behavior.
With `production`:
- Footer is shown in the app shell
- DOCX upload/conversion option is hidden
- Default provider/model behavior is production-oriented
- DeepInfra model picker is restricted without an API key
- Privacy modal shows hosted-service/operator wording
- Dev-only destructive document actions are hidden
With unset/non-`production`, the inverse dev behavior applies.
Full details: [Environment Variables](../reference/environment-variables#next_public_node_env).
:::
:::warning Auth recommendation
For internet-exposed Vercel deployments, set both `BASE_URL` and `AUTH_SECRET`. Running without auth is possible, but not recommended for public environments.
:::
:::tip :::tip
For all variables and defaults, see [Environment Variables](../reference/environment-variables). For all variables and defaults, see [Environment Variables](../reference/environment-variables).

View file

@ -11,7 +11,7 @@ import TabItem from '@theme/TabItem';
- A TTS API server that OpenReader can reach (Kokoro-FastAPI, Orpheus-FastAPI, DeepInfra, OpenAI, or equivalent) - A TTS API server that OpenReader can reach (Kokoro-FastAPI, Orpheus-FastAPI, DeepInfra, OpenAI, or equivalent)
:::note :::note
If you have suitable hardware, you can run Kokoro locally with Docker. See [Kokoro-FastAPI](../integrations/kokoro-fastapi). If you have suitable hardware, you can run Kokoro locally with Docker. See [Kokoro-FastAPI](./configure/tts-provider-guides/kokoro-fastapi).
::: :::
## 1. Start the Docker container ## 1. Start the Docker container
@ -75,10 +75,11 @@ If `8333` is not reachable from the browser, direct presigned access is unavaila
::: :::
:::info Related Docs :::info Related Docs
- [Environment Variables](../reference/environment-variables) - [Environment Variables](./reference/environment-variables)
- [Auth](../configure/auth) - [Auth](./configure/auth)
- [Database and Migrations](../configure/database-and-migrations) - [Database](./configure/database)
- [Object / Blob Storage](../configure/object-blob-storage) - [Object / Blob Storage](./configure/object-blob-storage)
- [Migrations](./configure/migrations)
::: :::
## 2. Configure settings in the app UI ## 2. Configure settings in the app UI

View file

@ -1,28 +0,0 @@
---
title: Custom OpenAI
---
Use any custom OpenAI-compatible TTS service with OpenReader.
Use this integration when your endpoint is not directly covered by built-in dropdown defaults.
## Compatibility requirements
Your provider should expose:
- `GET /v1/audio/voices`
- `POST /v1/audio/speech`
## OpenReader setup
1. In OpenReader settings, choose provider `Custom OpenAI-Like`.
2. Pick model `Kokoro`, `Orpheus`, or `Other` as appropriate.
3. Set `API_BASE` to your service base URL.
4. Set `API_KEY` if required by your service.
5. Choose voice.
## Notes
- `API_BASE` is required for this provider path because OpenReader cannot infer your custom host.
- If voices do not load, verify the `/v1/audio/voices` response format.
- For variable details, see [Environment Variables](../reference/environment-variables).

View file

@ -1,19 +0,0 @@
---
title: Deepinfra
---
Use Deepinfra as a hosted OpenAI-compatible TTS provider.
## OpenReader setup
1. In OpenReader settings, choose provider `Deepinfra`.
2. Leave `API_BASE` unset unless you want to override the default endpoint.
- Default value: `https://api.deepinfra.com/v1/openai`
3. Set `API_KEY` to your Deepinfra API key if needed.
4. Choose model and voice.
## Notes
- `Deepinfra` is a built-in provider in the dropdown, so `API_BASE` is usually not required.
- Deepinfra supports multiple TTS models, including Kokoro-family options.
- For variable details, see [Environment Variables](../reference/environment-variables).

View file

@ -1,49 +0,0 @@
---
title: Kokoro-FastAPI
---
You can run the Kokoro TTS API server directly with Docker.
:::warning
For Kokoro issues and support, use the upstream repository: [remsky/Kokoro-FastAPI](https://github.com/remsky/Kokoro-FastAPI).
:::
## CPU image
```bash
docker run -d \
--name kokoro-tts \
--restart unless-stopped \
-p 8880:8880 \
-e ONNX_NUM_THREADS=8 \
-e ONNX_INTER_OP_THREADS=4 \
-e ONNX_EXECUTION_MODE=parallel \
-e ONNX_OPTIMIZATION_LEVEL=all \
-e ONNX_MEMORY_PATTERN=true \
-e ONNX_ARENA_EXTEND_STRATEGY=kNextPowerOfTwo \
-e API_LOG_LEVEL=DEBUG \
ghcr.io/remsky/kokoro-fastapi-cpu:v0.2.4
```
## GPU image
```bash
docker run -d \
--name kokoro-tts \
--gpus all \
--user 1001:1001 \
--restart unless-stopped \
-p 8880:8880 \
-e USE_GPU=true \
-e PYTHONUNBUFFERED=1 \
-e API_LOG_LEVEL=DEBUG \
ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.4
```
## OpenReader integration notes
- In OpenReader settings, choose provider `Custom OpenAI-Like` and model `Kokoro`.
- Set OpenReader `API_BASE` to your Kokoro endpoint (for Docker Compose, commonly `http://kokoro-tts:8880/v1`).
- `API_BASE` is needed here because Kokoro is used via the custom provider path, not a built-in provider endpoint.
- GPU mode requires NVIDIA Docker support and is best on NVIDIA hardware.
- CPU mode works best on Apple Silicon or modern x86 CPUs.

View file

@ -1,18 +0,0 @@
---
title: OpenAI
---
Use OpenAI directly as an OpenAI-compatible TTS provider.
## OpenReader setup
1. In OpenReader settings, choose provider `OpenAI`.
2. Leave `API_BASE` unset unless you want to override the default `https://api.openai.com/v1`.
3. Set `API_KEY` to your OpenAI API key.
4. Choose model and voice.
## Notes
- `OpenAI` is a built-in provider in the dropdown, so `API_BASE` is usually not required.
- OpenReader routes TTS calls through its server API.
- For variable details, see [Environment Variables](../reference/environment-variables).

View file

@ -1,23 +0,0 @@
---
title: Orpheus-FastAPI
---
Use Orpheus-FastAPI as an OpenAI-compatible TTS backend for OpenReader.
## Upstream project
- [Lex-au/Orpheus-FastAPI](https://github.com/Lex-au/Orpheus-FastAPI)
## OpenReader setup
1. Start your Orpheus-FastAPI server.
2. In OpenReader settings, choose provider `Custom OpenAI-Like` and model `Orpheus`.
3. Set OpenReader `API_BASE` to your Orpheus base URL (typically ending with `/v1`).
4. Set `API_KEY` if your Orpheus deployment requires one.
5. Choose voice.
## Notes
- `API_BASE` is needed here because Orpheus is configured through the custom provider path.
- OpenReader expects OpenAI-compatible audio endpoints.
- For variable details, see [Environment Variables](../reference/environment-variables).

View file

@ -31,15 +31,16 @@ It supports multiple TTS providers including OpenAI, DeepInfra, and custom OpenA
- 🎨 **Customizable Experience** - 🎨 **Customizable Experience**
- Theme, TTS, and document handling controls - Theme, TTS, and document handling controls
## 🚀 Start Here ## 🧭 Key Docs
- [Docker Quick Start](./start-here/docker-quick-start) - [Docker Quick Start](./docker-quick-start)
- [Vercel Deployment](./start-here/vercel-deployment) - [Local Development](./deploy/local-development)
- [Local Development](./start-here/local-development) - [Vercel Deployment](./deploy/vercel-deployment)
- [Environment Variables](./reference/environment-variables) - [Environment Variables](./reference/environment-variables)
- [Auth](./configure/auth) - [Auth](./configure/auth)
- [Database and Migrations](./configure/database-and-migrations) - [Database](./configure/database)
- [Object / Blob Storage](./configure/object-blob-storage) - [Object / Blob Storage](./configure/object-blob-storage)
- [Migrations](./configure/migrations)
- [Server Library Import](./configure/server-library-import) - [Server Library Import](./configure/server-library-import)
- [TTS Providers](./configure/tts-providers) - [TTS Providers](./configure/tts-providers)

View file

@ -9,9 +9,9 @@ This is the single reference page for OpenReader WebUI environment variables.
| Variable | Area | Default | When to set | | Variable | Area | Default | When to set |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| `NEXT_PUBLIC_NODE_ENV` | Runtime mode | `development` | Set `production` for production builds | | `NEXT_PUBLIC_NODE_ENV` | Runtime mode | treated as `development` unless `production` | Set `production` for production client behavior |
| `NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT` | Client feature flags | `true` unless set to `false` | Disable audiobook export UI in any environment | | `NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT` | Client feature flags | `true` unless set to `false` | Set `false` to hide audiobook export UI |
| `NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT` | Client feature flags | `true` in dev, `false` in production | Force-enable word highlight UI in production | | `NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT` | Client feature flags | `false` unless set to `true` | Set `true` to enable word highlight + alignment |
| `API_BASE` | TTS provider | none | Point to your OpenAI-compatible TTS base URL | | `API_BASE` | TTS provider | none | Point to your OpenAI-compatible TTS base URL |
| `API_KEY` | TTS provider | `none` fallback in TTS route | Set when provider requires auth | | `API_KEY` | TTS provider | `none` fallback in TTS route | Set when provider requires auth |
| `TTS_CACHE_MAX_SIZE_BYTES` | TTS caching | `268435456` (256 MB) | Tune in-memory TTS cache size | | `TTS_CACHE_MAX_SIZE_BYTES` | TTS caching | `268435456` (256 MB) | Tune in-memory TTS cache size |
@ -52,12 +52,23 @@ This is the single reference page for OpenReader WebUI environment variables.
## Detailed Reference ## Detailed Reference
## Client Runtime and Feature Flags
### NEXT_PUBLIC_NODE_ENV ### NEXT_PUBLIC_NODE_ENV
Controls development vs production behavior in client/server code paths. Controls development vs production behavior in client/server code paths.
- Typical values: `development`, `production` - Typical values: `development`, `production`
- In production builds, set `production` - OpenReader `isDev` checks rely on this variable directly
- If this is not `production`, OpenReader treats the client as development mode
- In deployed environments, set `NEXT_PUBLIC_NODE_ENV=production` explicitly for predictable production behavior
- Affects:
- Footer visibility in the app shell
- DOCX upload/conversion availability in upload UI
- Default provider/model behavior for first-run TTS config
- DeepInfra model picker restrictions when no API key is set
- Privacy modal wording (hosted-service vs local/dev wording)
- Dev-only destructive document actions in settings
### NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT ### NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT
@ -65,14 +76,20 @@ Controls whether audiobook export UI/actions are shown in the client.
- Default behavior: enabled unless explicitly set to `false` - Default behavior: enabled unless explicitly set to `false`
- Applies in both development and production - Applies in both development and production
- Affects export entry points in PDF/EPUB pages and document settings UI
### NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT ### NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT
Controls word-by-word highlighting UI in production builds. Controls word-by-word highlighting UI and timestamp-alignment behavior.
- Development default: enabled - Default behavior: disabled unless set to `true`
- Production default: disabled unless set to `true` - Applies in both development and production
- Requires working timestamp generation (for example `WHISPER_CPP_BIN`) - Requires working timestamp generation (for example `WHISPER_CPP_BIN`)
- Affects:
- Word-highlight toggles in document settings
- Alignment requests during TTS playback
## TTS Provider and Request Behavior
### API_BASE ### API_BASE
@ -80,6 +97,7 @@ Base URL for OpenAI-compatible TTS API requests.
- Example: `http://host.docker.internal:8880/v1` - Example: `http://host.docker.internal:8880/v1`
- Can be overridden per request from UI settings - Can be overridden per request from UI settings
- Related docs: [TTS Providers](../configure/tts-providers)
### API_KEY ### API_KEY
@ -87,6 +105,7 @@ Default API key for TTS provider requests.
- Example: `none` or your provider token - Example: `none` or your provider token
- Can be overridden by request headers from app settings - Can be overridden by request headers from app settings
- Related docs: [TTS Providers](../configure/tts-providers)
### TTS_CACHE_MAX_SIZE_BYTES ### TTS_CACHE_MAX_SIZE_BYTES
@ -156,12 +175,15 @@ Authenticated IP backstop daily character limit.
- Default: `1000000` - Default: `1000000`
## Auth and Identity
### BASE_URL ### BASE_URL
External base URL for this OpenReader instance. External base URL for this OpenReader instance.
- Required with `AUTH_SECRET` to enable auth - Required with `AUTH_SECRET` to enable auth
- Example: `http://localhost:3003` or `https://reader.example.com` - Example: `http://localhost:3003` or `https://reader.example.com`
- Related docs: [Auth](../configure/auth)
### AUTH_SECRET ### AUTH_SECRET
@ -169,6 +191,7 @@ Secret key used by auth/session handling.
- Required with `BASE_URL` to enable auth - Required with `BASE_URL` to enable auth
- Generate with `openssl rand -base64 32` - Generate with `openssl rand -base64 32`
- Related docs: [Auth](../configure/auth)
### AUTH_TRUSTED_ORIGINS ### AUTH_TRUSTED_ORIGINS
@ -176,6 +199,7 @@ Additional allowed origins for auth requests.
- Comma-separated list - Comma-separated list
- `BASE_URL` origin is always trusted automatically - `BASE_URL` origin is always trusted automatically
- Related docs: [Auth](../configure/auth)
### GITHUB_CLIENT_ID ### GITHUB_CLIENT_ID
@ -196,6 +220,9 @@ Controls Better Auth rate limiting.
- Default behavior: auth-layer rate limiting enabled - Default behavior: auth-layer rate limiting enabled
- Set to `true` to disable auth-layer rate limiting - Set to `true` to disable auth-layer rate limiting
- This does not affect TTS character rate limiting - This does not affect TTS character rate limiting
- Related docs: [Auth](../configure/auth)
## Database and Object Blob Storage
### POSTGRES_URL ### POSTGRES_URL
@ -203,6 +230,7 @@ Switches metadata/auth storage from SQLite to Postgres.
- Unset: SQLite at `docstore/sqlite3.db` - Unset: SQLite at `docstore/sqlite3.db`
- Set: Postgres mode - Set: Postgres mode
- Related docs: [Database](../configure/database)
### USE_EMBEDDED_WEED_MINI ### USE_EMBEDDED_WEED_MINI
@ -210,18 +238,21 @@ Controls embedded SeaweedFS startup.
- Default behavior: treated as enabled when unset - Default behavior: treated as enabled when unset
- Set `false` to rely on external S3-compatible storage - Set `false` to rely on external S3-compatible storage
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
### WEED_MINI_DIR ### WEED_MINI_DIR
Data directory for embedded SeaweedFS (`weed mini`). Data directory for embedded SeaweedFS (`weed mini`).
- Default: `docstore/seaweedfs` - Default: `docstore/seaweedfs`
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
### WEED_MINI_WAIT_SEC ### WEED_MINI_WAIT_SEC
Maximum seconds to wait for embedded SeaweedFS startup. Maximum seconds to wait for embedded SeaweedFS startup.
- Default: `20` - Default: `20`
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
### S3_ACCESS_KEY_ID ### S3_ACCESS_KEY_ID
@ -229,6 +260,7 @@ Access key for S3-compatible storage.
- Auto-generated in embedded mode if unset - Auto-generated in embedded mode if unset
- Set explicitly for stable credentials or external providers - Set explicitly for stable credentials or external providers
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
### S3_SECRET_ACCESS_KEY ### S3_SECRET_ACCESS_KEY
@ -236,6 +268,7 @@ Secret key for S3-compatible storage.
- Auto-generated in embedded mode if unset - Auto-generated in embedded mode if unset
- Set explicitly for stable credentials or external providers - Set explicitly for stable credentials or external providers
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
### S3_BUCKET ### S3_BUCKET
@ -243,12 +276,14 @@ Bucket name used for document blobs.
- Default in embedded mode: `openreader-documents` - Default in embedded mode: `openreader-documents`
- Required for external S3-compatible storage - Required for external S3-compatible storage
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
### S3_REGION ### S3_REGION
Region used by the S3 client. Region used by the S3 client.
- Default in embedded mode: `us-east-1` - Default in embedded mode: `us-east-1`
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
### S3_ENDPOINT ### S3_ENDPOINT
@ -257,6 +292,7 @@ Endpoint URL for S3-compatible storage.
- In embedded mode, defaults to `http://<BASE_URL host>:8333` (or detected host) - In embedded mode, defaults to `http://<BASE_URL host>:8333` (or detected host)
- For AWS S3, usually leave unset - For AWS S3, usually leave unset
- For MinIO/SeaweedFS/R2/B2-style APIs, typically set explicitly - For MinIO/SeaweedFS/R2/B2-style APIs, typically set explicitly
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
### S3_FORCE_PATH_STYLE ### S3_FORCE_PATH_STYLE
@ -264,12 +300,16 @@ Path-style S3 addressing toggle.
- Default in embedded mode: `true` - Default in embedded mode: `true`
- Set according to provider requirements - Set according to provider requirements
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
### S3_PREFIX ### S3_PREFIX
Prefix prepended to stored object keys. Prefix prepended to stored object keys.
- Default: `openreader` - Default: `openreader`
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
## Migration Controls
### RUN_DRIZZLE_MIGRATIONS ### RUN_DRIZZLE_MIGRATIONS
@ -277,6 +317,7 @@ Controls startup migration execution in shared entrypoint.
- Default: `true` - Default: `true`
- Set `false` to skip automatic startup Drizzle schema migrations - Set `false` to skip automatic startup Drizzle schema migrations
- Related docs: [Migrations](../configure/migrations), [Database](../configure/database)
### RUN_FS_MIGRATIONS ### RUN_FS_MIGRATIONS
@ -285,6 +326,9 @@ Controls startup filesystem-to-object-store migration execution in shared entryp
- Default: `true` - Default: `true`
- Runs `scripts/migrate-fs-v2.mjs` at startup after DB migrations - Runs `scripts/migrate-fs-v2.mjs` at startup after DB migrations
- Set `false` to skip automatic storage migration pass - Set `false` to skip automatic storage migration pass
- Related docs: [Migrations](../configure/migrations), [Database](../configure/database), [Object / Blob Storage](../configure/object-blob-storage)
## Library Import
### IMPORT_LIBRARY_DIR ### IMPORT_LIBRARY_DIR
@ -292,6 +336,7 @@ Single directory root for server library import.
- Used when `IMPORT_LIBRARY_DIRS` is unset - Used when `IMPORT_LIBRARY_DIRS` is unset
- Default fallback root: `docstore/library` - Default fallback root: `docstore/library`
- Related docs: [Server Library Import](../configure/server-library-import)
### IMPORT_LIBRARY_DIRS ### IMPORT_LIBRARY_DIRS
@ -299,6 +344,9 @@ Multiple library roots for server library import.
- Separator: comma, colon, or semicolon - Separator: comma, colon, or semicolon
- Takes precedence over `IMPORT_LIBRARY_DIR` - Takes precedence over `IMPORT_LIBRARY_DIR`
- Related docs: [Server Library Import](../configure/server-library-import)
## Audio Tooling and Alignment
### WHISPER_CPP_BIN ### WHISPER_CPP_BIN

View file

@ -98,7 +98,7 @@ const config: Config = {
{ {
title: 'Community', title: 'Community',
items: [ items: [
{ label: 'Support', to: '/project/support-and-contributing' }, { label: 'Support', to: '/about/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' },
], ],

View file

@ -3,10 +3,50 @@ import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';
const sidebars: SidebarsConfig = { const sidebars: SidebarsConfig = {
tutorialSidebar: [ tutorialSidebar: [
'intro', 'intro',
{
type: 'doc',
id: 'docker-quick-start',
label: '🐳 Docker Quick Start',
},
{ {
type: 'category', type: 'category',
label: 'Start Here', label: '⚙️ Configure',
items: ['start-here/docker-quick-start', 'start-here/vercel-deployment', 'start-here/local-development'], items: [
{
type: 'category',
label: '🔊 TTS Providers',
link: {
type: 'doc',
id: 'configure/tts-providers',
},
items: [
'configure/tts-provider-guides/kokoro-fastapi',
'configure/tts-provider-guides/orpheus-fastapi',
'configure/tts-provider-guides/deepinfra',
'configure/tts-provider-guides/openai',
'configure/tts-provider-guides/custom-openai',
],
},
{
type: 'doc',
id: 'configure/auth',
label: '🔐 Auth',
},
{
type: 'doc',
id: 'configure/server-library-import',
label: '📥 Server Library Import',
},
'configure/tts-rate-limiting',
'configure/database',
'configure/object-blob-storage',
'configure/migrations',
],
},
{
type: 'category',
label: '🚀 Deploy',
items: ['deploy/local-development', 'deploy/vercel-deployment'],
}, },
{ {
type: 'category', type: 'category',
@ -18,31 +58,8 @@ const sidebars: SidebarsConfig = {
}, },
{ {
type: 'category', type: 'category',
label: 'Configure', label: 'About',
items: [ items: ['about/support-and-contributing', 'about/acknowledgements', 'about/license'],
'configure/tts-providers',
'configure/auth',
'configure/tts-rate-limiting',
'configure/database-and-migrations',
'configure/object-blob-storage',
'configure/server-library-import',
],
},
{
type: 'category',
label: 'Integrations',
items: [
'integrations/kokoro-fastapi',
'integrations/orpheus-fastapi',
'integrations/deepinfra',
'integrations/openai',
'integrations/custom-openai',
],
},
{
type: 'category',
label: 'Project',
items: ['project/support-and-contributing', 'project/acknowledgements', 'project/license'],
}, },
], ],
}; };

View file

@ -11,9 +11,8 @@ import { useParams } from 'next/navigation';
import type { TTSAudiobookChapter } from '@/types/tts'; import type { TTSAudiobookChapter } from '@/types/tts';
import type { AudiobookGenerationSettings } from '@/types/client'; import type { AudiobookGenerationSettings } from '@/types/client';
const isDev = process.env.NEXT_PUBLIC_NODE_ENV !== 'production' || process.env.NODE_ENV == null;
const canExportAudiobook = process.env.NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT !== 'false'; const canExportAudiobook = process.env.NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT !== 'false';
const canWordHighlight = isDev || process.env.NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT === 'true'; const canWordHighlight = process.env.NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT === 'true';
const viewTypeTextMapping = [ const viewTypeTextMapping = [
{ id: 'single', name: 'Single Page' }, { id: 'single', name: 'Single Page' },

View file

@ -99,6 +99,7 @@ interface SetTextOptions {
const CONTINUATION_LOOKAHEAD = 600; const CONTINUATION_LOOKAHEAD = 600;
const SENTENCE_ENDING = /[.?!…]["'”’)\]]*\s*$/; const SENTENCE_ENDING = /[.?!…]["'”’)\]]*\s*$/;
const wordHighlightFeatureEnabled = process.env.NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT === 'true';
// Tiny silent WAV used to unlock HTML5 audio on iOS/Safari. // Tiny silent WAV used to unlock HTML5 audio on iOS/Safari.
const SILENT_WAV_DATA_URI = const SILENT_WAV_DATA_URI =
@ -857,8 +858,9 @@ export function TTSProvider({ children }: { children: ReactNode }): ReactElement
*/ */
const getAudio = useCallback(async (sentence: string, preload = false): Promise<TTSAudioBuffer | undefined> => { const getAudio = useCallback(async (sentence: string, preload = false): Promise<TTSAudioBuffer | undefined> => {
const alignmentEnabledForCurrentDoc = const alignmentEnabledForCurrentDoc =
(!isEPUB && pdfHighlightEnabled && pdfWordHighlightEnabled) || wordHighlightFeatureEnabled &&
(isEPUB && epubHighlightEnabled && epubWordHighlightEnabled); ((!isEPUB && pdfHighlightEnabled && pdfWordHighlightEnabled) ||
(isEPUB && epubHighlightEnabled && epubWordHighlightEnabled));
// Helper to ensure we have an alignment for a given // Helper to ensure we have an alignment for a given
// sentence/audio pair, even when the audio itself is // sentence/audio pair, even when the audio itself is
// served from the local cache. // served from the local cache.

View file

@ -1,6 +1,7 @@
import type { DocumentListState } from '@/types/documents'; import type { DocumentListState } from '@/types/documents';
const isDev = process.env.NEXT_PUBLIC_NODE_ENV !== 'production' || process.env.NODE_ENV == null; const isDev = process.env.NEXT_PUBLIC_NODE_ENV !== 'production' || process.env.NODE_ENV == null;
const wordHighlightEnabledByDefault = process.env.NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT === 'true';
export type ViewType = 'single' | 'dual' | 'scroll'; export type ViewType = 'single' | 'dual' | 'scroll';
@ -53,9 +54,9 @@ export const APP_CONFIG_DEFAULTS: AppConfigValues = {
savedVoices: {}, savedVoices: {},
smartSentenceSplitting: true, smartSentenceSplitting: true,
pdfHighlightEnabled: true, pdfHighlightEnabled: true,
pdfWordHighlightEnabled: isDev, pdfWordHighlightEnabled: wordHighlightEnabledByDefault,
epubHighlightEnabled: true, epubHighlightEnabled: true,
epubWordHighlightEnabled: isDev, epubWordHighlightEnabled: wordHighlightEnabledByDefault,
firstVisit: false, firstVisit: false,
documentListState: { documentListState: {
sortBy: 'name', sortBy: 'name',