Migrate PDF parsing to use ONNX Docling layout model for structured block extraction, enabling improved TTS segmentation and chaptering. Add compute backend abstraction for heavy tasks (alignment, layout parsing) with configuration via `OPENREADER_COMPUTE_MODE`. Integrate block-level locators and document settings for per-document PDF parsing options. Update S3 storage for parsed PDF JSON, add migration and schema changes, and extend client and server APIs for parsed data and settings. Remove legacy word highlight flag in favor of compute capability detection. - Add ONNX model download, local/none compute modes, and `onnxruntime-node` dependency - Update PDF viewer and TTS pipeline to use parsed blocks and block-level locators - Add document settings storage and APIs for per-document PDF options - Update S3 storage layout for parsed PDF JSON - Add admin/config/docs updates for new compute and parsing features - Remove obsolete word highlight runtime flag and UI BREAKING CHANGE: PDF parsing and word highlighting now require `OPENREADER_COMPUTE_MODE=local` and ONNX model; document settings and S3 layout updated; legacy word highlight flag removed.
311 lines
7.8 KiB
Markdown
311 lines
7.8 KiB
Markdown
---
|
||
title: Local Development
|
||
---
|
||
|
||
import Tabs from '@theme/Tabs';
|
||
import TabItem from '@theme/TabItem';
|
||
|
||
## Prerequisites
|
||
|
||
<details>
|
||
<summary><strong>Node.js + pnpm (required)</strong></summary>
|
||
|
||
<Tabs groupId="local-dev-node-pnpm-os">
|
||
<TabItem value="macos" label="macOS" default>
|
||
|
||
```bash
|
||
brew install nvm pnpm
|
||
mkdir -p ~/.nvm
|
||
echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc
|
||
echo '[ -s "$(brew --prefix nvm)/nvm.sh" ] && . "$(brew --prefix nvm)/nvm.sh"' >> ~/.zshrc
|
||
source ~/.zshrc
|
||
nvm install --lts
|
||
nvm use --lts
|
||
node -v
|
||
pnpm -v
|
||
```
|
||
|
||
</TabItem>
|
||
<TabItem value="linux" label="Linux">
|
||
|
||
```bash
|
||
# Debian/Ubuntu example
|
||
sudo apt update
|
||
sudo apt install -y curl
|
||
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
||
export NVM_DIR="$HOME/.nvm"
|
||
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
||
nvm install --lts
|
||
nvm use --lts
|
||
corepack enable
|
||
corepack prepare pnpm@latest --activate
|
||
node -v
|
||
pnpm -v
|
||
```
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
</details>
|
||
|
||
<details>
|
||
<summary><strong>SeaweedFS <code>weed</code> binary (required unless using external S3)</strong></summary>
|
||
|
||
<Tabs groupId="local-dev-seaweed-os">
|
||
<TabItem value="macos" label="macOS" default>
|
||
|
||
```bash
|
||
brew install seaweedfs
|
||
weed version
|
||
```
|
||
|
||
:::warning SeaweedFS Compatibility Note (April 16, 2026)
|
||
If you see intermittent S3 `InternalError` upload failures with embedded storage, use SeaweedFS `4.18`.
|
||
OpenReader currently pins `4.18` in CI and Docker builds while `4.19` compatibility is investigated.
|
||
:::
|
||
|
||
</TabItem>
|
||
<TabItem value="linux" label="Linux">
|
||
|
||
```bash
|
||
# Linux amd64 example (pin 4.18)
|
||
mkdir -p "$HOME/.local/bin"
|
||
curl -fsSL -o /tmp/seaweedfs.tar.gz \
|
||
https://github.com/seaweedfs/seaweedfs/releases/download/4.18/linux_amd64.tar.gz
|
||
tar -xzf /tmp/seaweedfs.tar.gz -C /tmp weed
|
||
install -m 0755 /tmp/weed "$HOME/.local/bin/weed"
|
||
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
|
||
export PATH="$HOME/.local/bin:$PATH"
|
||
weed version
|
||
```
|
||
|
||
:::warning SeaweedFS Compatibility Note (April 16, 2026)
|
||
If you see intermittent S3 `InternalError` upload failures with embedded storage, use SeaweedFS `4.18`.
|
||
OpenReader currently pins `4.18` in CI and Docker builds while `4.19` compatibility is investigated.
|
||
:::
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
</details>
|
||
|
||
<details>
|
||
<summary><strong>LibreOffice (optional, for DOCX conversion)</strong></summary>
|
||
|
||
<Tabs groupId="local-dev-libreoffice-os">
|
||
<TabItem value="macos" label="macOS" default>
|
||
|
||
```bash
|
||
brew install libreoffice
|
||
```
|
||
|
||
</TabItem>
|
||
<TabItem value="linux" label="Linux">
|
||
|
||
```bash
|
||
# Debian/Ubuntu example
|
||
sudo apt update
|
||
sudo apt install -y libreoffice
|
||
```
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
</details>
|
||
|
||
<details>
|
||
<summary><strong>whisper.cpp (optional, for word-by-word highlighting)</strong></summary>
|
||
|
||
Install build dependencies:
|
||
|
||
<Tabs groupId="local-dev-whisper-deps-os">
|
||
<TabItem value="macos" label="macOS" default>
|
||
|
||
```bash
|
||
brew install cmake
|
||
```
|
||
|
||
</TabItem>
|
||
<TabItem value="linux" label="Linux">
|
||
|
||
```bash
|
||
# Debian/Ubuntu example
|
||
sudo apt update
|
||
sudo apt install -y git build-essential cmake
|
||
```
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
Build whisper.cpp:
|
||
|
||
```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"
|
||
```
|
||
|
||
If you are not on Debian/Ubuntu, install equivalent packages with your distro package manager:
|
||
|
||
- Fedora/RHEL: use `dnf` (`gcc gcc-c++ make cmake curl git tar xz`)
|
||
- Arch: use `pacman` (`base-devel cmake curl git tar xz`)
|
||
|
||
:::tip
|
||
Set `OPENREADER_COMPUTE_MODE=local` and `WHISPER_CPP_BIN` in your `.env` to enable word-by-word highlighting.
|
||
:::
|
||
|
||
</details>
|
||
|
||
## Steps
|
||
|
||
### Required flow
|
||
|
||
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`.
|
||
|
||
Use one of these `.env` mode templates:
|
||
|
||
<Tabs groupId="local-env-modes">
|
||
<TabItem value="no-auth" label="No Auth (simple)" default>
|
||
|
||
```env
|
||
API_BASE=http://host.docker.internal:8880/v1
|
||
API_KEY=none
|
||
OPENREADER_COMPUTE_MODE=local
|
||
# Leave BASE_URL and AUTH_SECRET unset to keep auth disabled.
|
||
# (Admin panel is unavailable without auth.)
|
||
# API_BASE/API_KEY seed a shared default provider if you want shared mode.
|
||
```
|
||
|
||
</TabItem>
|
||
<TabItem value="auth-enabled" label="Auth Enabled">
|
||
|
||
```env
|
||
API_BASE=http://host.docker.internal:8880/v1
|
||
API_KEY=none
|
||
OPENREADER_COMPUTE_MODE=local
|
||
BASE_URL=http://localhost:3003
|
||
AUTH_SECRET=<generate-with-openssl-rand-hex-32>
|
||
# Optional when you need multiple local origins:
|
||
# AUTH_TRUSTED_ORIGINS=http://localhost:3003,http://127.0.0.1:3003
|
||
```
|
||
|
||
</TabItem>
|
||
<TabItem value="auth-with-admin" label="Auth + Admin Panel">
|
||
|
||
```env
|
||
# API_BASE / API_KEY are seeded into the admin "default-openai" shared provider
|
||
# on first boot, then no longer read. Manage them in Settings → Admin afterwards.
|
||
API_BASE=http://host.docker.internal:8880/v1
|
||
API_KEY=none
|
||
OPENREADER_COMPUTE_MODE=local
|
||
BASE_URL=http://localhost:3003
|
||
AUTH_SECRET=<generate-with-openssl-rand-hex-32>
|
||
# Comma-separated emails to auto-promote to admin on signin.
|
||
ADMIN_EMAILS=you@example.com
|
||
```
|
||
|
||
</TabItem>
|
||
<TabItem value="external-s3" label="External S3">
|
||
|
||
```env
|
||
API_BASE=http://host.docker.internal:8880/v1
|
||
API_KEY=none
|
||
OPENREADER_COMPUTE_MODE=local
|
||
USE_EMBEDDED_WEED_MINI=false
|
||
S3_BUCKET=your-bucket
|
||
S3_REGION=us-east-1
|
||
S3_ACCESS_KEY_ID=your-access-key
|
||
S3_SECRET_ACCESS_KEY=your-secret-key
|
||
# Optional for non-AWS providers:
|
||
# S3_ENDPOINT=https://your-s3-compatible-endpoint
|
||
# S3_FORCE_PATH_STYLE=true
|
||
```
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
:::note Env vars vs. admin panel
|
||
On first boot, `API_KEY` / `API_BASE` and any `NEXT_PUBLIC_*` flags you've set get auto-seeded into the admin-managed runtime config (DB-backed, keys encrypted at rest). After that, the admin UI is authoritative and editing those env vars no longer changes app behavior. See [Admin Panel](../configure/admin-panel).
|
||
:::
|
||
|
||
:::note User BYOK restriction default
|
||
If you want each user to enter personal provider credentials, set `restrictUserApiKeys=false` (from **Settings → Admin** when auth/admin is enabled, or via legacy first-boot seed `NEXT_PUBLIC_RESTRICT_USER_API_KEYS=false` for no-admin bootstrap flows).
|
||
:::
|
||
|
||
:::info
|
||
For all environment variables, see [Environment Variables](../reference/environment-variables).
|
||
:::
|
||
|
||
:::tip Optional model prefetch
|
||
To pre-populate the Docling ONNX model cache before first PDF parse, run `pnpm fetch-models`.
|
||
:::
|
||
|
||
See [Auth](../configure/auth) for app/auth behavior.
|
||
See [Admin Panel](../configure/admin-panel) for the shared-provider and feature-flag management UI.
|
||
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. Start the app.
|
||
|
||
<Tabs groupId="local-run-mode">
|
||
<TabItem value="dev" label="Dev (recommended)" 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).
|
||
|
||
### Optional workflows
|
||
|
||
Run manual DB migrations only for troubleshooting or explicit migration workflows:
|
||
|
||
- Migrations run automatically on startup through the shared entrypoint for both `pnpm dev` and `pnpm start`.
|
||
|
||
```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`.
|
||
:::
|