Skip to content

Editor stuck at "Loading editor…": built bundle in dist/ is never served (/assets/editor.js 404s) #52

Description

@mmoren10

Summary

On a self-hosted instance started with npm run serve, the document editor never boots — it hangs at "Loading editor…". The built editor bundle produced by npm run build is written to dist/, but the server only serves static assets from public/, so /assets/editor.js returns 404.

Environment

  • Self-hosted, npm run serve (API + editor on :4000)
  • Accessed via http://localhost:4000/d/<slug>?token=<accessToken>
  • Version: fb25787 ("Sync Proof SDK with latest shared collab fixes")

Root cause

  • npm run build = vite build && node scripts/finalize-web-build.mjs. Vite emits the bundle to dist/assets/editor.js, and dist/index.html references <script defer src="./assets/editor.js">.
  • server/share-web-routes.ts:600 serves the SPA by reading dist/index.html and rewriting "./"/, so the browser requests /assets/editor.js.
  • But server/index.ts:49 mounts only public/:
    app.use(express.static(path.join(__dirname, '..', 'public')));
    There is no static mount for dist/, and scripts/finalize-web-build.mjs does not copy dist/assets/* into public/ (it only rewrites index.html and writes a manifest).
  • Net: /assets/editor.js (and the presence-color PNGs blue.png, lime.png, …) live in dist/assets/ but are never served → 404 → the SPA shell loads but the editor JS never does.

Reproduction

git clone https://github.com/EveryInc/proof-sdk && cd proof-sdk
npm install && npm run build && npm run serve
# create a doc
curl -sS -X POST http://localhost:4000/documents -H 'Content-Type: application/json' \
  -d '{"title":"t","markdown":"# hi"}'
# the bundle the editor needs:
curl -i http://localhost:4000/assets/editor.js        # -> HTTP/1.1 404
ls dist/assets/editor.js                               # -> exists (2.8 MB)
ls public/assets/editor.js                             # -> No such file

Open /d/<slug>?token=… in a browser → stuck at "Loading editor…".

Suggested fix

Either:

  1. Mount the build output in server/index.ts (one line), e.g.
    app.use(express.static(path.join(__dirname, '..', 'public')));
    app.use(express.static(path.join(__dirname, '..', 'dist'))); // serve built bundle
    (public stays authoritative; dist fills the editor.js gap and stays fresh after every build), or
  2. Have scripts/finalize-web-build.mjs copy dist/assets/* (and the favicons) into public/assets/.

Option 1 is preferable since it avoids stale copies after rebuilds.

Found while debugging a self-hosted instance with Claude Code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions