diff --git a/Dockerfile b/Dockerfile
index f4ebc3e..83230da 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -73,12 +73,14 @@ COPY --from=app-builder /app/src/db ./src/db
# Merge in the dependency subset needed by the entrypoint migration scripts.
COPY --from=app-builder /opt/entrypoint-migration-tools/node_modules /tmp/runtime-tools-node_modules
RUN mkdir -p /app/node_modules && \
+ rm -rf /app/node_modules/pg && \
rm -rf /tmp/runtime-tools-node_modules/@aws-sdk \
/tmp/runtime-tools-node_modules/better-sqlite3 \
- /tmp/runtime-tools-node_modules/ffmpeg-static \
- /tmp/runtime-tools-node_modules/pg && \
+ /tmp/runtime-tools-node_modules/ffmpeg-static && \
cp -an /tmp/runtime-tools-node_modules/. /app/node_modules/ && \
rm -rf /tmp/runtime-tools-node_modules
+# Drizzle Kit discovers the Postgres driver through ESM import during startup migrations.
+RUN node --input-type=module -e "await import('pg')"
# Ship the embedded compute worker as a separate deployed bundle.
COPY --from=app-builder /opt/embedded-compute-worker ./embedded-compute-worker
diff --git a/compute-worker/docker-compose.yml b/compute-worker/docker-compose.yml
deleted file mode 100644
index 115eea8..0000000
--- a/compute-worker/docker-compose.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-services:
- nats:
- image: nats:2.14-alpine
- container_name: openreader-compute-nats
- command: ["-js", "-sd", "/data"]
- ports:
- - "4222:4222"
- - "8222:8222"
- volumes:
- - nats-data:/data
-
- compute-worker:
- build:
- context: ..
- dockerfile: compute-worker/Dockerfile
- container_name: openreader-compute-worker
- depends_on:
- - nats
- env_file:
- - path: ./.env
- required: false
- environment:
- NATS_URL: ${NATS_URL:-nats://nats:4222}
- COMPUTE_WORKER_HOST: ${COMPUTE_WORKER_HOST:-0.0.0.0}
- PORT: ${PORT:-8081}
- COMPUTE_WORKER_TOKEN: ${COMPUTE_WORKER_TOKEN:-local-compute-token}
- S3_PREFIX: ${S3_PREFIX:-openreader}
- COMPUTE_PREWARM_MODELS: ${COMPUTE_PREWARM_MODELS:-false}
- ports:
- - "8081:8081"
- develop:
- watch:
- - action: sync+restart
- path: .
- target: /workspace
- - action: rebuild
- path: ./package.json
- - action: rebuild
- path: ../pnpm-lock.yaml
- - action: rebuild
- path: ../pnpm-workspace.yaml
-
-volumes:
- nats-data:
diff --git a/docker/examples/compose.full.yml b/docker/examples/compose.full.yml
new file mode 100644
index 0000000..bdf2270
--- /dev/null
+++ b/docker/examples/compose.full.yml
@@ -0,0 +1,124 @@
+name: openreader-example
+
+services:
+ openreader:
+ image: ghcr.io/richardr1126/openreader:latest
+ # Keep localhost:8333 valid for both app requests and browser-facing presigned URLs.
+ network_mode: service:seaweedfs
+ depends_on:
+ kokoro-tts:
+ condition: service_started
+ postgres:
+ condition: service_healthy
+ seaweedfs:
+ condition: service_healthy
+ environment:
+ BASE_URL: ${BASE_URL:-http://localhost:3003}
+ AUTH_SECRET: ${AUTH_SECRET:-local-openreader-auth-secret-change-me}
+ POSTGRES_URL: postgres://openreader:openreader@postgres:5432/openreader
+ COMPUTE_WORKER_URL: http://compute-worker:8081
+ COMPUTE_WORKER_TOKEN: ${COMPUTE_WORKER_TOKEN:-local-compute-token}
+ USE_EMBEDDED_WEED_MINI: "false"
+ S3_ENDPOINT: ${S3_ENDPOINT:-http://localhost:8333} # Used for internal endpoint and public facing presigned URLs.
+ S3_BUCKET: ${S3_BUCKET:-openreader-documents}
+ S3_REGION: ${S3_REGION:-us-east-1}
+ S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-devkey}
+ S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-devsecret}
+ S3_FORCE_PATH_STYLE: "true"
+ S3_PREFIX: ${S3_PREFIX:-openreader}
+ RUNTIME_SEED_JSON: |-
+ {
+ "version": 1,
+ "runtimeConfig": {
+ "defaultTtsProvider": "kokoro"
+ },
+ "providers": [
+ {
+ "slug": "kokoro",
+ "displayName": "Kokoro",
+ "providerType": "custom-openai",
+ "baseUrl": "http://kokoro-tts:8880/v1",
+ "defaultModel": "kokoro",
+ "enabled": true
+ }
+ ]
+ }
+ volumes:
+ - openreader-docstore:/app/docstore
+
+ kokoro-tts:
+ image: ghcr.io/remsky/kokoro-fastapi-cpu:v0.2.4
+ environment:
+ ONNX_NUM_THREADS: 8
+ ONNX_INTER_OP_THREADS: 4
+ ONNX_EXECUTION_MODE: parallel
+ ONNX_OPTIMIZATION_LEVEL: all
+ ONNX_MEMORY_PATTERN: "true"
+ ONNX_ARENA_EXTEND_STRATEGY: kNextPowerOfTwo
+ API_LOG_LEVEL: DEBUG
+ ports:
+ - "8880:8880"
+
+ seaweedfs:
+ image: chrislusf/seaweedfs:4.18
+ command: ["mini", "-dir=/data"]
+ environment:
+ AWS_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-devkey}
+ AWS_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-devsecret}
+ healthcheck:
+ test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:9333/cluster/status >/dev/null"]
+ interval: 2s
+ timeout: 2s
+ retries: 30
+ ports:
+ - "3003:3003"
+ - "8333:8333"
+ volumes:
+ - seaweedfs-data:/data
+
+ nats:
+ image: nats:2.14-alpine
+ command: ["-js", "-sd", "/data"]
+ volumes:
+ - nats-data:/data
+
+ postgres:
+ image: postgres:17-alpine
+ environment:
+ POSTGRES_USER: openreader
+ POSTGRES_PASSWORD: openreader
+ POSTGRES_DB: openreader
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U openreader -d openreader"]
+ interval: 2s
+ timeout: 2s
+ retries: 30
+ volumes:
+ - postgres-data:/var/lib/postgresql/data
+
+ compute-worker:
+ image: ghcr.io/richardr1126/openreader-compute-worker:latest
+ depends_on:
+ nats:
+ condition: service_started
+ seaweedfs:
+ condition: service_healthy
+ environment:
+ NATS_URL: nats://nats:4222
+ COMPUTE_WORKER_HOST: 0.0.0.0
+ PORT: 8081
+ COMPUTE_WORKER_TOKEN: ${COMPUTE_WORKER_TOKEN:-local-compute-token}
+ S3_ENDPOINT: http://seaweedfs:8333
+ S3_BUCKET: ${S3_BUCKET:-openreader-documents}
+ S3_REGION: ${S3_REGION:-us-east-1}
+ S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-devkey}
+ S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-devsecret}
+ S3_FORCE_PATH_STYLE: "true"
+ S3_PREFIX: ${S3_PREFIX:-openreader}
+ COMPUTE_PREWARM_MODELS: ${COMPUTE_PREWARM_MODELS:-false}
+
+volumes:
+ openreader-docstore:
+ seaweedfs-data:
+ nats-data:
+ postgres-data:
diff --git a/docker/examples/compose.local.yml b/docker/examples/compose.local.yml
new file mode 100644
index 0000000..a50b667
--- /dev/null
+++ b/docker/examples/compose.local.yml
@@ -0,0 +1,130 @@
+name: openreader-local-build
+
+services:
+ openreader:
+ image: openreader:local
+ build:
+ context: ../..
+ dockerfile: Dockerfile
+ # Keep localhost:8333 valid for both app requests and browser-facing presigned URLs.
+ network_mode: service:seaweedfs
+ depends_on:
+ kokoro-tts:
+ condition: service_started
+ postgres:
+ condition: service_healthy
+ seaweedfs:
+ condition: service_healthy
+ environment:
+ BASE_URL: ${BASE_URL:-http://localhost:3003}
+ AUTH_SECRET: ${AUTH_SECRET:-local-openreader-auth-secret-change-me}
+ POSTGRES_URL: postgres://openreader:openreader@postgres:5432/openreader
+ COMPUTE_WORKER_URL: http://compute-worker:8081
+ COMPUTE_WORKER_TOKEN: ${COMPUTE_WORKER_TOKEN:-local-compute-token}
+ USE_EMBEDDED_WEED_MINI: "false"
+ S3_ENDPOINT: ${S3_ENDPOINT:-http://localhost:8333} # Used for internal endpoint and public facing presigned URLs.
+ S3_BUCKET: ${S3_BUCKET:-openreader-documents}
+ S3_REGION: ${S3_REGION:-us-east-1}
+ S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-devkey}
+ S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-devsecret}
+ S3_FORCE_PATH_STYLE: "true"
+ S3_PREFIX: ${S3_PREFIX:-openreader}
+ RUNTIME_SEED_JSON: |-
+ {
+ "version": 1,
+ "runtimeConfig": {
+ "defaultTtsProvider": "kokoro"
+ },
+ "providers": [
+ {
+ "slug": "kokoro",
+ "displayName": "Kokoro",
+ "providerType": "custom-openai",
+ "baseUrl": "http://kokoro-tts:8880/v1",
+ "defaultModel": "kokoro",
+ "enabled": true
+ }
+ ]
+ }
+ volumes:
+ - openreader-docstore:/app/docstore
+
+ kokoro-tts:
+ image: ghcr.io/remsky/kokoro-fastapi-cpu:v0.2.4
+ environment:
+ ONNX_NUM_THREADS: 8
+ ONNX_INTER_OP_THREADS: 4
+ ONNX_EXECUTION_MODE: parallel
+ ONNX_OPTIMIZATION_LEVEL: all
+ ONNX_MEMORY_PATTERN: "true"
+ ONNX_ARENA_EXTEND_STRATEGY: kNextPowerOfTwo
+ API_LOG_LEVEL: DEBUG
+ ports:
+ - "8880:8880"
+
+ seaweedfs:
+ image: chrislusf/seaweedfs:4.18
+ command: ["mini", "-dir=/data"]
+ environment:
+ AWS_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-devkey}
+ AWS_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-devsecret}
+ healthcheck:
+ test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:9333/cluster/status >/dev/null"]
+ interval: 2s
+ timeout: 2s
+ retries: 30
+ ports:
+ - "3003:3003"
+ - "8333:8333"
+ volumes:
+ - seaweedfs-data:/data
+
+ nats:
+ image: nats:2.14-alpine
+ command: ["-js", "-sd", "/data"]
+ volumes:
+ - nats-data:/data
+
+ postgres:
+ image: postgres:17-alpine
+ environment:
+ POSTGRES_USER: openreader
+ POSTGRES_PASSWORD: openreader
+ POSTGRES_DB: openreader
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U openreader -d openreader"]
+ interval: 2s
+ timeout: 2s
+ retries: 30
+ volumes:
+ - postgres-data:/var/lib/postgresql/data
+
+ compute-worker:
+ image: openreader-compute-worker:local
+ build:
+ context: ../..
+ dockerfile: compute-worker/Dockerfile
+ depends_on:
+ nats:
+ condition: service_started
+ seaweedfs:
+ condition: service_healthy
+ environment:
+ NATS_URL: nats://nats:4222
+ COMPUTE_WORKER_HOST: 0.0.0.0
+ PORT: 8081
+ COMPUTE_WORKER_TOKEN: ${COMPUTE_WORKER_TOKEN:-local-compute-token}
+ S3_ENDPOINT: http://seaweedfs:8333
+ S3_BUCKET: ${S3_BUCKET:-openreader-documents}
+ S3_REGION: ${S3_REGION:-us-east-1}
+ S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-devkey}
+ S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:-devsecret}
+ S3_FORCE_PATH_STYLE: "true"
+ S3_PREFIX: ${S3_PREFIX:-openreader}
+ COMPUTE_PREWARM_MODELS: ${COMPUTE_PREWARM_MODELS:-false}
+
+volumes:
+ openreader-docstore:
+ seaweedfs-data:
+ nats-data:
+ postgres-data:
diff --git a/docker/examples/compose.yml b/docker/examples/compose.yml
new file mode 100644
index 0000000..4745d0e
--- /dev/null
+++ b/docker/examples/compose.yml
@@ -0,0 +1,49 @@
+name: openreader-slim-example
+
+services:
+ openreader:
+ image: ghcr.io/richardr1126/openreader:latest
+ depends_on:
+ kokoro-tts:
+ condition: service_started
+ environment:
+ BASE_URL: ${BASE_URL:-http://localhost:3003}
+ AUTH_SECRET: ${AUTH_SECRET:-local-openreader-auth-secret-change-me}
+ RUNTIME_SEED_JSON: |-
+ {
+ "version": 1,
+ "runtimeConfig": {
+ "defaultTtsProvider": "kokoro"
+ },
+ "providers": [
+ {
+ "slug": "kokoro",
+ "displayName": "Kokoro",
+ "providerType": "custom-openai",
+ "baseUrl": "http://kokoro-tts:8880/v1",
+ "defaultModel": "kokoro",
+ "enabled": true
+ }
+ ]
+ }
+ ports:
+ - "3003:3003"
+ - "8333:8333"
+ volumes:
+ - openreader-docstore:/app/docstore
+
+ kokoro-tts:
+ image: ghcr.io/remsky/kokoro-fastapi-cpu:v0.2.4
+ environment:
+ ONNX_NUM_THREADS: 8
+ ONNX_INTER_OP_THREADS: 4
+ ONNX_EXECUTION_MODE: parallel
+ ONNX_OPTIMIZATION_LEVEL: all
+ ONNX_MEMORY_PATTERN: "true"
+ ONNX_ARENA_EXTEND_STRATEGY: kNextPowerOfTwo
+ API_LOG_LEVEL: DEBUG
+ ports:
+ - "8880:8880"
+
+volumes:
+ openreader-docstore:
diff --git a/docs-site/docs/deploy/docker-compose.md b/docs-site/docs/deploy/docker-compose.md
new file mode 100644
index 0000000..78786d3
--- /dev/null
+++ b/docs-site/docs/deploy/docker-compose.md
@@ -0,0 +1,153 @@
+---
+title: Docker Compose
+description: Run OpenReader with the slim, full, or local-build Docker Compose examples.
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+Use these examples to run OpenReader with Kokoro-FastAPI and persistent storage. Choose the slim
+stack for the simplest deployment, or the full stack when you want PostgreSQL, SeaweedFS, NATS,
+and the compute worker as separate containers.
+
+## Prerequisites
+
+- A recent Docker version with Docker Compose
+- A clone of the OpenReader repository
+
+```bash
+git clone https://github.com/richardr1126/openreader.git
+cd openreader
+```
+
+## Choose a stack
+
+
+
+
+The default slim example runs:
+
+- OpenReader with embedded SeaweedFS, NATS, compute worker, and SQLite
+- Kokoro-FastAPI as a companion container
+
+```bash
+docker compose -f docker/examples/compose.yml up
+# Repository convenience command: pnpm compose
+```
+
+Compose file: [`docker/examples/compose.yml`](https://github.com/richardr1126/openreader/blob/main/docker/examples/compose.yml)
+
+
+
+
+The full example runs OpenReader, Kokoro-FastAPI, PostgreSQL, SeaweedFS, NATS, and the compute
+worker as separate containers using published images.
+
+```bash
+docker compose -f docker/examples/compose.full.yml up
+# Repository convenience command: pnpm compose:full
+```
+
+Compose file: [`docker/examples/compose.full.yml`](https://github.com/richardr1126/openreader/blob/main/docker/examples/compose.full.yml)
+
+For details about running the worker separately, see
+[Compute Worker](./compute-worker).
+
+
+
+
+The local-build example uses the full multi-container layout, but builds the OpenReader app and
+compute-worker images from the current checkout.
+
+```bash
+docker compose -f docker/examples/compose.local.yml up --build
+# Repository convenience command: pnpm compose:local
+```
+
+Compose file: [`docker/examples/compose.local.yml`](https://github.com/richardr1126/openreader/blob/main/docker/examples/compose.local.yml)
+
+
+
+
+## Included services
+
+| Service | Slim | Full | Local Build |
+| --- | --- | --- | --- |
+| OpenReader | Published image | Published image | Local build |
+| Kokoro-FastAPI | Container | Container | Container |
+| Database | Embedded SQLite | PostgreSQL container | PostgreSQL container |
+| SeaweedFS | Embedded | Container | Container |
+| NATS | Embedded | Container | Container |
+| Compute worker | Embedded | Published image | Local build |
+
+On first boot, `RUNTIME_SEED_JSON` creates an enabled Kokoro shared provider and selects it as the
+default TTS provider.
+
+## Endpoints
+
+- OpenReader: `http://localhost:3003`
+- SeaweedFS S3: `http://localhost:8333`
+- Kokoro-FastAPI: `http://localhost:8880`
+
+In the full examples, PostgreSQL, the compute worker, and NATS remain internal to the Compose
+network.
+
+## LAN access
+
+Set `BASE_URL` and `S3_ENDPOINT` to the Docker host's LAN IP so browser-facing app and presigned
+S3 URLs are reachable from other devices:
+
+
+
+
+```bash
+BASE_URL=http://192.168.0.XXX:3003 \
+S3_ENDPOINT=http://192.168.0.XXX:8333 \
+docker compose -f docker/examples/compose.yml up
+# Repository convenience command: pnpm compose
+```
+
+
+
+
+```bash
+BASE_URL=http://192.168.0.XXX:3003 \
+S3_ENDPOINT=http://192.168.0.XXX:8333 \
+docker compose -f docker/examples/compose.full.yml up
+# Repository convenience command: pnpm compose:full
+```
+
+
+
+
+```bash
+BASE_URL=http://192.168.0.XXX:3003 \
+S3_ENDPOINT=http://192.168.0.XXX:8333 \
+docker compose -f docker/examples/compose.local.yml up --build
+# Repository convenience command: pnpm compose:local
+```
+
+
+
+
+Replace `192.168.0.XXX` with your Docker host's LAN IP and allow inbound TCP ports `3003` and
+`8333` through its firewall.
+
+:::info Internal full-stack endpoint
+The full and local-build compute workers continue using `http://seaweedfs:8333` internally.
+`S3_ENDPOINT` configures the app endpoint and browser-facing presigned URLs.
+:::
+
+## Configuration
+
+The examples use local-only default credentials. Override existing `${VARIABLE}` values through
+your shell environment before using them beyond local development.
+
+:::warning Protect public deployments
+Replace the default `AUTH_SECRET`, PostgreSQL credentials, S3 credentials, and compute-worker
+token before exposing a stack outside your trusted local network.
+:::
+
+For the complete configuration reference, see
+[Environment Variables](../reference/environment-variables). See [Database](../configure/database)
+for PostgreSQL and SQLite behavior.
diff --git a/docs-site/docs/deploy/local-development.md b/docs-site/docs/deploy/local-development.md
index 6098225..7d81811 100644
--- a/docs-site/docs/deploy/local-development.md
+++ b/docs-site/docs/deploy/local-development.md
@@ -159,45 +159,10 @@ If you need mirrors or pinned artifact locations, set `WHISPER_MODEL_BASE_URL` i
-
-External compute worker dev stack (optional)
-
-Use this only when you intentionally run compute-worker as a separate service.
-Default local flow does not need `compute-worker/.env`; embedded worker startup reads root `.env`.
-Full worker deployment details are in [Compute Worker (NATS JetStream)](./compute-worker).
-
-Start only NATS + compute-worker via compose watch:
-
-```bash
-docker compose --env-file compute-worker/.env -f compute-worker/docker-compose.yml up --watch
-# or: pnpm compute:dev:compose
-```
-
-`compute-worker/.env.example` contains a starter config for standalone worker service deployments.
-
-Run the main app separately on the host:
-
-```bash
-pnpm dev
-```
-
-For app -> external worker routing, set in root `.env`:
-
-```env
-COMPUTE_WORKER_URL=http://localhost:8081
-COMPUTE_WORKER_TOKEN=
-```
-
-Ownership in external worker mode:
-- root `.env`: app routing/auth (`COMPUTE_WORKER_URL`, `COMPUTE_WORKER_TOKEN`) plus optional shared timeout/stale/retry overrides such as `COMPUTE_PDF_JOB_ATTEMPTS`
-- `compute-worker/.env*` (or worker platform env): worker runtime variables (`NATS_*`, `S3_*`, model base URLs, worker tuning)
-
-For embedded worker startup (`COMPUTE_WORKER_URL` unset), worker tuning values such as `COMPUTE_PDF_JOB_ATTEMPTS` must be set in the root `.env` because `compute-worker/.env*` is ignored in that mode.
-
-Worker mode requires worker-reachable shared object storage (S3-compatible endpoint).
-For external worker mode, object storage must be shared/reachable by both app and worker services.
-
-
+:::tip Docker Compose
+To run OpenReader and Kokoro-FastAPI with Docker Compose, including slim, full, and local-build
+options, see [Docker Compose](./docker-compose).
+:::
## Steps
diff --git a/docs-site/sidebars.ts b/docs-site/sidebars.ts
index 63041f9..45597dc 100644
--- a/docs-site/sidebars.ts
+++ b/docs-site/sidebars.ts
@@ -55,7 +55,12 @@ const sidebars: SidebarsConfig = {
{
type: 'category',
label: '🚀 Deploy',
- items: ['deploy/local-development', 'deploy/compute-worker', 'deploy/vercel-deployment'],
+ items: [
+ 'deploy/local-development',
+ 'deploy/docker-compose',
+ 'deploy/compute-worker',
+ 'deploy/vercel-deployment',
+ ],
},
{
type: 'category',
diff --git a/package.json b/package.json
index 25d915d..37ad06a 100644
--- a/package.json
+++ b/package.json
@@ -16,8 +16,9 @@
"test:e2e": "playwright test",
"test:unit": "vitest run",
"test:compute": "vitest run --project compute-worker",
- "compute:openapi:generate": "pnpm --dir compute-worker openapi:generate && openapi-typescript compute-worker/openapi.json -o src/lib/server/compute-worker/generated.ts",
- "compute:openapi:check": "pnpm compute:openapi:generate && git diff --exit-code -- compute-worker/openapi.json src/lib/server/compute-worker/generated.ts",
+ "compose": "docker compose -f docker/examples/compose.yml up",
+ "compose:full": "docker compose -f docker/examples/compose.full.yml up",
+ "compose:local": "docker compose -f docker/examples/compose.local.yml up --build",
"migrate": "node drizzle/scripts/migrate.mjs",
"migrate-fs": "node scripts/migrate-fs-v2.mjs",
"migrate-fs:dry-run": "node scripts/migrate-fs-v2.mjs --dry-run true",
@@ -28,9 +29,10 @@
"docs:serve": "pnpm --dir docs-site serve",
"docs:version": "pnpm --dir docs-site docusaurus docs:version",
"docs:clear": "pnpm --dir docs-site clear",
- "compute:worker:dev": "pnpm --filter @openreader/compute-worker dev",
- "compute:worker:start": "pnpm --filter @openreader/compute-worker start",
- "compute:dev:compose": "docker compose --env-file compute-worker/.env -f compute-worker/docker-compose.yml up --build",
+ "compute:dev": "pnpm --filter @openreader/compute-worker dev",
+ "compute:start": "pnpm --filter @openreader/compute-worker start",
+ "compute:openapi:generate": "pnpm --dir compute-worker openapi:generate && openapi-typescript compute-worker/openapi.json -o src/lib/server/compute-worker/generated.ts",
+ "compute:openapi:check": "pnpm compute:openapi:generate && git diff --exit-code -- compute-worker/openapi.json src/lib/server/compute-worker/generated.ts",
"lint:route-errors": "node scripts/check-route-error-responses.mjs"
},
"dependencies": {