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. - Heavy compute features (Whisper alignment + PDF layout parsing) run through an external compute worker service.
- For worker setup details and worker-specific env vars, see Compute Worker (NATS JetStream).
docx conversion requires soffice (LibreOffice), which is not available in a standard Vercel runtime.
1. Environment Variables
Recommended production setup (auth enabled, admin panel enabled):
# Infrastructure
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
# Optional (non-AWS S3-compatible providers):
# S3_ENDPOINT=https://...
# S3_FORCE_PATH_STYLE=true
# Auth (required for the admin panel)
BASE_URL=https://your-app.vercel.app
AUTH_SECRET=...
ADMIN_EMAILS=you@example.com # comma-separated; admins manage TTS + features in-app
# Heavy compute (required on Vercel in current releases)
COMPUTE_WORKER_URL=https://<railway-worker-domain>
COMPUTE_WORKER_TOKEN=...
# Logging (recommended for Vercel log ingestion)
LOG_FORMAT=json
LOG_LEVEL=info
# First-boot seed for the TTS shared provider (optional; manage in-app afterwards)
# API_KEY=your_replicate_key
# API_BASE only needed for OpenAI-compatible self-hosted providers
If you also run an external worker service (for example Railway), set these there too:
LOG_FORMAT=jsonCOMPUTE_LOG_LEVEL=info
API_KEY / API_BASE are one-shot bootstrap seeds on first deploy. After boot, manage providers and site features in Settings → Admin. Changes there apply on refresh without a redeploy. See Admin Panel.
1a. Railway + Synadia quick start (worker mode)
If your Vercel app uses an external compute worker on Railway with Synadia Cloud (NGS):
- Deploy a Railway service from:
ghcr.io/richardr1126/openreader-compute-worker:refactor-ppdoclayoutv3-onnx-layout-parsing
- Enable public networking on that Railway service and set:
COMPUTE_WORKER_URL=https://<railway-worker-domain>(in Vercel)
- Use the same
COMPUTE_WORKER_TOKENvalue in both Vercel and Railway worker env vars.
For complete Railway worker env vars (NATS_*, S3_*, health checks, and Synadia .creds guidance), see Compute Worker (NATS JetStream).
2. First-run admin configuration (recommended)
After the first successful deploy and admin login, open Settings → Admin and configure:
- Shared providers: create/edit your provider key(s) here (encrypted at rest).
- Site features:
enableDocxConversion=falseon Vercel (sofficeunavailable).enableDestructiveDeleteActions=falsefor safer public deployments.enableTtsProvidersTab=falseif you want shared-provider-only UX.enableUserSignups=trueunless you explicitly want an invite-only deployment.restrictUserApiKeys=trueto block user BYOK through the hosted server.defaultTtsProvider=replicate(or your preferred shared slug).showAllProviderModels=falseif you want users locked to each provider's default model.enableAudiobookExport=true.
3. Runtime JSON seed (optional)
If you must pre-seed site features/providers at deploy time, use RUNTIME_SEED_JSON or RUNTIME_SEED_JSON_PATH (versioned JSON seed document). Prefer the admin panel for ongoing management.
See Environment Variables for schema and examples.
Set both BASE_URL and AUTH_SECRET — they are required in v4+ and also required for the admin panel and for encrypting admin-stored TTS credentials.
Admin-managed TTS provider keys are encrypted with a key derived from AUTH_SECRET. If you rotate AUTH_SECRET after the first deploy, you must re-enter each admin shared provider's API key from the UI.
For all variables and defaults, see Environment Variables.
4. Database and data migrations
Vercel deployments do not run scripts/openreader-entrypoint.mjs, so automatic startup migrations do not run there.
- Run
pnpm migratein a controlled environment to apply Drizzle schema migrations to your Postgres DB. - Run
pnpm migrate-fsonly when migrating legacy local filesystem data (docstore/documents_v1,docstore/audiobooks_v1) into object storage + DB rows. Fresh Vercel deployments usually do not need this.
5. 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/tts/segments/ensure
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.
6. Function memory sizing
FFmpeg workloads benefit from more memory/CPU. This repo includes:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"functions": {
"app/api/audiobook/route.ts": { "memory": 3009 },
"app/api/tts/segments/ensure/route.ts": { "memory": 3009 }
}
}
Adjust memory per route if your files are larger or your plan differs.
7. Runtime expectations and caveats
- Audiobook APIs require S3 configuration; otherwise they return
503. - For production Vercel deploys, use
POSTGRES_URLinstead of SQLite.
8. Smoke test after deploy
- Upload and read a PDF/EPUB document.
- Confirm sync/blob fetch works across refreshes/devices.
- Generate at least one audiobook chapter and play/download it.
- Verify worker-backed word highlighting and PDF parsing.