Skip to content

Fix subpath deploy load failures (API 404, matrix=null hang)#281

Merged
ford442 merged 1 commit into
mainfrom
cursor/fix-subpath-load-failures-d86d
Jun 19, 2026
Merged

Fix subpath deploy load failures (API 404, matrix=null hang)#281
ford442 merged 1 commit into
mainfrom
cursor/fix-subpath-load-failures-d86d

Conversation

@ford442

@ford442 ford442 commented Jun 19, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes console errors and stuck loading when the app runs at https://test.1ink.us/xm-player/.

Root causes

  1. /api/songs and /api/shaders 404 — production builds called relative /xm-player/api/* on the static host, but the library API lives on https://storage.noahcohn.com.
  2. matrix=null after module fetch — the parser worker re-downloaded libopenmpt WASM from CDN (15s+ timeout) even though the main thread already had WASM initialized. Under strict COEP (require-corp on the live server) this path is slow and unreliable.
  3. Stale deploy on test.1ink.us — live index.html still references ./assets/modplayer.1iss (corrupt CSS) and base: / instead of /xm-player/. A fresh npm run build:xm-player:verify deploy is required.

Changes

  • utils/storageApi.ts: Production fallback to https://storage.noahcohn.com when VITE_STORAGE_API_URL is unset; dev still uses Vite /api proxy.
  • package.json: build:xm-player now sets VITE_STORAGE_API_URL=https://storage.noahcohn.com.
  • hooks/useLibOpenMPT.ts: Prefer main-thread parse when libopenmpt is ready; skip parser worker creation in the common case.
  • audio-worklet/diagnostics.ts: Log detectRuntimeBase() instead of raw import.meta.env.BASE_URL.
  • docs/DEPLOY.md: Document VITE_STORAGE_API_URL.

Deploy steps

npm run build:xm-player:verify
python deploy.py --build

After deploy, verify:

  • Status progresses FetchingParsingLoaded within a few seconds
  • No 404 on storage.noahcohn.com/api/songs
  • index.html references /xm-player/assets/index-*.css (not modplayer.1iss)
  • COEP header is credentialless (.htaccess in dist overrides server require-corp)

Test plan

  • npm run typecheck
  • npm run build:xm-player:verify
  • Storage API URL baked into dist bundle
Open in Web Open in Cursor 

Summary by CodeRabbit

  • Documentation

    • Updated deployment documentation with environment variable configuration for storage API URL.
  • Chores

    • Updated build configuration to support storage API URL environment variable with fallback behavior.
    • Refactored internal code paths for improved efficiency.

- Route library/shader API to storage.noahcohn.com in production builds
  (VITE_STORAGE_API_URL in build:xm-player + runtime PROD fallback)
- Parse modules on main thread when libopenmpt is already initialized,
  avoiding slow/failing worker CDN WASM reload under strict COEP
- Skip parser worker creation when main-thread lib is ready
- Log detectRuntimeBase() in worklet diagnostics instead of raw BASE_URL

Co-authored-by: Noah Cohn <noahc42@gmail.com>
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d772ef97-5d50-4f33-bae0-0ab04b8e375c

📥 Commits

Reviewing files that changed from the base of the PR and between ad6d3cb and 3610bc3.

📒 Files selected for processing (5)
  • audio-worklet/diagnostics.ts
  • docs/DEPLOY.md
  • hooks/useLibOpenMPT.ts
  • package.json
  • utils/storageApi.ts

📝 Walkthrough

Walkthrough

The PR adds a VITE_STORAGE_API_URL environment variable with a production fallback to storageApi.ts, injects it in the build:xm-player script, and documents it. Audio-worklet diagnostics switch from import.meta.env.BASE_URL to detectRuntimeBase(). In useLibOpenMPT, two helpers enable main-thread libOpenMPT parsing, bypassing the parser worker when the lib is already initialized.

Changes

Runtime URL & Storage API Configuration

Layer / File(s) Summary
Storage API URL fallback chain and build config
utils/storageApi.ts, package.json, docs/DEPLOY.md
storageBaseUrl uses an IIFE that prefers VITE_STORAGE_API_URL, falls back to a hardcoded production URL when import.meta.env.PROD is true, and otherwise returns ''. The build:xm-player script now injects VITE_STORAGE_API_URL, and the new env var is documented in the deployment table.
Audio worklet base URL via detectRuntimeBase
audio-worklet/diagnostics.ts
getWorkletDiagnostics() replaces import.meta.env.BASE_URL with detectRuntimeBase(), adding the import of that shared helper.

Main-thread libOpenMPT Parse Path

Layer / File(s) Summary
isLibReadyForParse and parseOnMainThread helpers
hooks/useLibOpenMPT.ts
isLibReadyForParse checks for _openmpt_module_create_from_memory2 on the lib instance. parseOnMainThread invokes parseModuleWithLib, validates the pattern matrix, and returns a WorkerParseResponse-shaped object.
resolveParsedModule and processModuleData worker gating
hooks/useLibOpenMPT.ts
resolveParsedModule early-returns parseOnMainThread when isLibReadyForParse is true, emitting onParseProgress('patterns'). The former inline fallback parse is refactored to call parseOnMainThread. processModuleData introduces useWorkerParse to skip parser worker creation and passes null to resolveParsedModule when main-thread parsing is used.

Sequence Diagram(s)

sequenceDiagram
  participant processModuleData
  participant isLibReadyForParse
  participant resolveParsedModule
  participant parseOnMainThread
  participant ParserWorker

  processModuleData->>isLibReadyForParse: check lib._openmpt_module_create_from_memory2
  isLibReadyForParse-->>processModuleData: ready = true / false

  alt useWorkerParse = false (lib ready)
    processModuleData->>resolveParsedModule: worker = null
    resolveParsedModule->>parseOnMainThread: parseModuleWithLib(lib, data)
    parseOnMainThread-->>resolveParsedModule: WorkerParseResponse
  else useWorkerParse = true
    processModuleData->>ParserWorker: create & start worker
    processModuleData->>resolveParsedModule: worker = ParserWorker
    ParserWorker-->>resolveParsedModule: WorkerParseResponse
  end

  resolveParsedModule-->>processModuleData: parsed module result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • ford442/mod-player#189: Directly modifies getWorkletDiagnostics() in audio-worklet/diagnostics.ts, the same function updated here to use detectRuntimeBase().
  • ford442/mod-player#256: Updates both audio-worklet/diagnostics.ts base-URL logic and utils/storageApi.ts VITE_STORAGE_API_URL handling, the exact two files changed here.
  • ford442/mod-player#261: Modifies build:xm-player in package.json for deploy-time base-path configuration, the same script updated here to inject VITE_STORAGE_API_URL.

Suggested labels

codex

🐇 A rabbit hops through the build,
Where base URLs were once instilled—
Now detectRuntimeBase() leads the way,
And storage URLs find their stay.
The worker rests when lib is primed,
All paths resolved and neatly timed! 🎵

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/fix-subpath-load-failures-d86d

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ford442 ford442 marked this pull request as ready for review June 19, 2026 18:24
@ford442 ford442 merged commit ca5eb5d into main Jun 19, 2026
3 checks passed
@ford442 ford442 deleted the cursor/fix-subpath-load-failures-d86d branch June 19, 2026 18:24
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.

2 participants