Pulp Engine Document Rendering
Get started
Release v0.47.0

Pulp Engine v0.47.0 — Release Notes

The bundled editor deployment path is now first-class. The Docker image now includes the compiled visual editor SPA, served by the API at /editor/. Prior to this release, the Docker image was API-only: the product claimed “a React-based visual editor that ships with the platform” but no artifact or deployment path actually delivered it. That gap is closed.


What changed

1. Editor bundled in the Docker image

The Dockerfile builder stage already compiled the editor during pnpm build — the apps/editor/dist/ output existed in the builder but was never copied into the runtime image. The runtime image now includes it:

COPY --from=builder /build/apps/editor/dist /app/editor-dist

The editor is built with VITE_EDITOR_BASE_PATH=/editor/ so Vite emits asset URLs prefixed at /editor/assets/..., matching the subpath where the API serves it.

2. API serves the editor at /editor/

apps/api/src/server.ts now registers a fastifyStatic handler for /editor/ when the editor-dist/ directory exists at runtime. In local dev and non-Docker source builds the directory is absent, so the registration is silently skipped — no behaviour change for those paths.

A permanent redirect from /editor/editor/ ensures users typing the shorter URL land correctly.

The startup log now includes Visual editor available at /editor/ when the editor is bundled.

3. Same-origin API wiring

apps/editor/src/lib/api-config.ts previously defaulted to http://127.0.0.1:3001 (wrong port — the API runs on 3000, and this default was silently broken in all Docker deployments). The default is now '' (empty string), which causes the SPA to make same-origin relative requests (/templates, /auth/editor-token, etc.) when served from the API origin.

?? (nullish coalescing) is used instead of || so an explicit empty-string VITE_API_URL build var is honoured if needed.

4. Local development wiring fixed

apps/editor/.env.development is a new committed file containing:

VITE_API_URL=http://localhost:3000

Vite loads this file automatically in dev mode (pnpm dev / vite serve) but not during production builds (vite build). This fixes the broken local dev default and requires no manual environment setup to run the editor against a local API instance.

The Playwright E2E configs explicitly pass VITE_API_URL as a process env var, which takes higher priority than .env files in Vite’s resolution order — E2E tests are unaffected.

5. Evaluator compose files updated

compose.yaml and compose.postgres.yaml (both labelled evaluator setups) now include:

PREVIEW_ROUTES_ENABLED: "true"

Without this, evaluators can log in and edit templates but the editor’s live preview button returns 404. This is evaluation posture and is clearly labelled as such in both files. Preview routes remain off by default in production — see docs/deployment-guide.md § Visual Editor for production guidance.

Both files also have the editor URL comment corrected from http://localhost:3000 to http://localhost:3000/editor/.

6. Documentation

  • docs/deployment-guide.md — new “Visual Editor” section documenting: bundled path, live preview gating (PREVIEW_ROUTES_ENABLED), same-origin CORS behaviour, and local-dev vs Docker topology table.
  • docs/editor-guide.md — new “Deployment modes” section at the top distinguishing local development (:5174) from bundled deployment (/editor/).
  • README.md — editor URL added to Docker run examples; preview posture note separated from editor availability note; CORS_ALLOWED_ORIGINS annotation updated (bundled editor is same-origin — CORS not required for editor-to-API calls).

7. Deployment validation

scripts/validate-deploy.sh now includes check 6, gated on EXPECT_EDITOR=true:

EXPECT_EDITOR=true ./scripts/validate-deploy.sh http://localhost:3000 $API_KEY_ADMIN

When set, GET /editor/ must return HTTP 200 with Content-Type: text/html — failure is a hard error. When absent, the check is skipped with an advisory notice. Use for Docker image deployments; skip for API-only or source-build deployments.

docs/runbook.md smoke tests section now includes a “Bundled editor check” subsection covering the curl checks, browser login flow, and EXPECT_EDITOR script invocation.


Validation

  • pnpm --filter @pulp-engine/api typecheck — 0 errors
  • pnpm --filter @pulp-engine/editor typecheck — 0 errors
  • pnpm --filter @pulp-engine/api lint — 0 errors
  • pnpm --filter @pulp-engine/editor lint — 0 errors
  • pnpm --filter @pulp-engine/api test:file559 passed, 48 skipped, 0 failed

Upgrade

No breaking changes to the API, storage, auth, or render pipeline. All existing env vars, API shapes, and database schemas are unchanged. No migrations required.

Docker image: the image now includes the editor SPA (~1 MB additional). The API starts and operates identically when the editor dist is absent (local dev, non-Docker builds).

CORS_ALLOWED_ORIGINS in hardened mode: for same-origin bundled deployments (editor and API on the same host), the editor makes same-origin requests and CORS is not involved. However, HARDEN_PRODUCTION=true still requires CORS_ALLOWED_ORIGINS to be set. Set it to your deployment URL (e.g. CORS_ALLOWED_ORIGINS=https://pulp-engine.example.com).


Bug fix included in this release

PDF renderer: PUPPETEER_EXECUTABLE_PATH not forwarded to child process worker

The child-process render dispatcher forks its worker with env: {} for secret isolation. PUPPETEER_EXECUTABLE_PATH and PUPPETEER_CACHE_DIR were not forwarded — they are configuration paths, not secrets, but the omission meant the worker’s Puppeteer fell back to its default Chrome cache location, which differs when the operator (or CI) sets PUPPETEER_EXECUTABLE_PATH to a system Chrome binary. Symptom: the startup probe passed (used process.env, found Chrome) while actual renders returned 422 render_error (worker could not find Chrome). This bug was present since v0.46.0. Fixed by forwarding both vars when set. (packages/pdf-renderer/src/child-process-dispatcher.ts)

docker pull ghcr.io/OWNER/pulp-engine:v0.47.0