docs: snapshot v2.1.1
This commit is contained in:
parent
6d33de83c2
commit
4505684108
24 changed files with 1728 additions and 0 deletions
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
title: Acknowledgements
|
||||
---
|
||||
|
||||
This project is built with support from the following open-source projects and tools:
|
||||
|
||||
- [Kokoro-82M](https://huggingface.co/hexgrad/Kokoro-82M)
|
||||
- [Kokoro-FastAPI](https://github.com/remsky/Kokoro-FastAPI)
|
||||
- [Better Auth](https://www.better-auth.com/)
|
||||
- [SQLite](https://www.sqlite.org/)
|
||||
- [PostgreSQL](https://www.postgresql.org/)
|
||||
- [SeaweedFS](https://github.com/seaweedfs/seaweedfs)
|
||||
- [whisper.cpp](https://github.com/ggerganov/whisper.cpp)
|
||||
- [ffmpeg](https://ffmpeg.org)
|
||||
- [react-pdf](https://github.com/wojtekmaj/react-pdf)
|
||||
- [react-reader](https://github.com/happyr/react-reader)
|
||||
7
docs-site/versioned_docs/version-v2.1.1/about/license.md
Normal file
7
docs-site/versioned_docs/version-v2.1.1/about/license.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: License
|
||||
---
|
||||
|
||||
OpenReader is licensed under the MIT License.
|
||||
|
||||
- Repository license file: [LICENSE](https://github.com/richardr1126/openreader/blob/main/LICENSE)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
title: Support and Contributing
|
||||
---
|
||||
|
||||
## Feature requests
|
||||
|
||||
Use [GitHub Discussions](https://github.com/richardr1126/openreader/discussions) for feature requests and ideas.
|
||||
|
||||
## Issues and support
|
||||
|
||||
If you encounter a bug, open an issue in [GitHub Issues](https://github.com/richardr1126/openreader/issues).
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome.
|
||||
|
||||
- Fork the repository
|
||||
- Create your branch
|
||||
- Open a pull request with your changes
|
||||
46
docs-site/versioned_docs/version-v2.1.1/configure/auth.md
Normal file
46
docs-site/versioned_docs/version-v2.1.1/configure/auth.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
title: Auth
|
||||
---
|
||||
|
||||
This page covers application-level configuration for provider access and authentication.
|
||||
|
||||
## Auth behavior
|
||||
|
||||
- Auth is enabled only when both `BASE_URL` and `AUTH_SECRET` are set.
|
||||
- Remove either value to disable auth.
|
||||
- Keep `AUTH_TRUSTED_ORIGINS` empty to trust only `BASE_URL`.
|
||||
- Anonymous auth sessions are disabled by default.
|
||||
- Set `USE_ANONYMOUS_AUTH_SESSIONS=true` to enable anonymous session flows.
|
||||
|
||||
## Route behavior
|
||||
|
||||
- `/` is a public landing/onboarding page and remains indexable.
|
||||
- `/app` is the protected app home (document list and uploader UI).
|
||||
- If auth is enabled and a valid session exists (including anonymous), visiting `/` redirects to `/app`.
|
||||
- Protected app routes continue to require auth; when anonymous sessions are disabled and no session exists, users are redirected to `/signin`.
|
||||
|
||||
## Related docs
|
||||
|
||||
- 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 provider-specific guidance: [TTS Providers](./tts-providers)
|
||||
- For storage/S3/SeaweedFS behavior: [Object / Blob Storage](./object-blob-storage)
|
||||
- For database mode: [Database](./database)
|
||||
- For migration behavior and commands: [Migrations](./migrations)
|
||||
|
||||
## Sync notes
|
||||
|
||||
### Auth enabled
|
||||
|
||||
- Settings and reading progress are saved to the server.
|
||||
- Updates are not instant push-based sync; they use normal client polling/refresh behavior.
|
||||
- If two devices change the same item around the same time, the newest update wins.
|
||||
|
||||
### Auth disabled
|
||||
|
||||
- Settings and reading progress stay local in the browser (Dexie/IndexedDB).
|
||||
- This avoids no-auth cross-browser conflicts, but there is no cross-device sync.
|
||||
|
||||
## Claim modal note
|
||||
|
||||
- You may still see old anonymous settings/progress available to claim from older deployments.
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
title: Database
|
||||
---
|
||||
|
||||
This page covers database mode selection for OpenReader.
|
||||
|
||||
## 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 (`user`, `session`, `account`, `verification`) when auth is enabled — schema is auto-generated by Better Auth.
|
||||
- TTS character usage counters (`user_tts_chars`) for daily rate limiting (when enabled).
|
||||
- User settings preferences (`user_preferences`) when auth is enabled.
|
||||
- User reading progress (`user_document_progress`) when auth is enabled.
|
||||
- Document preview job/asset metadata (`document_previews`) for server-side PDF/EPUB thumbnails.
|
||||
|
||||
App-specific tables are manually maintained in Drizzle schema files, while auth tables are generated by the Better Auth CLI. Both are migrated together via Drizzle. See [Migrations](./migrations) for details.
|
||||
|
||||
## 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)
|
||||
- [Auth](./auth)
|
||||
|
||||
## State sync summary
|
||||
|
||||
- With auth enabled, settings and reading progress are stored in SQL and synced from the app.
|
||||
- With auth disabled, settings and reading progress remain local in the browser.
|
||||
- Sync is currently request-based (not realtime push invalidation).
|
||||
132
docs-site/versioned_docs/version-v2.1.1/configure/migrations.md
Normal file
132
docs-site/versioned_docs/version-v2.1.1/configure/migrations.md
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
---
|
||||
title: Migrations
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
This page covers migration behavior for both database schema and storage data in OpenReader.
|
||||
|
||||
## Startup migration behavior
|
||||
|
||||
By default, the shared entrypoint runs migrations automatically before app startup in:
|
||||
|
||||
- Docker container startup
|
||||
- `pnpm dev`
|
||||
- `pnpm start`
|
||||
|
||||
Startup migration phases:
|
||||
|
||||
- DB schema migrations (`pnpm migrate`)
|
||||
- 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:
|
||||
|
||||
- Set `RUN_DRIZZLE_MIGRATIONS=false`
|
||||
- Set `RUN_FS_MIGRATIONS=false`
|
||||
|
||||
:::warning
|
||||
If you disable startup migrations, ensure your deployment process runs migrations before serving traffic.
|
||||
:::
|
||||
|
||||
## Apply migrations
|
||||
|
||||
In most cases, you do not need manual migration commands because startup runs migrations automatically.
|
||||
|
||||
`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>
|
||||
|
||||
```bash
|
||||
# Run pending migrations for one target:
|
||||
# - Postgres if POSTGRES_URL is set
|
||||
# - SQLite if POSTGRES_URL is unset
|
||||
pnpm migrate
|
||||
|
||||
# Run storage migration (filesystem -> S3 + DB)
|
||||
pnpm migrate-fs
|
||||
|
||||
# Dry-run storage migration without uploading/deleting
|
||||
pnpm migrate-fs:dry-run
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="drizzle-direct" label="Manual Drizzle Cmd">
|
||||
|
||||
```bash
|
||||
# Migrate SQLite
|
||||
pnpm exec drizzle-kit migrate --config drizzle.config.sqlite.ts
|
||||
|
||||
# Migrate Postgres
|
||||
pnpm exec drizzle-kit migrate --config drizzle.config.pg.ts
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Generate migrations
|
||||
|
||||
`pnpm generate` is a two-phase script for contributors and schema changes:
|
||||
|
||||
1. **Better Auth schema generation** — runs the Better Auth CLI twice (once for SQLite, once for Postgres) to produce auto-generated Drizzle schema files for auth tables (`user`, `session`, `account`, `verification`).
|
||||
2. **Drizzle migration generation** — runs `drizzle-kit generate` for both `drizzle.config.sqlite.ts` and `drizzle.config.pg.ts`, producing SQL migration files from all schema files (app + auth).
|
||||
|
||||
:::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.
|
||||
:::
|
||||
|
||||
### Schema ownership
|
||||
|
||||
Auth tables are owned by Better Auth. Their Drizzle schema definitions are auto-generated and should **not** be hand-edited:
|
||||
|
||||
- `src/db/schema_auth_sqlite.ts`
|
||||
- `src/db/schema_auth_postgres.ts`
|
||||
|
||||
App-specific tables are manually maintained in the standard Drizzle schema files:
|
||||
|
||||
- `src/db/schema_sqlite.ts`
|
||||
- `src/db/schema_postgres.ts`
|
||||
|
||||
Both sets of schema files are included in the Drizzle configs, so `drizzle-kit generate` and `drizzle-kit migrate` handle all tables together.
|
||||
|
||||
<Tabs groupId="generate-migration-commands">
|
||||
<TabItem value="project-script" label="Project Script" default>
|
||||
|
||||
```bash
|
||||
# Full pipeline: Better Auth CLI + Drizzle generate (both dialects)
|
||||
pnpm generate
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="drizzle-direct" label="Manual Drizzle Cmd">
|
||||
|
||||
```bash
|
||||
# Generate SQLite migrations only (skips Better Auth CLI)
|
||||
pnpm exec drizzle-kit generate --config drizzle.config.sqlite.ts
|
||||
|
||||
# Generate Postgres migrations only (skips Better Auth CLI)
|
||||
pnpm exec drizzle-kit generate --config drizzle.config.pg.ts
|
||||
```
|
||||
|
||||
:::warning
|
||||
Running `drizzle-kit generate` directly skips the Better Auth CLI step. If auth schema has changed upstream (e.g. after a Better Auth version bump), run `pnpm generate` instead to regenerate the auth schema files first.
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Related docs
|
||||
|
||||
- [Database](./database)
|
||||
- [Object / Blob Storage](./object-blob-storage)
|
||||
- [Migration Environment Variables](../reference/environment-variables#migration-controls)
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
---
|
||||
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.
|
||||
|
||||
## Storage backends
|
||||
|
||||
- Embedded (default): SQLite metadata + embedded SeaweedFS (`weed mini`) blobs.
|
||||
- External: Postgres + external S3-compatible object storage.
|
||||
|
||||
Storage variables are documented in [Environment Variables](../reference/environment-variables#database-and-object-blob-storage).
|
||||
|
||||
## Ports
|
||||
|
||||
- `3003`: OpenReader app and API routes
|
||||
- `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
|
||||
|
||||
- Primary path: browser uploads to presigned URL from `/api/documents/blob/upload/presign`.
|
||||
- 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).
|
||||
- Preview path: `/api/documents/blob/preview` (returns `202` while a preview is generating; serves/redirects when ready).
|
||||
|
||||
## Document previews
|
||||
|
||||
- PDF/EPUB previews are generated server-side and stored in object storage under `document_previews_v1`.
|
||||
- Preview generation is triggered on upload registration and also backfills on first preview request for older docs.
|
||||
- Preview artifacts are temporary-cache friendly and can be regenerated from the source document blob.
|
||||
|
||||
## FS / Volume Mounts
|
||||
|
||||
### App data mount
|
||||
|
||||
- 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
|
||||
|
||||
If `8333` is not published externally:
|
||||
|
||||
- Document uploads still work through upload fallback proxy
|
||||
- Reads/snippets continue through app API routes
|
||||
- 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 Debug Commands
|
||||
|
||||
Audiobook assets are stored in object storage under the `audiobooks_v1` keyspace. Use these commands to inspect and download objects for debugging.
|
||||
|
||||
<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>
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
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
|
||||
|
||||
## FS / Volume Mounts
|
||||
|
||||
### App data mount
|
||||
|
||||
- Target: `/app/docstore`
|
||||
- Recommended: yes, for persistence
|
||||
- Purpose: stores app runtime data, metadata DB, and embedded storage state
|
||||
- Mount string: `-v openreader_docstore:/app/docstore`
|
||||
|
||||
### Library source mount
|
||||
|
||||
- Target: `/app/docstore/library`
|
||||
- Recommended: yes for this feature, use read-only (`:ro`)
|
||||
- Purpose: exposes host files as import candidates in Server Library Import
|
||||
- Mount string: `-v /path/to/your/library:/app/docstore/library:ro`
|
||||
|
||||
## 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`
|
||||
|
||||
## 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
|
||||
|
||||
- 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.
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
title: DeepInfra
|
||||
---
|
||||
|
||||
Use DeepInfra's hosted TTS models as your provider.
|
||||
|
||||
## Setup
|
||||
|
||||
**Environment variables (recommended for deployment):**
|
||||
|
||||
```env
|
||||
API_BASE=https://api.deepinfra.com/v1/openai
|
||||
API_KEY=your-deepinfra-key
|
||||
NEXT_PUBLIC_DEFAULT_TTS_PROVIDER=deepinfra
|
||||
```
|
||||
|
||||
**Or in-app via Settings → TTS Provider:**
|
||||
|
||||
1. Set provider to `Deepinfra`.
|
||||
2. The base URL is pre-filled, no changes needed.
|
||||
3. Enter your `API_KEY`.
|
||||
4. Choose a model and voice.
|
||||
|
||||
Settings modal values override env vars. See [TTS Providers](../tts-providers) for how the two layers interact.
|
||||
|
||||
## Notes
|
||||
|
||||
- Available models include `hexgrad/Kokoro-82M` and `canopylabs/orpheus-3b-0.1-ft`.
|
||||
- Without an API key, only the free-tier model (`hexgrad/Kokoro-82M`) is shown in the dropdown.
|
||||
- TTS requests are sent from the server, not the browser. The API key is never exposed to clients.
|
||||
|
||||
## References
|
||||
|
||||
- [DeepInfra TTS models](https://deepinfra.com/models/text-to-speech)
|
||||
- [TTS Providers](../tts-providers)
|
||||
- [TTS Environment Variables](../../reference/environment-variables#tts-provider-and-request-behavior)
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
title: KittenTTS-FastAPI
|
||||
---
|
||||
|
||||
Run [KittenTTS-FastAPI](https://github.com/richardr1126/KittenTTS-FastAPI) locally and connect it to OpenReader using the `Custom OpenAI-Like` provider. Lightweight and CPU-friendly.
|
||||
|
||||
## Run KittenTTS
|
||||
|
||||
```bash
|
||||
docker run -it --rm \
|
||||
--name kittentts-fastapi \
|
||||
-e KITTEN_MODEL_REPO_ID="KittenML/kitten-tts-nano-0.8-fp32" \
|
||||
-p 8005:8005 \
|
||||
ghcr.io/richardr1126/kittentts-fastapi-cpu
|
||||
```
|
||||
|
||||
## Connect to OpenReader
|
||||
|
||||
**Environment variables (recommended for deployment):**
|
||||
|
||||
```env
|
||||
API_BASE=http://kittentts-fastapi:8005/v1
|
||||
```
|
||||
|
||||
> Use `kittentts-fastapi` if that's the container name, or `host.docker.internal` if not.
|
||||
|
||||
**Or in-app via Settings → TTS Provider:**
|
||||
|
||||
1. Set provider to `Custom OpenAI-Like`.
|
||||
2. Set `API_BASE` to your KittenTTS endpoint (e.g. `http://kittentts-fastapi:8005/v1`).
|
||||
3. Leave `API_KEY` blank unless your deployment requires one.
|
||||
4. Choose model `kitten-tts` (or the model your deployment exposes).
|
||||
|
||||
Settings modal values override env vars. See [TTS Providers](../tts-providers) for how the two layers interact.
|
||||
|
||||
## References
|
||||
|
||||
- [richardr1126/KittenTTS-FastAPI](https://github.com/richardr1126/KittenTTS-FastAPI)
|
||||
- [TTS Providers](../tts-providers)
|
||||
- [TTS Environment Variables](../../reference/environment-variables#tts-provider-and-request-behavior)
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
title: Kokoro-FastAPI
|
||||
---
|
||||
|
||||
Run [Kokoro-FastAPI](https://github.com/remsky/Kokoro-FastAPI) locally and connect it to OpenReader using the `Custom OpenAI-Like` provider.
|
||||
|
||||
:::warning
|
||||
For Kokoro issues and support, use the upstream repository: [remsky/Kokoro-FastAPI](https://github.com/remsky/Kokoro-FastAPI).
|
||||
:::
|
||||
|
||||
## Run Kokoro
|
||||
|
||||
**CPU:**
|
||||
|
||||
```bash
|
||||
docker run --name kokoro-tts \
|
||||
--restart unless-stopped \
|
||||
-d \
|
||||
-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 (NVIDIA):**
|
||||
|
||||
```bash
|
||||
docker run --name kokoro-tts \
|
||||
--restart unless-stopped \
|
||||
-d \
|
||||
--gpus all \
|
||||
--user 1001:1001 \
|
||||
-p 8880:8880 \
|
||||
-e USE_GPU=true \
|
||||
-e PYTHONUNBUFFERED=1 \
|
||||
-e API_LOG_LEVEL=DEBUG \
|
||||
ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.4
|
||||
```
|
||||
|
||||
## Connect to OpenReader
|
||||
|
||||
**Environment variables (recommended for deployment):**
|
||||
|
||||
```env
|
||||
API_BASE=http://kokoro-tts:8880/v1
|
||||
```
|
||||
|
||||
> Use `kokoro-tts` if that's the container name, or `host.docker.internal` if not.
|
||||
|
||||
**Or in-app via Settings → TTS Provider:**
|
||||
|
||||
1. Set provider to `Custom OpenAI-Like`.
|
||||
2. Set `API_BASE` to your Kokoro endpoint (e.g. `http://kokoro-tts:8880/v1`).
|
||||
3. Leave `API_KEY` blank unless your deployment requires one.
|
||||
4. Choose model `Kokoro`.
|
||||
|
||||
Settings modal values override env vars. See [TTS Providers](../tts-providers) for how the two layers interact.
|
||||
|
||||
## 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)
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
title: OpenAI
|
||||
---
|
||||
|
||||
Use the OpenAI TTS API as your provider.
|
||||
|
||||
## Setup
|
||||
|
||||
**Environment variables (recommended for deployment):**
|
||||
|
||||
```env
|
||||
API_BASE=https://api.openai.com/v1
|
||||
API_KEY=sk-...
|
||||
NEXT_PUBLIC_DEFAULT_TTS_PROVIDER=openai
|
||||
```
|
||||
|
||||
**Or in-app via Settings → TTS Provider:**
|
||||
|
||||
1. Set provider to `OpenAI`.
|
||||
2. The base URL is pre-filled, no changes needed.
|
||||
3. Enter your `API_KEY`.
|
||||
4. Choose a model and voice.
|
||||
|
||||
Settings modal values override env vars. See [TTS Providers](../tts-providers) for how the two layers interact.
|
||||
|
||||
## Notes
|
||||
|
||||
- Models: `tts-1`, `tts-1-hd`, `gpt-4o-mini-tts`
|
||||
- TTS requests are sent from the server, not the browser. The API key is never exposed to clients.
|
||||
|
||||
## References
|
||||
|
||||
- [OpenAI TTS pricing](https://platform.openai.com/docs/pricing#transcription-and-speech)
|
||||
- [TTS Providers](../tts-providers)
|
||||
- [TTS Environment Variables](../../reference/environment-variables#tts-provider-and-request-behavior)
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
title: Orpheus-FastAPI
|
||||
---
|
||||
|
||||
Run [Orpheus-FastAPI](https://github.com/Lex-au/Orpheus-FastAPI) locally and connect it to OpenReader using the `Custom OpenAI-Like` provider.
|
||||
|
||||
## Run Orpheus
|
||||
|
||||
Refer to the upstream repository for Docker instructions: [Lex-au/Orpheus-FastAPI](https://github.com/Lex-au/Orpheus-FastAPI).
|
||||
|
||||
## Connect to OpenReader
|
||||
|
||||
**Environment variables (recommended for deployment):**
|
||||
|
||||
```env
|
||||
API_BASE=http://orpheus:8000/v1
|
||||
```
|
||||
|
||||
> Use the container name if that's how it's named, or `host.docker.internal` if not.
|
||||
|
||||
**Or in-app via Settings → TTS Provider:**
|
||||
|
||||
1. Set provider to `Custom OpenAI-Like`.
|
||||
2. Set `API_BASE` to your Orpheus endpoint (e.g. `http://orpheus:8000/v1`).
|
||||
3. Leave `API_KEY` blank unless your deployment requires one.
|
||||
4. Choose model `Orpheus` (or the model your deployment exposes).
|
||||
|
||||
Settings modal values override env vars. See [TTS Providers](../tts-providers) for how the two layers interact.
|
||||
|
||||
## 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)
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
title: Other
|
||||
---
|
||||
|
||||
Use any OpenAI-compatible TTS service with OpenReader, including self-hosted servers not covered by a dedicated guide.
|
||||
|
||||
## Requirements
|
||||
|
||||
Your service must expose these endpoints:
|
||||
|
||||
- `GET /v1/audio/voices`
|
||||
- `POST /v1/audio/speech`
|
||||
|
||||
Known compatible implementations: [Kokoro-FastAPI](./kokoro-fastapi), [KittenTTS-FastAPI](./kitten-tts-fastapi), [Orpheus-FastAPI](./orpheus-fastapi).
|
||||
|
||||
## Setup
|
||||
|
||||
**Environment variables (recommended for deployment):**
|
||||
|
||||
```env
|
||||
API_BASE=http://your-tts-server/v1
|
||||
API_KEY=optional-key-if-required
|
||||
```
|
||||
|
||||
**Or in-app via Settings → TTS Provider:**
|
||||
|
||||
1. Set provider to `Custom OpenAI-Like`.
|
||||
2. Set `API_BASE` to your service's base URL (typically ending in `/v1`).
|
||||
3. Set `API_KEY` if your service requires authentication.
|
||||
4. Choose a model and voice supported by your backend.
|
||||
|
||||
Settings modal values override env vars. See [TTS Providers](../tts-providers) for how the two layers interact.
|
||||
|
||||
:::warning TTS requests are server-side
|
||||
`API_BASE` must be reachable from the **Next.js server**, not just the browser. In Docker, use container names or `host.docker.internal`.
|
||||
:::
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If voices don't load, check that `/v1/audio/voices` is reachable from the server and returns a valid response shape.
|
||||
|
||||
## References
|
||||
|
||||
- [TTS Providers](../tts-providers)
|
||||
- [TTS Environment Variables](../../reference/environment-variables#tts-provider-and-request-behavior)
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
title: TTS Providers
|
||||
---
|
||||
|
||||
OpenReader routes all TTS requests through the Next.js server to an OpenAI-compatible API. You choose your provider and credentials in one of two places:
|
||||
|
||||
**Environment variables**: set in your `.env` or `docker-compose.yml` as server-level defaults. Applied when the user has no saved Settings.
|
||||
|
||||
**Settings modal** (Settings > TTS Provider): stored in the browser and sent with every TTS request. **Overrides env vars.**
|
||||
|
||||
:::note
|
||||
Set env vars as deployment-level defaults. Users (or you, in a single-user setup) can then change the provider, base URL, and API key from the Settings modal without redeploying. Clearing the Settings fields falls back to the env var defaults.
|
||||
:::
|
||||
|
||||
## Providers
|
||||
|
||||
- **OpenAI**: Cloud. Base URL pre-filled (`https://api.openai.com/v1`). API key required.
|
||||
- **Deepinfra**: Cloud. Base URL pre-filled (`https://api.deepinfra.com/v1/openai`). API key required.
|
||||
- **Custom OpenAI-Like**: Self-hosted or any custom endpoint. `API_BASE` must be set manually (typically ending in `/v1`). API key optional.
|
||||
|
||||
For `OpenAI` and `Deepinfra` you only need to supply an API key. For `Custom OpenAI-Like` you must also set `API_BASE`.
|
||||
|
||||
## Custom provider requirements
|
||||
|
||||
Self-hosted or custom providers must expose OpenAI-compatible audio endpoints:
|
||||
|
||||
- `GET /v1/audio/voices`
|
||||
- `POST /v1/audio/speech`
|
||||
|
||||
:::warning TTS requests are server-side
|
||||
TTS requests originate from the **Next.js server**, not the browser. `API_BASE` must be reachable from the server runtime. In Docker, use container names or `host.docker.internal` rather than `localhost`.
|
||||
:::
|
||||
|
||||
## Provider guides
|
||||
|
||||
- [Kokoro-FastAPI](./tts-provider-guides/kokoro-fastapi)
|
||||
- [KittenTTS-FastAPI](./tts-provider-guides/kitten-tts-fastapi)
|
||||
- [Orpheus-FastAPI](./tts-provider-guides/orpheus-fastapi)
|
||||
- [DeepInfra](./tts-provider-guides/deepinfra)
|
||||
- [OpenAI](./tts-provider-guides/openai)
|
||||
- [Other](./tts-provider-guides/other)
|
||||
|
||||
## Related
|
||||
|
||||
- [TTS Environment Variables](../reference/environment-variables#tts-provider-and-request-behavior)
|
||||
- [TTS Rate Limiting](./tts-rate-limiting)
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
title: TTS Rate Limiting
|
||||
---
|
||||
|
||||
This page explains OpenReader's TTS character rate limiting controls.
|
||||
|
||||
## Overview
|
||||
|
||||
- TTS rate limiting is disabled by default.
|
||||
- To enable it, set `TTS_ENABLE_RATE_LIMIT=true`.
|
||||
- Limits are enforced per day in UTC.
|
||||
- Enforcement applies only when auth is enabled.
|
||||
|
||||
## How enforcement works
|
||||
|
||||
When enabled, OpenReader enforces:
|
||||
|
||||
- Per-user daily character limits.
|
||||
- IP backstop daily character limits.
|
||||
- Anonymous device backstop tracking (cookie-based) to reduce limit resets.
|
||||
|
||||
If a request exceeds the active limit, the TTS API returns `429` with reset metadata for the next UTC day.
|
||||
|
||||
## Required auth behavior
|
||||
|
||||
- Auth must be enabled (`BASE_URL` + `AUTH_SECRET`) for TTS char limits to apply.
|
||||
- If auth is disabled, TTS character limits are effectively unlimited.
|
||||
- `DISABLE_AUTH_RATE_LIMIT` only affects Better Auth's own request throttling.
|
||||
- `DISABLE_AUTH_RATE_LIMIT` does not disable TTS character limits.
|
||||
|
||||
## Environment variables
|
||||
|
||||
Enable/disable:
|
||||
|
||||
- `TTS_ENABLE_RATE_LIMIT` (default: `false`)
|
||||
|
||||
Per-user daily limits:
|
||||
|
||||
- `TTS_DAILY_LIMIT_ANONYMOUS` (default: `50000`)
|
||||
- `TTS_DAILY_LIMIT_AUTHENTICATED` (default: `500000`)
|
||||
|
||||
IP backstop daily limits:
|
||||
|
||||
- `TTS_IP_DAILY_LIMIT_ANONYMOUS` (default: `100000`)
|
||||
- `TTS_IP_DAILY_LIMIT_AUTHENTICATED` (default: `1000000`)
|
||||
|
||||
## Related docs
|
||||
|
||||
- TTS/rate-limit environment variables: [Environment Variables](../reference/environment-variables#tts-provider-and-request-behavior)
|
||||
- Auth configuration: [Auth](./auth)
|
||||
- Provider setup: [TTS Providers](./tts-providers)
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
---
|
||||
title: Local Development
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js (recommended with [nvm](https://github.com/nvm-sh/nvm))
|
||||
- `pnpm` (recommended) or `npm`
|
||||
|
||||
```bash
|
||||
npm install -g pnpm
|
||||
```
|
||||
|
||||
- A reachable TTS API server
|
||||
- [SeaweedFS](https://github.com/seaweedfs/seaweedfs) `weed` binary (required unless using external S3 storage)
|
||||
|
||||
<Tabs groupId="seaweedfs-install">
|
||||
<TabItem value="macos" label="macOS" default>
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
- [libreoffice](https://www.libreoffice.org) (required for DOCX conversion)
|
||||
|
||||
```bash
|
||||
brew install libreoffice
|
||||
```
|
||||
|
||||
- [whisper.cpp](https://github.com/ggml-org/whisper.cpp) (optional, for word-by-word highlighting)
|
||||
|
||||
```bash
|
||||
# clone and build whisper.cpp (no model download needed – OpenReader handles that)
|
||||
git clone https://github.com/ggml-org/whisper.cpp.git
|
||||
cd whisper.cpp
|
||||
cmake -B build
|
||||
cmake --build build -j --config Release
|
||||
|
||||
# point OpenReader to the compiled whisper-cli binary
|
||||
echo WHISPER_CPP_BIN="$(pwd)/build/bin/whisper-cli"
|
||||
```
|
||||
|
||||
:::tip
|
||||
Set `WHISPER_CPP_BIN` in your `.env` to enable word-by-word highlighting.
|
||||
:::
|
||||
|
||||
## Steps
|
||||
|
||||
1. Clone the repository.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/richardr1126/openreader.git
|
||||
cd openreader
|
||||
```
|
||||
|
||||
2. Install dependencies.
|
||||
|
||||
```bash
|
||||
pnpm i
|
||||
```
|
||||
|
||||
3. Configure the environment.
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Then edit `.env`.
|
||||
|
||||
- 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 -hex 32`).
|
||||
|
||||
Optional:
|
||||
|
||||
- `AUTH_TRUSTED_ORIGINS=http://localhost:3003,http://192.168.0.116:3003`
|
||||
- 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
|
||||
|
||||
:::info
|
||||
For all environment variables, see [Environment Variables](../reference/environment-variables).
|
||||
:::
|
||||
|
||||
See [Auth](../configure/auth) for app/auth behavior.
|
||||
Storage configuration details are in [Object / Blob Storage](../configure/object-blob-storage).
|
||||
Refer to [Database](../configure/database) for database modes.
|
||||
Learn about migration behavior and commands in [Migrations](../configure/migrations).
|
||||
|
||||
4. Run DB migrations.
|
||||
|
||||
- Migrations run automatically on startup through the shared entrypoint for both `pnpm dev` and `pnpm start`.
|
||||
- You only need manual migration commands for one-off troubleshooting or explicit migration workflows:
|
||||
|
||||
```bash
|
||||
pnpm migrate
|
||||
```
|
||||
|
||||
:::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`.
|
||||
:::
|
||||
|
||||
5. Start the app.
|
||||
|
||||
<Tabs groupId="local-run-mode">
|
||||
<TabItem value="dev" label="Dev" default>
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="prod" label="Build + Start">
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
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).
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
title: Vercel Deployment
|
||||
---
|
||||
|
||||
This guide covers deploying OpenReader to Vercel with external Postgres and S3-compatible object storage.
|
||||
|
||||
## What works on Vercel
|
||||
|
||||
- Documents (PDF/EPUB/TXT/MD) work with `POSTGRES_URL` + external S3 storage.
|
||||
- Audiobook routes work on Node.js serverless functions using `ffmpeg-static`.
|
||||
|
||||
:::warning DOCX Conversion Limitation
|
||||
`docx` conversion requires `soffice` (LibreOffice), which is not available in a standard Vercel runtime.
|
||||
:::
|
||||
|
||||
## 1. Environment Variables
|
||||
|
||||
Recommended production setup (auth enabled):
|
||||
|
||||
```bash
|
||||
API_BASE=https://api.deepinfra.com/v1/openai
|
||||
API_KEY=your_deepinfra_key
|
||||
POSTGRES_URL=postgres://...
|
||||
USE_EMBEDDED_WEED_MINI=false
|
||||
S3_ACCESS_KEY_ID=...
|
||||
S3_SECRET_ACCESS_KEY=...
|
||||
S3_BUCKET=...
|
||||
S3_REGION=us-east-1
|
||||
S3_PREFIX=openreader
|
||||
BASE_URL=https://your-app.vercel.app
|
||||
AUTH_SECRET=...
|
||||
# Optional client/runtime feature defaults:
|
||||
NEXT_PUBLIC_ENABLE_DOCX_CONVERSION=false
|
||||
NEXT_PUBLIC_ENABLE_DESTRUCTIVE_DELETE_ACTIONS=false
|
||||
NEXT_PUBLIC_ENABLE_TTS_PROVIDERS_TAB=false
|
||||
NEXT_PUBLIC_DEFAULT_TTS_PROVIDER=deepinfra
|
||||
NEXT_PUBLIC_DEFAULT_TTS_MODEL=hexgrad/Kokoro-82M
|
||||
NEXT_PUBLIC_SHOW_ALL_DEEPINFRA_MODELS=false
|
||||
NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT=true
|
||||
NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT=false
|
||||
# Optional (non-AWS S3-compatible providers):
|
||||
# S3_ENDPOINT=https://...
|
||||
# S3_FORCE_PATH_STYLE=true
|
||||
```
|
||||
|
||||
:::info Production Configuration & Feature Flags
|
||||
We recommend setting these defaults for a production-like environment:
|
||||
|
||||
- `NEXT_PUBLIC_ENABLE_DOCX_CONVERSION=false`: Disables DOCX upload (requires external tools anyway)
|
||||
- `NEXT_PUBLIC_ENABLE_DESTRUCTIVE_DELETE_ACTIONS=false`: Hides destructive "Delete All" actions
|
||||
- `NEXT_PUBLIC_ENABLE_TTS_PROVIDERS_TAB=false`: Hides the Settings -> TTS Provider section
|
||||
- `NEXT_PUBLIC_DEFAULT_TTS_PROVIDER=deepinfra`: Points default TTS to a scalable provider
|
||||
- `NEXT_PUBLIC_DEFAULT_TTS_MODEL=hexgrad/Kokoro-82M`: Uses a high-quality default model
|
||||
- `NEXT_PUBLIC_SHOW_ALL_DEEPINFRA_MODELS=false`: Restricts usage to free models if no key is provided
|
||||
- `NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT=true`: (Optional) Controls audiobook export UI
|
||||
- `NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT=false`: (Optional) Controls word highlighting UI (requires timestamp backend)
|
||||
:::
|
||||
|
||||
:::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
|
||||
For all variables and defaults, see [Environment Variables](../reference/environment-variables).
|
||||
:::
|
||||
|
||||
## 2. FFmpeg packaging in Vercel functions
|
||||
|
||||
`ffmpeg-static` binaries must be included in function traces. This repo already does that in `next.config.ts` via `outputFileTracingIncludes` for:
|
||||
|
||||
- `/api/audiobook`
|
||||
- `/api/audiobook/chapter`
|
||||
- `/api/audiobook/status`
|
||||
- `/api/whisper`
|
||||
|
||||
:::info
|
||||
`serverExternalPackages` should include `ffmpeg-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.
|
||||
|
||||
## 3. Function memory sizing
|
||||
|
||||
FFmpeg workloads benefit from more memory/CPU. This repo includes:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://openapi.vercel.sh/vercel.json",
|
||||
"functions": {
|
||||
"app/api/audiobook/route.ts": { "memory": 3009 },
|
||||
"app/api/whisper/route.ts": { "memory": 3009 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Adjust memory per route if your files are larger or your plan differs.
|
||||
|
||||
## 4. Runtime expectations and caveats
|
||||
|
||||
- Audiobook APIs require S3 configuration; otherwise they return `503`.
|
||||
- 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.
|
||||
- Vercel deployments do not run `scripts/openreader-entrypoint.mjs`, so run `pnpm migrate-fs` in a controlled environment when migrating legacy filesystem data.
|
||||
|
||||
## 5. Smoke test after deploy
|
||||
|
||||
1. Upload and read a PDF/EPUB document.
|
||||
2. Confirm sync/blob fetch works across refreshes/devices.
|
||||
3. Generate at least one audiobook chapter and play/download it.
|
||||
4. If using word highlighting, verify timestamps are produced and rendered.
|
||||
121
docs-site/versioned_docs/version-v2.1.1/docker-quick-start.md
Normal file
121
docs-site/versioned_docs/version-v2.1.1/docker-quick-start.md
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
---
|
||||
title: Docker Quick Start
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A recent Docker version installed
|
||||
- A TTS API server that OpenReader can reach (Kokoro-FastAPI, KittenTTS-FastAPI, Orpheus-FastAPI, DeepInfra, OpenAI, or equivalent)
|
||||
|
||||
:::note
|
||||
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
|
||||
|
||||
<Tabs groupId="docker-start-mode">
|
||||
<TabItem value="minimal" label="Minimal" default>
|
||||
|
||||
Auth disabled, embedded storage ephemeral, no library import:
|
||||
|
||||
```bash
|
||||
docker run --name openreader \
|
||||
--restart unless-stopped \
|
||||
-p 3003:3003 \
|
||||
-p 8333:8333 \
|
||||
ghcr.io/richardr1126/openreader:latest
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="localhost" label="Localhost">
|
||||
|
||||
Persistent storage, embedded SeaweedFS `weed mini`, optional auth, optional library mount:
|
||||
|
||||
```bash
|
||||
docker run --name openreader \
|
||||
--restart unless-stopped \
|
||||
-p 3003:3003 \
|
||||
-p 8333:8333 \
|
||||
-v openreader_docstore:/app/docstore \
|
||||
-v /path/to/your/library:/app/docstore/library:ro \
|
||||
-e API_BASE=http://host.docker.internal:8880/v1 \
|
||||
-e API_KEY=none \
|
||||
-e BASE_URL=http://localhost:3003 \
|
||||
-e AUTH_SECRET=$(openssl rand -hex 32) \
|
||||
ghcr.io/richardr1126/openreader:latest
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="local-network" label="LAN Host">
|
||||
|
||||
Use this when the app should be reachable from other devices on your LAN:
|
||||
|
||||
```bash
|
||||
docker run --name openreader \
|
||||
--restart unless-stopped \
|
||||
-p 3003:3003 \
|
||||
-p 8333:8333 \
|
||||
-v openreader_docstore:/app/docstore \
|
||||
-e API_BASE=http://host.docker.internal:8880/v1 \
|
||||
-e BASE_URL=http://<YOUR_LAN_IP>:3003 \
|
||||
-e AUTH_SECRET=$(openssl rand -hex 32) \
|
||||
-e AUTH_TRUSTED_ORIGINS=http://localhost:3003,http://127.0.0.1:3003 \
|
||||
-e USE_ANONYMOUS_AUTH_SESSIONS=true \
|
||||
ghcr.io/richardr1126/openreader:latest
|
||||
```
|
||||
|
||||
Replace `<YOUR_LAN_IP>` with the Docker host IP address on your local network to allow access from other devices.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip Quick Tips
|
||||
- Remove `/app/docstore/library` if you do not need server library import.
|
||||
- Remove either `BASE_URL` or `AUTH_SECRET` to keep auth disabled.
|
||||
- Set `API_BASE` to your reachable TTS server base URL.
|
||||
:::
|
||||
|
||||
:::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](./configure/database)
|
||||
- [Object / Blob Storage](./configure/object-blob-storage)
|
||||
- [Migrations](./configure/migrations)
|
||||
:::
|
||||
|
||||
## 2. Configure settings in the app UI
|
||||
|
||||
- Set TTS provider and model in Settings
|
||||
- Set TTS API base URL and API key if needed
|
||||
- Select the model voice from the voice dropdown
|
||||
|
||||
## 3. Update Docker image
|
||||
|
||||
Legacy image compatibility: `ghcr.io/richardr1126/openreader-webui:latest` remains available as an alias.
|
||||
|
||||
```bash
|
||||
docker stop openreader || true && \
|
||||
docker rm openreader || true && \
|
||||
docker image rm ghcr.io/richardr1126/openreader:latest || true && \
|
||||
docker pull ghcr.io/richardr1126/openreader: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.
|
||||
52
docs-site/versioned_docs/version-v2.1.1/introduction.md
Normal file
52
docs-site/versioned_docs/version-v2.1.1/introduction.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
id: intro
|
||||
title: Introduction
|
||||
slug: /
|
||||
---
|
||||
|
||||
OpenReader 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**.
|
||||
|
||||
> Previously named **OpenReader-WebUI**.
|
||||
|
||||
It supports multiple TTS providers including OpenAI, DeepInfra, and custom OpenAI-compatible endpoints such as [Kokoro-FastAPI](https://github.com/remsky/Kokoro-FastAPI), [KittenTTS-FastAPI](https://github.com/richardr1126/KittenTTS-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`)
|
||||
- [**KittenTTS-FastAPI**](https://github.com/richardr1126/KittenTTS-FastAPI): lightweight, CPU-friendly self-hosted TTS
|
||||
- [**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**
|
||||
- 13 built-in themes (light and dark palettes), TTS, and document handling controls
|
||||
|
||||
## 🧭 Key Docs
|
||||
|
||||
- [Docker Quick Start](./docker-quick-start)
|
||||
- [Local Development](./deploy/local-development)
|
||||
- [Vercel Deployment](./deploy/vercel-deployment)
|
||||
- [Environment Variables](./reference/environment-variables)
|
||||
- [Auth](./configure/auth)
|
||||
- [Database](./configure/database)
|
||||
- [Object / Blob Storage](./configure/object-blob-storage)
|
||||
- [Migrations](./configure/migrations)
|
||||
- [Server Library Import](./configure/server-library-import)
|
||||
- [TTS Providers](./configure/tts-providers)
|
||||
|
||||
## Source Repository
|
||||
|
||||
- GitHub: [richardr1126/openreader](https://github.com/richardr1126/openreader)
|
||||
|
|
@ -0,0 +1,406 @@
|
|||
---
|
||||
title: Environment Variables
|
||||
toc_max_heading_level: 3
|
||||
---
|
||||
|
||||
This is the single reference page for OpenReader environment variables.
|
||||
|
||||
## Quick Reference Table
|
||||
|
||||
| Variable | Area | Default | When to set |
|
||||
| --- | --- | --- | --- |
|
||||
| `NEXT_PUBLIC_ENABLE_DOCX_CONVERSION` | Client feature flags | `true` unless set to `false` | Set `false` to hide DOCX support |
|
||||
| `NEXT_PUBLIC_ENABLE_DESTRUCTIVE_DELETE_ACTIONS` | Client feature flags | `true` unless set to `false` | Set `false` to hide destructive actions |
|
||||
| `NEXT_PUBLIC_ENABLE_TTS_PROVIDERS_TAB` | Client feature flags | `true` unless set to `false` | Set `false` to hide the TTS Provider settings tab |
|
||||
| `NEXT_PUBLIC_DEFAULT_TTS_PROVIDER` | Client feature flags | `custom-openai` | Override default TTS provider |
|
||||
| `NEXT_PUBLIC_DEFAULT_TTS_MODEL` | Client feature flags | `kokoro` | Override default TTS model |
|
||||
| `NEXT_PUBLIC_SHOW_ALL_DEEPINFRA_MODELS` | Client feature flags | `true` unless set to `false` | Set `false` to restrict DeepInfra models |
|
||||
| `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` unless set to `false` | Set `false` to disable word highlight + alignment |
|
||||
| `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 |
|
||||
| `TTS_CACHE_MAX_SIZE_BYTES` | TTS caching | `268435456` (256 MB) | Tune in-memory TTS cache size |
|
||||
| `TTS_CACHE_TTL_MS` | TTS caching | `1800000` (30 min) | Tune in-memory TTS cache TTL |
|
||||
| `TTS_MAX_RETRIES` | TTS retry | `2` | Tune retry attempts for upstream 429/5xx |
|
||||
| `TTS_RETRY_INITIAL_MS` | TTS retry | `250` | Tune initial retry delay |
|
||||
| `TTS_RETRY_MAX_MS` | TTS retry | `2000` | Tune max retry delay |
|
||||
| `TTS_RETRY_BACKOFF` | TTS retry | `2` | Tune exponential backoff factor |
|
||||
| `TTS_ENABLE_RATE_LIMIT` | Rate limiting | `false` | Set `true` to enable TTS per-user/IP daily character limits |
|
||||
| `TTS_DAILY_LIMIT_ANONYMOUS` | Rate limiting | `50000` | Override anonymous per-user daily character limit |
|
||||
| `TTS_DAILY_LIMIT_AUTHENTICATED` | Rate limiting | `500000` | Override authenticated per-user daily character limit |
|
||||
| `TTS_IP_DAILY_LIMIT_ANONYMOUS` | Rate limiting | `100000` | Override anonymous IP backstop daily limit |
|
||||
| `TTS_IP_DAILY_LIMIT_AUTHENTICATED` | Rate limiting | `1000000` | Override authenticated IP backstop daily limit |
|
||||
| `BASE_URL` | Auth | unset | Required (with `AUTH_SECRET`) to enable auth |
|
||||
| `AUTH_SECRET` | Auth | unset | Required (with `BASE_URL`) to enable auth |
|
||||
| `AUTH_TRUSTED_ORIGINS` | Auth | empty | Add extra allowed origins |
|
||||
| `USE_ANONYMOUS_AUTH_SESSIONS` | Auth | `false` | Set `true` to enable anonymous auth sessions |
|
||||
| `GITHUB_CLIENT_ID` | Auth/OAuth | unset | Set with `GITHUB_CLIENT_SECRET` to enable GitHub sign-in |
|
||||
| `GITHUB_CLIENT_SECRET` | Auth/OAuth | unset | Set with `GITHUB_CLIENT_ID` to enable GitHub sign-in |
|
||||
| `DISABLE_AUTH_RATE_LIMIT` | Rate limiting | `false` | Set `true` to disable auth-layer rate limiting |
|
||||
| `POSTGRES_URL` | Database | unset (SQLite mode) | Set to switch metadata/auth DB to Postgres |
|
||||
| `USE_EMBEDDED_WEED_MINI` | Storage | `true` when unset | Set `false` to use external S3-compatible storage only |
|
||||
| `WEED_MINI_DIR` | Storage | `docstore/seaweedfs` | Override embedded SeaweedFS data directory |
|
||||
| `WEED_MINI_WAIT_SEC` | Storage | `20` | Tune SeaweedFS startup wait timeout |
|
||||
| `S3_ACCESS_KEY_ID` | Storage | auto-generated in embedded mode | Set explicitly for stable/external credentials |
|
||||
| `S3_SECRET_ACCESS_KEY` | Storage | auto-generated in embedded mode | Set explicitly for stable/external credentials |
|
||||
| `S3_BUCKET` | Storage | `openreader-documents` in embedded mode | Required for external S3-compatible storage |
|
||||
| `S3_REGION` | Storage | `us-east-1` in embedded mode | Required for external S3-compatible storage |
|
||||
| `S3_ENDPOINT` | Storage | derived in embedded mode | Set for S3-compatible providers (MinIO/SeaweedFS/R2/etc.) |
|
||||
| `S3_FORCE_PATH_STYLE` | Storage | `true` in embedded mode | Set per provider requirement |
|
||||
| `S3_PREFIX` | Storage | `openreader` | Customize object key prefix |
|
||||
| `RUN_DRIZZLE_MIGRATIONS` | Database migrations | `true` | Set `false` to skip startup Drizzle schema migrations |
|
||||
| `RUN_FS_MIGRATIONS` | Storage migrations | `true` | Set `false` to skip startup filesystem -> S3/DB migration pass |
|
||||
| `IMPORT_LIBRARY_DIR` | Library import | `docstore/library` fallback | Set a single server library root |
|
||||
| `IMPORT_LIBRARY_DIRS` | Library import | unset | Set multiple roots (comma/colon/semicolon separated) |
|
||||
| `WHISPER_CPP_BIN` | Word timing | unset | Set to enable `whisper.cpp` timestamps |
|
||||
| `FFMPEG_BIN` | Audio runtime | auto-detected (`ffmpeg-static`) | Override ffmpeg binary path |
|
||||
|
||||
|
||||
|
||||
## TTS Provider and Request Behavior
|
||||
|
||||
### API_BASE
|
||||
|
||||
Server-level default base URL for OpenAI-compatible TTS API requests.
|
||||
|
||||
- Example: `http://host.docker.internal:8880/v1`
|
||||
- Used when no `API_BASE` is set in the user's Settings modal
|
||||
- If the user sets `API_BASE` in **Settings → TTS Provider**, that value takes precedence
|
||||
- Related docs: [TTS Providers](../configure/tts-providers)
|
||||
|
||||
### API_KEY
|
||||
|
||||
Server-level default API key for TTS provider requests.
|
||||
|
||||
- Example: your provider token, or omit if the provider doesn't require auth
|
||||
- Used when no `API_KEY` is set in the user's Settings modal
|
||||
- If the user sets `API_KEY` in **Settings → TTS Provider**, that value takes precedence
|
||||
- Related docs: [TTS Providers](../configure/tts-providers)
|
||||
|
||||
### TTS_CACHE_MAX_SIZE_BYTES
|
||||
|
||||
Maximum in-memory TTS audio cache size in bytes.
|
||||
|
||||
- Default: `268435456` (256 MB)
|
||||
|
||||
### TTS_CACHE_TTL_MS
|
||||
|
||||
In-memory TTS audio cache TTL in milliseconds.
|
||||
|
||||
- Default: `1800000` (30 minutes)
|
||||
|
||||
### TTS_MAX_RETRIES
|
||||
|
||||
Maximum retries for upstream TTS failures (429/5xx).
|
||||
|
||||
- Default: `2`
|
||||
|
||||
### TTS_RETRY_INITIAL_MS
|
||||
|
||||
Initial retry delay in milliseconds for TTS upstream requests.
|
||||
|
||||
- Default: `250`
|
||||
|
||||
### TTS_RETRY_MAX_MS
|
||||
|
||||
Maximum retry delay in milliseconds.
|
||||
|
||||
- Default: `2000`
|
||||
|
||||
### TTS_RETRY_BACKOFF
|
||||
|
||||
Exponential backoff multiplier between retries.
|
||||
|
||||
- Default: `2`
|
||||
|
||||
### TTS_ENABLE_RATE_LIMIT
|
||||
|
||||
Controls TTS character rate limiting in the TTS API.
|
||||
|
||||
- Default: `false` (TTS char limits disabled)
|
||||
- Set to `true` to enforce `TTS_DAILY_LIMIT_*` and `TTS_IP_DAILY_LIMIT_*`
|
||||
- For behavior details and examples, see [TTS Rate Limiting](../configure/tts-rate-limiting)
|
||||
|
||||
### TTS_DAILY_LIMIT_ANONYMOUS
|
||||
|
||||
Anonymous per-user daily character limit.
|
||||
|
||||
- Default: `50000`
|
||||
|
||||
### TTS_DAILY_LIMIT_AUTHENTICATED
|
||||
|
||||
Authenticated per-user daily character limit.
|
||||
|
||||
- Default: `500000`
|
||||
|
||||
### TTS_IP_DAILY_LIMIT_ANONYMOUS
|
||||
|
||||
Anonymous IP backstop daily character limit.
|
||||
|
||||
- Default: `100000`
|
||||
|
||||
### TTS_IP_DAILY_LIMIT_AUTHENTICATED
|
||||
|
||||
Authenticated IP backstop daily character limit.
|
||||
|
||||
- Default: `1000000`
|
||||
|
||||
## Auth and Identity
|
||||
|
||||
### BASE_URL
|
||||
|
||||
External base URL for this OpenReader instance.
|
||||
|
||||
- Required with `AUTH_SECRET` to enable auth
|
||||
- Example: `http://localhost:3003` or `https://reader.example.com`
|
||||
- Related docs: [Auth](../configure/auth)
|
||||
|
||||
### AUTH_SECRET
|
||||
|
||||
Secret key used by auth/session handling.
|
||||
|
||||
- Required with `BASE_URL` to enable auth
|
||||
- Generate with `openssl rand -hex 32`
|
||||
- Related docs: [Auth](../configure/auth)
|
||||
|
||||
### AUTH_TRUSTED_ORIGINS
|
||||
|
||||
Additional allowed origins for auth requests.
|
||||
|
||||
- Comma-separated list
|
||||
- `BASE_URL` origin is always trusted automatically
|
||||
- Related docs: [Auth](../configure/auth)
|
||||
|
||||
### USE_ANONYMOUS_AUTH_SESSIONS
|
||||
|
||||
Controls whether auth-enabled deployments can create/use anonymous sessions.
|
||||
|
||||
- Default: `false` (anonymous sessions disabled)
|
||||
- Set `true` to allow anonymous sessions and guest-style flows
|
||||
- When `false`, users must sign in or sign up with an account
|
||||
- Related docs: [Auth](../configure/auth)
|
||||
|
||||
### GITHUB_CLIENT_ID
|
||||
|
||||
GitHub OAuth client ID.
|
||||
|
||||
- Enable only with `GITHUB_CLIENT_SECRET`
|
||||
|
||||
### GITHUB_CLIENT_SECRET
|
||||
|
||||
GitHub OAuth client secret.
|
||||
|
||||
- Enable only with `GITHUB_CLIENT_ID`
|
||||
|
||||
### DISABLE_AUTH_RATE_LIMIT
|
||||
|
||||
Controls Better Auth rate limiting.
|
||||
|
||||
- Default behavior: auth-layer rate limiting enabled
|
||||
- Set to `true` to disable auth-layer rate limiting
|
||||
- This does not affect TTS character rate limiting
|
||||
- Related docs: [Auth](../configure/auth)
|
||||
|
||||
## Database and Object Blob Storage
|
||||
|
||||
### POSTGRES_URL
|
||||
|
||||
Switches metadata/auth storage from SQLite to Postgres.
|
||||
|
||||
- Unset: SQLite at `docstore/sqlite3.db`
|
||||
- Set: Postgres mode
|
||||
- Related docs: [Database](../configure/database)
|
||||
|
||||
### USE_EMBEDDED_WEED_MINI
|
||||
|
||||
Controls embedded SeaweedFS startup.
|
||||
|
||||
- Default behavior: treated as enabled when unset
|
||||
- Set `false` to rely on external S3-compatible storage
|
||||
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
|
||||
|
||||
### WEED_MINI_DIR
|
||||
|
||||
Data directory for embedded SeaweedFS (`weed mini`).
|
||||
|
||||
- Default: `docstore/seaweedfs`
|
||||
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
|
||||
|
||||
### WEED_MINI_WAIT_SEC
|
||||
|
||||
Maximum seconds to wait for embedded SeaweedFS startup.
|
||||
|
||||
- Default: `20`
|
||||
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
|
||||
|
||||
### S3_ACCESS_KEY_ID
|
||||
|
||||
Access key for S3-compatible storage.
|
||||
|
||||
- Auto-generated in embedded mode if unset
|
||||
- Set explicitly for stable credentials or external providers
|
||||
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
|
||||
|
||||
### S3_SECRET_ACCESS_KEY
|
||||
|
||||
Secret key for S3-compatible storage.
|
||||
|
||||
- Auto-generated in embedded mode if unset
|
||||
- Set explicitly for stable credentials or external providers
|
||||
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
|
||||
|
||||
### S3_BUCKET
|
||||
|
||||
Bucket name used for document blobs.
|
||||
|
||||
- Default in embedded mode: `openreader-documents`
|
||||
- Required for external S3-compatible storage
|
||||
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
|
||||
|
||||
### S3_REGION
|
||||
|
||||
Region used by the S3 client.
|
||||
|
||||
- Default in embedded mode: `us-east-1`
|
||||
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
|
||||
|
||||
### S3_ENDPOINT
|
||||
|
||||
Endpoint URL for S3-compatible storage.
|
||||
|
||||
- In embedded mode, defaults to `http://<BASE_URL host>:8333` (or detected host)
|
||||
- For AWS S3, usually leave unset
|
||||
- For MinIO/SeaweedFS/R2/B2-style APIs, typically set explicitly
|
||||
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
|
||||
|
||||
### S3_FORCE_PATH_STYLE
|
||||
|
||||
Path-style S3 addressing toggle.
|
||||
|
||||
- Default in embedded mode: `true`
|
||||
- Set according to provider requirements
|
||||
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
|
||||
|
||||
### S3_PREFIX
|
||||
|
||||
Prefix prepended to stored object keys.
|
||||
|
||||
- Default: `openreader`
|
||||
- Related docs: [Object / Blob Storage](../configure/object-blob-storage)
|
||||
|
||||
## Migration Controls
|
||||
|
||||
### RUN_DRIZZLE_MIGRATIONS
|
||||
|
||||
Controls startup migration execution in shared entrypoint.
|
||||
|
||||
- Default: `true`
|
||||
- Set `false` to skip automatic startup Drizzle schema migrations
|
||||
- Related docs: [Migrations](../configure/migrations), [Database](../configure/database)
|
||||
|
||||
### RUN_FS_MIGRATIONS
|
||||
|
||||
Controls startup filesystem-to-object-store migration execution in shared entrypoint.
|
||||
|
||||
- Default: `true`
|
||||
- Runs `scripts/migrate-fs-v2.mjs` at startup after DB migrations
|
||||
- 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
|
||||
|
||||
Single directory root for server library import.
|
||||
|
||||
- Used when `IMPORT_LIBRARY_DIRS` is unset
|
||||
- Default fallback root: `docstore/library`
|
||||
- Related docs: [Server Library Import](../configure/server-library-import)
|
||||
|
||||
### IMPORT_LIBRARY_DIRS
|
||||
|
||||
Multiple library roots for server library import.
|
||||
|
||||
- Separator: comma, colon, or semicolon
|
||||
- Takes precedence over `IMPORT_LIBRARY_DIR`
|
||||
- Related docs: [Server Library Import](../configure/server-library-import)
|
||||
|
||||
## Audio Tooling and Alignment
|
||||
|
||||
### WHISPER_CPP_BIN
|
||||
|
||||
Absolute path to compiled `whisper.cpp` binary for word-level timestamps.
|
||||
|
||||
- Example: `/whisper.cpp/build/bin/whisper-cli`
|
||||
- Required only for optional word-by-word highlighting
|
||||
|
||||
### FFMPEG_BIN
|
||||
|
||||
Absolute path or executable name for the ffmpeg binary used by audiobook/processing routes.
|
||||
|
||||
- Resolution order: `FFMPEG_BIN` -> `ffmpeg-static`
|
||||
- Example: `/var/task/node_modules/ffmpeg-static/ffmpeg`
|
||||
|
||||
## Client Runtime and Feature Flags
|
||||
|
||||
### NEXT_PUBLIC_ENABLE_DOCX_CONVERSION
|
||||
|
||||
Controls whether the experimental DOCX-to-PDF conversion and upload feature is enabled.
|
||||
|
||||
- Default: `true` (enabled)
|
||||
- Set `false` to hide DOCX support in the upload UI
|
||||
|
||||
### NEXT_PUBLIC_ENABLE_DESTRUCTIVE_DELETE_ACTIONS
|
||||
|
||||
Controls whether the "Delete all user docs" and other bulk-delete buttons are shown in Settings.
|
||||
|
||||
- Default: `true` (enabled)
|
||||
- Set `false` to hide destructive actions (recommended for production)
|
||||
|
||||
### NEXT_PUBLIC_ENABLE_TTS_PROVIDERS_TAB
|
||||
|
||||
Controls whether the **TTS Provider** section appears in the Settings modal.
|
||||
|
||||
- Default: `true` (enabled)
|
||||
- Set `false` to hide provider/model/API controls in Settings
|
||||
- Useful when you want provider config locked to environment defaults
|
||||
|
||||
### NEXT_PUBLIC_DEFAULT_TTS_PROVIDER
|
||||
|
||||
Sets the default TTS provider for new users.
|
||||
|
||||
- Default: `custom-openai`
|
||||
- Example values: `deepinfra`, `openai`, `custom-openai`
|
||||
|
||||
### NEXT_PUBLIC_DEFAULT_TTS_MODEL
|
||||
|
||||
Sets the default TTS model for new users.
|
||||
|
||||
- Default: `kokoro`
|
||||
- Example values: `hexgrad/Kokoro-82M`, `tts-1`
|
||||
|
||||
### NEXT_PUBLIC_SHOW_ALL_DEEPINFRA_MODELS
|
||||
|
||||
Controls whether the DeepInfra model list shows all models or just the free tier when no API key is set.
|
||||
|
||||
- Default: `true` (show all)
|
||||
- Set `false` to restrict to free tier models when no API key is provided
|
||||
|
||||
### NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT
|
||||
|
||||
Controls whether audiobook export UI/actions are shown in the client.
|
||||
|
||||
- Default behavior: enabled unless explicitly set to `false`
|
||||
- Applies in both development and production
|
||||
- Affects export entry points in PDF/EPUB pages and document settings UI
|
||||
|
||||
### NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT
|
||||
|
||||
Controls word-by-word highlighting UI and timestamp-alignment behavior.
|
||||
|
||||
- Default behavior: enabled unless explicitly set to `false`
|
||||
- Applies in both development and production
|
||||
- Requires working timestamp generation (for example `WHISPER_CPP_BIN`)
|
||||
- Affects:
|
||||
- Word-highlight toggles in document settings
|
||||
- Alignment requests during TTS playback
|
||||
44
docs-site/versioned_docs/version-v2.1.1/reference/stack.md
Normal file
44
docs-site/versioned_docs/version-v2.1.1/reference/stack.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
title: Stack
|
||||
---
|
||||
|
||||
## Framework
|
||||
|
||||
- [Next.js](https://nextjs.org/) 15 (App Router)
|
||||
- [React](https://react.dev/) 19
|
||||
- [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
## Containerization and runtime
|
||||
|
||||
- [Docker](https://www.docker.com/) (linux/amd64 and linux/arm64)
|
||||
- Shared entrypoint that runs DB migrations by default and can bootstrap embedded SeaweedFS before app startup
|
||||
|
||||
## Next.js client
|
||||
|
||||
- UI: [Tailwind CSS](https://tailwindcss.com), [Headless UI](https://headlessui.com), [@tailwindcss/typography](https://tailwindcss.com/docs/typography-plugin)
|
||||
- Interactions: `react-dnd`, `react-dropzone`
|
||||
- Authentication: [Better Auth](https://www.better-auth.com/) client SDK
|
||||
- Local storage/cache: [Dexie.js](https://dexie.org/) (IndexedDB)
|
||||
- Document rendering:
|
||||
- PDF: [react-pdf](https://github.com/wojtekmaj/react-pdf), [pdf.js](https://mozilla.github.io/pdf.js/)
|
||||
- EPUB: [react-reader](https://github.com/gerhardsletten/react-reader), [epubjs](https://github.com/futurepress/epub.js/)
|
||||
- Markdown/Text: [react-markdown](https://github.com/remarkjs/react-markdown), [remark-gfm](https://github.com/remarkjs/remark-gfm)
|
||||
- Text preprocessing/matching: [compromise](https://github.com/spencermountain/compromise), [cmpstr](https://github.com/remsky/cmpstr)
|
||||
|
||||
## Next.js server
|
||||
|
||||
- APIs: Route Handlers for sync, blob/content access, migrations, audiobook export, TTS/Whisper proxying
|
||||
- State sync: request-based today (not realtime push updates)
|
||||
- Authentication: [Better Auth](https://www.better-auth.com/) server handlers/adapters
|
||||
- Metadata DB: [Drizzle ORM](https://orm.drizzle.team/) with SQLite (`better-sqlite3`) by default and optional Postgres (`pg`)
|
||||
- App tables are manually maintained in Drizzle schema files
|
||||
- Auth tables are auto-generated by the [Better Auth](https://www.better-auth.com/) CLI and migrated alongside app tables via Drizzle
|
||||
- Blob storage: embedded [SeaweedFS](https://github.com/seaweedfs/seaweedfs) (`weed mini`) by default, or external S3-compatible storage via AWS SDK v3
|
||||
- Audio/processing pipeline: OpenAI-compatible TTS providers, [ffmpeg](https://ffmpeg.org/) for audiobook assembly, optional [whisper.cpp](https://github.com/ggerganov/whisper.cpp) for word timestamps
|
||||
|
||||
## Tooling and testing
|
||||
|
||||
- ESLint
|
||||
- TypeScript
|
||||
- [Playwright](https://playwright.dev/) end-to-end tests
|
||||
- Drizzle migration/generation scripts
|
||||
71
docs-site/versioned_sidebars/version-v2.1.1-sidebars.json
Normal file
71
docs-site/versioned_sidebars/version-v2.1.1-sidebars.json
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"tutorialSidebar": [
|
||||
"intro",
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "docker-quick-start",
|
||||
"label": "🐳 Docker Quick Start"
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"label": "⚙️ Configure",
|
||||
"items": [
|
||||
{
|
||||
"type": "category",
|
||||
"label": "🔊 TTS Providers",
|
||||
"link": {
|
||||
"type": "doc",
|
||||
"id": "configure/tts-providers"
|
||||
},
|
||||
"items": [
|
||||
"configure/tts-provider-guides/kokoro-fastapi",
|
||||
"configure/tts-provider-guides/kitten-tts-fastapi",
|
||||
"configure/tts-provider-guides/orpheus-fastapi",
|
||||
"configure/tts-provider-guides/deepinfra",
|
||||
"configure/tts-provider-guides/openai",
|
||||
"configure/tts-provider-guides/other"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"label": "Reference",
|
||||
"items": [
|
||||
"reference/environment-variables",
|
||||
"reference/stack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"label": "About",
|
||||
"items": [
|
||||
"about/support-and-contributing",
|
||||
"about/acknowledgements",
|
||||
"about/license"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
[
|
||||
"v2.1.1",
|
||||
"v2.1.0",
|
||||
"v2.0.1",
|
||||
"v2.0.0"
|
||||
|
|
|
|||
Loading…
Reference in a new issue