Skip to main content
Version: v5.1.0

Local Development

Prerequisites​

Node.js + pnpm (required)
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
SeaweedFS weed binary (required unless using external S3)
brew install seaweedfs
weed version
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.

NATS Server nats-server (required for embedded compute mode)

If COMPUTE_WORKER_URL is unset, startup launches embedded compute worker + NATS, so nats-server must be available on host PATH.

If you always use an external worker (COMPUTE_WORKER_URL set), this is not required.

brew install nats-server
nats-server -v
LibreOffice (optional, for DOCX conversion)
brew install libreoffice
Word-by-word highlighting (optional)

No extra native Whisper CLI build step is required.

Word-by-word highlighting and PDF layout parsing are worker-backed in current releases.

If you need mirrors or pinned artifact locations, set WHISPER_MODEL_BASE_URL in .env (current defaults expect q4 Whisper files at that base URL).

Docker Compose

To run OpenReader and Kokoro-FastAPI with Docker Compose, including slim, full, and local-build options, see Docker Compose.

Steps​

Required flow​

  1. Clone the repository.
git clone https://github.com/richardr1126/openreader.git
cd openreader
  1. Install dependencies.
pnpm i
  1. Create your .env file.
cp .env.example .env
openssl rand -base64 32

Open .env and set these two values. Paste the command output as AUTH_SECRET:

BASE_URL=http://localhost:3003
AUTH_SECRET=<paste-the-generated-value>

That is a complete configuration: the app starts its own storage, queue, and compute worker, and the worker and playback secrets are generated or derived for you. Keep AUTH_SECRET stable, since it also encrypts saved provider keys.

Then add only what applies to you. Each tab lists what to add to the same .env, so you can combine them. If something is missing or wrong, startup lists every problem at once and exits.

Use when: you want an admin account ready on the first boot.

BOOTSTRAP_ADMIN_EMAIL=owner@example.com
BOOTSTRAP_ADMIN_PASSWORD=<unique-initial-password-at-least-16-characters>

Then: sign in, and change the password in Settings → Account. The Admin tab appears after that. Remove these two lines afterward.

Env vars vs. admin panel

Provider and runtime settings in .env seed the database on first boot (API_*, RUNTIME_SEED_JSON, RUNTIME_SEED_JSON_PATH). After that the admin UI is authoritative and editing those variables no longer changes behavior. See Admin Panel. Browsers never supply provider credentials.

Related guides: Auth, Database, Migrations, and the full Environment Variables reference. Upgrading from v4? See Upgrade from v4.

Scheduled maintenance tasks

Local and self-hosted Node.js deployments start the scheduled-task loop in-process and check for due work once per minute. No CRON_SECRET is required unless you intentionally invoke the cron HTTP route yourself. Manage task intervals and inspect failures from Settings → Admin → Scheduled tasks.

  1. Start the app.
pnpm dev

If you use embedded worker startup (no COMPUTE_WORKER_URL) and the host is missing nats-server, install nats-server locally or switch to external worker mode.

Provider reachability

Background speech generation runs in the compute worker, while optional custom voice discovery runs in the app server. A self-hosted provider base URL must therefore be reachable from both runtimes. For native pnpm dev/pnpm start with the embedded worker, http://127.0.0.1:<port>/v1 is correct. If the worker is remote, configure a URL reachable from that host as well.

Visit http://localhost:3003. Signed in as an admin, open Settings → Admin → System to confirm the worker, storage, and providers are healthy.

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.
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_V4_DECOMMISSION=false. You can run the idempotent v4 legacy storage decommission manually with pnpm migrate-decommission. See Upgrade from v4 before a production v4.4→v5 upgrade.