#18510 · @DroganC · opened Mar 21, 2026 at 9:40 AM UTC · last updated Mar 21, 2026 at 10:02 AM UTC
feat: offline web static serve
Score breakdown
Impact
Clarity
Urgency
Ease Of Review
Guidelines
Readiness
Size
Trust
Traction
Summary
This PR enables opencode web to serve its UI from a local build, eliminating reliance on app.opencode.ai for users in air-gapped or offline environments. It introduces a new environment variable for configuration and comprehensive documentation.
Description
Issue for this PR
Closes #18510
Type of change
- [ ] Bug fix
- [x] New feature
- [ ] Refactor / code improvement
- [x] Documentation
What does this PR do?
Problem: opencode web serves the browser UI by proxying to https://app.opencode.ai when no API route matches. On machines without outbound access to that host, the UI never loads.
Changes:
packages/opencode/src/server/server.ts— Ifpackages/app/dist/index.htmlexists (orOPENCODE_APP_DISTpoints at a directory that contains it), serve files from that directory with the same SPA fallback as before (unknown paths →index.html). Otherwise keep the existing proxy behavior.Flag.OPENCODE_APP_DISTinpackages/opencode/src/flag/flag.ts— Documents and centralizes the env var used for the absolute path override.- One log line when local dist is used (
serving web UI from local distwithroot) so operators can confirm the proxy is not in use. packages/app— Changelog fetch uses/changelog.json(frompublic/after build); notification and project avatar use same-origin favicon paths instead ofhttps://opencode.ai/..., so those requests stay on the server.docs/OFFLINE_WEB.md(English) — How to buildpackages/app, which env vars matter, and troubleshooting.CONTRIBUTING.md— Short subsection linking to that doc.
Why it works: The Vite production bundle is static files. Serving them from the same process that hosts the API avoids any dependency on app.opencode.ai for HTML/JS/CSS. The API routes are unchanged and still registered before the catch-all.
How did you verify your code works?
bun run buildinpackages/appsodist/index.htmlexists.OPENCODE_APP_DISTset to thatdistpath (or rely on default path frompackages/opencode), thenbun run --conditions=browser ./src/index.ts webfrompackages/opencode.- Confirmed the browser loads the app from
http://127.0.0.1:4096and the server logsserving web UI from local distonce. - With
distremoved or renamed, confirmed fallback still proxies (when network allows) so default behavior is preserved.
Screenshots / recordings
Optional: browser showing the app loaded from localhost while offline (no change to core UI layout intended).
Checklist
- [x] I have tested my changes locally
- [x] I have not included unrelated changes in this PR
Linked Issues
None.
Comments
No comments.
Changed Files
.gitignore
+3−0CONTRIBUTING.md
+4−0docs/OFFLINE_WEB.md
+82−0packages/app/public/changelog.json
+1−0packages/app/src/components/dialog-connect-provider.tsx
+1−1packages/app/src/components/dialog-custom-provider.tsx
+1−1packages/app/src/context/highlights.tsx
+1−1packages/app/src/entry.tsx
+1−1packages/app/src/pages/layout/sidebar-items.tsx
+1−1packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx
+1−1packages/opencode/src/flag/flag.ts
+2−0packages/opencode/src/server/server.ts
+40−6