Skip to content

fix: serve dist/assets when self-hosting the editor#13

Open
maxmilneaus wants to merge 1 commit intoEveryInc:mainfrom
maxmilneaus:fix/serve-dist-assets-for-self-hosted-editor
Open

fix: serve dist/assets when self-hosting the editor#13
maxmilneaus wants to merge 1 commit intoEveryInc:mainfrom
maxmilneaus:fix/serve-dist-assets-for-self-hosted-editor

Conversation

@maxmilneaus
Copy link

Problem

When self-hosting the Proof SDK, the editor loads as a blank white page with no UI.

share-web-routes.ts correctly reads dist/index.html and serves it as the SPA shell for /d/:slug routes. However, server/index.ts only mounts a static file server for public/ — not dist/.

This means the browser receives the editor HTML, immediately tries to fetch /assets/editor.js (and other built assets), gets a 404 for each, and the page stays blank.

Reproduction

# Clone, install, build
git clone https://github.com/EveryInc/proof-sdk.git
cd proof-sdk
npm install
npm run build
npm run serve

# Create a doc
curl -X POST http://localhost:4000/documents   -H 'Content-Type: application/json'   -d '{"title": "Test", "markdown": "# Test"}'

# Open the returned /d/<slug> URL in a browser
# Result: blank white page, browser console shows 404s for /assets/editor.js

Fix

Add dist/ as a static file directory alongside the existing public/ server in server/index.ts:

  app.use(express.static(path.join(__dirname, '..', 'public')));
+ app.use(express.static(path.join(__dirname, '..', 'dist')));

One line. No behaviour change for the API or hosted runtime — only affects the self-hosted editor frontend path.

share-web-routes.ts reads dist/index.html and injects it as the SPA
shell for /d/:slug routes, but server/index.ts only mounts a static
file server for public/ — not dist/.

This means the browser loads the editor HTML but immediately 404s on
/assets/editor.js (and all other built assets), resulting in a blank
white page with no editor UI when self-hosting.

Fix: add express.static for the dist directory alongside the existing
public directory static server.

Reproduction:
1. Clone the repo and run: npm install && npm run build && npm run serve
2. Create a doc: POST /documents with a markdown body
3. Open the returned URL in a browser
4. Page is blank; browser console shows 404s for /assets/editor.js
@maxmilneaus
Copy link
Author

Validation

Tested against a clean clone of main (no local modifications):

Without fix/assets/editor.js returns 404:

fetch('http://localhost:4001/assets/editor.js')
// → { status: 404, ok: false }

With fix — assets load (2.8MB JS bundle), editor renders fully with toolbar and collab presence indicator.

Steps run:

git clone https://github.com/EveryInc/proof-sdk.git /tmp/proof-sdk-test
cd /tmp/proof-sdk-test
npm install && npm run build
PORT=4001 COLLAB_PUBLIC_BASE_URL=ws://localhost:4001/ws COLLAB_EMBEDDED_WS=true tsx server/index.ts &

# Create doc
curl -X POST http://localhost:4001/documents   -H 'Content-Type: application/json'   -d '{"title":"PR Validation Test","markdown":"# PR Validation Test\n\nConfirming upstream bug."}'

# Check assets 404 (bug confirmed)
curl -I http://localhost:4001/assets/editor.js  # → 404

# Apply fix, restart
# → assets now serve correctly, editor renders

@rdhyee
Copy link

rdhyee commented Mar 12, 2026

Nice catch — hit the exact same issue when self-hosting on a Linode VPS this week.

I went with an Nginx location /assets/ alias rather than adding dist/ to Express static, mostly because I wanted Nginx to serve the hashed assets with Cache-Control: public, immutable headers and keep Express focused on the API. But your one-line fix is simpler and works without a reverse proxy, which is the right default for the codebase.

FWIW, dist/assets/ was one of several self-hosting gotchas I ran into. I've been collecting them on my fork along with a deployment guide:

  • WebSocket coexistence: WebSocketServer({ server, path: '/ws' }) captures ALL upgrade events and rejects /collab with 400 — fix is noServer: true with manual upgrade routing (rdhyee/proof-sdk#1)
  • Three undocumented collab modes: startCollabRuntimeEmbedded reports enabled: true but doesn't serve WebSocket connections — need startCollabRuntimeAttached for single-port deploys
  • Vite build OOMs on small VPS (1GB) — need to build locally and rsync
  • Self-hosting guide: SELF-HOSTING.md on my fork documents the full deployment path (Nginx, systemd, env vars, architecture)

Haven't issued an upstream PR yet since I'm still testing my deployment, but happy to coordinate if useful. The self-hosting story clearly needs attention given multiple people are hitting the same walls within 48 hours of launch.

@dgalarza
Copy link

I ran into this issue as well trying to run locally / self-host.

@maxmilneaus
Copy link
Author

I ended up having more issues, so have paused using Proof local host for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants