feat(web-studio): bundle web-studio into docker, serve at /studio#2156
Merged
qin-ctx merged 2 commits intoMay 21, 2026
Conversation
…avicon to public
- Dockerfile: add node:20 build stage for web-studio, `vite build --base=/studio/`
output to /app/web-studio/dist. New ENV OPENVIKING_WEB_STUDIO_DIR.
- server/app.py: serve /studio and /studio/{path:path} from dist; SPA deep-link
fallback to index.html. Favicon routes (/favicon.ico, /favicon.png,
/apple-touch-icon.png, /mcp/favicon.ico+png+touch) read from the same dist —
no more separate console/static dependency.
- web-studio/public: ship favicon.ico, favicon-32.png, apple-touch-icon.png
inside the SPA bundle so they end up in dist root.
Old console (8020) untouched in this branch.
…efault ovClient was initialized with `baseUrl: ENV_BASE_URL || 'http://127.0.0.1:1933'`, which short-circuited normalizeBaseUrl's window.location.origin fallback. As a result, when web-studio was served by the OV server itself (e.g. bundled in the OV docker image at /studio/), the SPA would try to call back to the user's local 127.0.0.1:1933 instead of the same origin it was loaded from — making the bundled deployment unusable. Removing the literal fallback lets normalizeBaseUrl pick window.location.origin when ENV_BASE_URL is empty, which is the right default for every "served by OV" shape (bundled image, port-forwarded docker, reverse-proxied custom domain). Dev workflows running vite separately can opt in by setting VITE_OV_BASE_URL or overriding the URL in the in-app Connection dialog (which persists to localStorage).
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨No code suggestions found for the PR. |
qin-ctx
approved these changes
May 21, 2026
7 tasks
ZaynJarvis
added a commit
to ZaynJarvis/OpenViking
that referenced
this pull request
May 21, 2026
…o in pip, fix favicons The OpenViking docker image still launched the legacy `openviking/console` standalone service on port 8020. Now that web-studio is bundled into the OV server itself at /studio (see volcengine#2156), that process is redundant and the port is just a confusing artefact. This change retires the old console (python package + 8020 + console-frontend favicons) but **keeps the in-compose Caddy as a stable single-ingress on port 1934**, just simplified to one upstream now that there's no 8020. The server-side BFF at `openviking/server/routers/console.py` (under `/api/v1/console/*`) is also kept — web-studio uses the same endpoints. **The OAuth authorize page (`openviking/server/oauth/router.py`) is deliberately untouched in this PR** — the console-link button and Quick authorize same-origin panel will be re-pointed at web-studio in a focused follow-up. BREAKING CHANGES: - Port 8020 is gone from the docker image and docker-compose.yml; Caddy at 1934 now forwards everything to 1933 (web-studio lives at /studio there). Anything bookmarked at `http://host:8020/...` must migrate to `http://host:1933/studio/`. - `python -m openviking.console.bootstrap` no longer exists; the python package `openviking.console` has been removed. Pip packaging: - web-studio dist is now shipped inside the wheel under `openviking/web_studio/dist/` (mirroring the old `openviking/console/static/` layout). The dockerfile copies `--from=web-studio-builder /web-studio/dist` into the source tree before `uv sync`, so the wheel produced by the default docker build always carries the SPA. Building the wheel without running `npm run build` first leaves the directory empty, which gracefully degrades /studio to a 404 without breaking server startup. - Favicon assets (`favicon.ico` / `favicon-32.png` / `apple-touch-icon.png`, ~11 KB total) are duplicated into `openviking/server/static/` and shipped via package-data so `/favicon.*` and `/mcp/favicon.*` routes are always registered, regardless of whether the web-studio dist is bundled. - `pyproject.toml` and `setup.py` `package-data` drop `console/static/**` and add `server/static/**` + `web_studio/dist/**`. - New favicons (the 16/32/180 set in both `openviking/server/static/` and `web-studio/public/`) are downscaled from the canonical `web-studio/public/openviking-icon.png`, so the small-icon family matches the SPA's high-res rel="icon" target — the studio tab icon now stays consistent whether the browser uses the HTML link tag or falls back to auto-fetching `/favicon.ico`. Server: - `openviking/server/app.py` now reads `/studio` from `Path(__file__).parent.parent / 'web_studio' / 'dist'` by default; `OPENVIKING_WEB_STUDIO_DIR` still wins for dev mode pointing at a repo-local build. Favicon routes are unconditionally registered and load from `openviking/server/static/`. - `openviking/observability/usage_audit/projection.py` drops the legacy `/console/*` skip prefix (the BFF prefix `/api/v1/console/*` remains). Docker: - `web-studio-builder` stage moved earlier (Stage 2) so its dist can flow into `py-builder` before `uv sync` runs. - Runtime stage no longer separately copies the dist or sets `OPENVIKING_WEB_STUDIO_DIR`; the in-package path is the default. - Entrypoint renamed `openviking-console-entrypoint.sh` -> `openviking-entrypoint.sh` and stripped of the `python -m openviking.console.bootstrap` launch. - `EXPOSE 1933 8020` -> `EXPOSE 1933`. - `docker-compose.yml` drops the openviking service's 8020 port mapping; the caddy service stays but no longer needs port 8020 exposed. - `Caddyfile` simplified to a single `:1934 { reverse_proxy openviking:1933 }` — the legacy `/console/*` route to :8020 is gone. Docs: - en/zh quickstart updated to drop the 8020 mapping and explain that the API server now also serves `/studio`. - Other guides (`12-public-access.md`, `11-oauth.md`, `05-observability.md`, `04-setup-for-agent.md`, `03-deployment.md`) are intentionally left for a focused follow-up PR alongside the OAuth quick-authorize reintroduction. Tests: - Deleted `tests/misc/test_console_{proxy,static_assets}.py` (covered the removed console package). `tests/observability/test_console_router.py` stays — it covers the BFF, which remains.
ZaynJarvis
added a commit
to ZaynJarvis/OpenViking
that referenced
this pull request
May 21, 2026
…o in pip, fix favicons The OpenViking docker image still launched the legacy `openviking/console` standalone service on port 8020. Now that web-studio is bundled into the OV server itself at /studio (see volcengine#2156), that process is redundant and the port is just a confusing artefact. This change retires the old console (python package + 8020 + console-frontend favicons) but **keeps the in-compose Caddy as a stable single-ingress on port 1934**, just simplified to one upstream now that there's no 8020. The server-side BFF at `openviking/server/routers/console.py` (under `/api/v1/console/*`) is also kept — web-studio uses the same endpoints. **The OAuth authorize page (`openviking/server/oauth/router.py`) is deliberately untouched in this PR** — the console-link button and Quick authorize same-origin panel will be re-pointed at web-studio in a focused follow-up. BREAKING CHANGES: - Port 8020 is gone from the docker image and docker-compose.yml; Caddy at 1934 now forwards everything to 1933 (web-studio lives at /studio there). Anything bookmarked at `http://host:8020/...` must migrate to `http://host:1933/studio/`. - `python -m openviking.console.bootstrap` no longer exists; the python package `openviking.console` has been removed. Pip packaging: - web-studio dist is now shipped inside the wheel under `openviking/web_studio/dist/` (mirroring the old `openviking/console/static/` layout). The dockerfile copies `--from=web-studio-builder /web-studio/dist` into the source tree before `uv sync`, so the wheel produced by the default docker build always carries the SPA. Building the wheel without running `npm run build` first leaves the directory empty, which gracefully degrades /studio to a 404 without breaking server startup. - Favicon assets (`favicon.ico` / `favicon-32.png` / `apple-touch-icon.png`, ~11 KB total) are duplicated into `openviking/server/static/` and shipped via package-data so `/favicon.*` and `/mcp/favicon.*` routes are always registered, regardless of whether the web-studio dist is bundled. - `pyproject.toml` and `setup.py` `package-data` drop `console/static/**` and add `server/static/**` + `web_studio/dist/**`. - New favicons (the 16/32/180 set in both `openviking/server/static/` and `web-studio/public/`) are downscaled from the canonical `web-studio/public/openviking-icon.png`, so the small-icon family matches the SPA's high-res rel="icon" target — the studio tab icon now stays consistent whether the browser uses the HTML link tag or falls back to auto-fetching `/favicon.ico`. Server: - `openviking/server/app.py` now reads `/studio` from `Path(__file__).parent.parent / 'web_studio' / 'dist'` by default; `OPENVIKING_WEB_STUDIO_DIR` still wins for dev mode pointing at a repo-local build. Favicon routes are unconditionally registered and load from `openviking/server/static/`. - `openviking/observability/usage_audit/projection.py` drops the legacy `/console/*` skip prefix (the BFF prefix `/api/v1/console/*` remains). Docker: - `web-studio-builder` stage moved earlier (Stage 2) so its dist can flow into `py-builder` before `uv sync` runs. - Runtime stage no longer separately copies the dist or sets `OPENVIKING_WEB_STUDIO_DIR`; the in-package path is the default. - Entrypoint renamed `openviking-console-entrypoint.sh` -> `openviking-entrypoint.sh` and stripped of the `python -m openviking.console.bootstrap` launch. - `EXPOSE 1933 8020` -> `EXPOSE 1933`. - `docker-compose.yml` drops the openviking service's 8020 port mapping; the caddy service stays but no longer needs port 8020 exposed. - `Caddyfile` simplified to a single `:1934 { reverse_proxy openviking:1933 }` — the legacy `/console/*` route to :8020 is gone. Docs: - en/zh quickstart updated to drop the 8020 mapping and explain that the API server now also serves `/studio`. - Other guides (`12-public-access.md`, `11-oauth.md`, `05-observability.md`, `04-setup-for-agent.md`, `03-deployment.md`) are intentionally left for a focused follow-up PR alongside the OAuth quick-authorize reintroduction. Tests: - Deleted `tests/misc/test_console_{proxy,static_assets}.py` (covered the removed console package). `tests/observability/test_console_router.py` stays — it covers the BFF, which remains.
qin-ctx
pushed a commit
that referenced
this pull request
May 21, 2026
…o in pip, fix favicons (#2160) The OpenViking docker image still launched the legacy `openviking/console` standalone service on port 8020. Now that web-studio is bundled into the OV server itself at /studio (see #2156), that process is redundant and the port is just a confusing artefact. This change retires the old console (python package + 8020 + console-frontend favicons) but **keeps the in-compose Caddy as a stable single-ingress on port 1934**, just simplified to one upstream now that there's no 8020. The server-side BFF at `openviking/server/routers/console.py` (under `/api/v1/console/*`) is also kept — web-studio uses the same endpoints. **The OAuth authorize page (`openviking/server/oauth/router.py`) is deliberately untouched in this PR** — the console-link button and Quick authorize same-origin panel will be re-pointed at web-studio in a focused follow-up. BREAKING CHANGES: - Port 8020 is gone from the docker image and docker-compose.yml; Caddy at 1934 now forwards everything to 1933 (web-studio lives at /studio there). Anything bookmarked at `http://host:8020/...` must migrate to `http://host:1933/studio/`. - `python -m openviking.console.bootstrap` no longer exists; the python package `openviking.console` has been removed. Pip packaging: - web-studio dist is now shipped inside the wheel under `openviking/web_studio/dist/` (mirroring the old `openviking/console/static/` layout). The dockerfile copies `--from=web-studio-builder /web-studio/dist` into the source tree before `uv sync`, so the wheel produced by the default docker build always carries the SPA. Building the wheel without running `npm run build` first leaves the directory empty, which gracefully degrades /studio to a 404 without breaking server startup. - Favicon assets (`favicon.ico` / `favicon-32.png` / `apple-touch-icon.png`, ~11 KB total) are duplicated into `openviking/server/static/` and shipped via package-data so `/favicon.*` and `/mcp/favicon.*` routes are always registered, regardless of whether the web-studio dist is bundled. - `pyproject.toml` and `setup.py` `package-data` drop `console/static/**` and add `server/static/**` + `web_studio/dist/**`. - New favicons (the 16/32/180 set in both `openviking/server/static/` and `web-studio/public/`) are downscaled from the canonical `web-studio/public/openviking-icon.png`, so the small-icon family matches the SPA's high-res rel="icon" target — the studio tab icon now stays consistent whether the browser uses the HTML link tag or falls back to auto-fetching `/favicon.ico`. Server: - `openviking/server/app.py` now reads `/studio` from `Path(__file__).parent.parent / 'web_studio' / 'dist'` by default; `OPENVIKING_WEB_STUDIO_DIR` still wins for dev mode pointing at a repo-local build. Favicon routes are unconditionally registered and load from `openviking/server/static/`. - `openviking/observability/usage_audit/projection.py` drops the legacy `/console/*` skip prefix (the BFF prefix `/api/v1/console/*` remains). Docker: - `web-studio-builder` stage moved earlier (Stage 2) so its dist can flow into `py-builder` before `uv sync` runs. - Runtime stage no longer separately copies the dist or sets `OPENVIKING_WEB_STUDIO_DIR`; the in-package path is the default. - Entrypoint renamed `openviking-console-entrypoint.sh` -> `openviking-entrypoint.sh` and stripped of the `python -m openviking.console.bootstrap` launch. - `EXPOSE 1933 8020` -> `EXPOSE 1933`. - `docker-compose.yml` drops the openviking service's 8020 port mapping; the caddy service stays but no longer needs port 8020 exposed. - `Caddyfile` simplified to a single `:1934 { reverse_proxy openviking:1933 }` — the legacy `/console/*` route to :8020 is gone. Docs: - en/zh quickstart updated to drop the 8020 mapping and explain that the API server now also serves `/studio`. - Other guides (`12-public-access.md`, `11-oauth.md`, `05-observability.md`, `04-setup-for-agent.md`, `03-deployment.md`) are intentionally left for a focused follow-up PR alongside the OAuth quick-authorize reintroduction. Tests: - Deleted `tests/misc/test_console_{proxy,static_assets}.py` (covered the removed console package). `tests/observability/test_console_router.py` stays — it covers the BFF, which remains.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Bundles the
web-studioVite SPA into the OpenViking docker image and exposes it at/studio/on the same OV server origin (port 1933). After this change, running the image is enough to get both the API and the new web frontend on a single port — no separate hosting, no CORS dance, no extra deployment unit.Type of Change
Changes Made
web-studio-builderstage (node:20-bookworm-slim) runsnpm ci+npm run build -- --base=/studio/and emits/web-studio/dist. The runtime stage copies/web-studio/dist → /app/web-studio/distand exportsOPENVIKING_WEB_STUDIO_DIR=/app/web-studio/distso the server picks it up out-of-the-box. The npm install layer is cached on/root/.npmkeyed byTARGETPLATFORM, so rebuilds only re-run whenpackage.json/ lockfile change.openviking/server/app.py: whenOPENVIKING_WEB_STUDIO_DIR(or the in-repo fallback path) contains a builtdist/, register/studioand/studio/{path:path}handlers. The latter serves matching asset files when they exist, and falls back toindex.htmlfor unknown paths so TanStack Router deep-links survive a hard refresh.index.htmlis sent withCache-Control: no-storeto avoid stale shells. The legacyconsole/staticfavicon directory is replaced by the sameweb-studio/dist(web-studio now owns the canonical icons), so the top-level/favicon.*and/mcp/favicon.*routes stay backwards-compatible without a separate static folder.web-studio/public/: addfavicon.ico,favicon-32.png,apple-touch-icon.pngso the build emits the icon set the server expects.web-studio/src/lib/ov-client/client.ts: drop the hardcoded'http://127.0.0.1:1933'fallback in the module-levelovClientinitializer.normalizeBaseUrlalready falls back towindow.location.originin browsers, but the literal short-circuited it — so when the SPA was served by OV at/studio/, every API call still tried to hit the user's local 127.0.0.1:1933 and failed. Removing the literal makes the default same-origin, which is the right answer for every "served by OV" shape (docker bundle, port-forwarded docker, reverse-proxied custom domain). The in-app Connection dialog can still override the base URL at runtime (persisted tolocalStorage), so dev workflows running vite separately can either setVITE_OV_BASE_URLor just punch in the local URL once.Testing
web-studionpm run buildpassesGET /health→ 200GET /studio/→ 200 (SPA shell)GET /favicon.ico→ 200ov add-resource <file>→ upload + semantic/embedding queues drain successfullyov add-memory '<text>'→ 200, retrievable viaov find/studio/in a browser issues API calls back to the deployed origin (same-origin), not localhostAdditional Notes
<repo>/web-studio/distsonpm run buildinsideweb-studio/is enough to enable/studio/locally without setting any env var./consolestatic path is untouched. A follow-up PR can deprecate / removeopenviking/console/staticonce the team is comfortable.