From 950aa1e950c8ccae0bcc8c780e405a61719533b8 Mon Sep 17 00:00:00 2001 From: Alexey Volkov Date: Thu, 19 Mar 2026 01:34:28 -0700 Subject: [PATCH 1/2] feat: App - Support setting base URL during build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed to host OpenCode app under under some URL prefix. This minimal change makes it possible to build OpenCode Web App with VITE_BASE_URL="/subdir/" and have it run under `http://:/subdir/` instead of root (`http://:/`). Set `VITE_BASE_URL` env var during build. This automatically sets the `base` in Vite config. Vite generates correct URLs in `index.html`. `import.meta.env.BASE_URL` is also used in routers. See https://vite.dev/config/shared-options#base You can also set `VITE_OPENCODE_SERVER_BASE_URL` to specify the base URL prefix for the server. Usage: ``` % VITE_BASE_URL="/XXX" VITE_OPENCODE_SERVER_BASE_URL="/" bun dev $ vite (!) "base" option should start with a slash. VITE v7.1.4 ready in 320 ms ➜ Local: http://localhost:3000/XXX ``` --- packages/app/src/app.tsx | 1 + packages/app/src/entry.tsx | 6 ++++-- packages/app/src/env.d.ts | 1 + packages/app/vite.config.ts | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx index e370862212b..21a9fd3b3a4 100644 --- a/packages/app/src/app.tsx +++ b/packages/app/src/app.tsx @@ -279,6 +279,7 @@ export function AppInterface(props: { {routerProps.children}} > diff --git a/packages/app/src/entry.tsx b/packages/app/src/entry.tsx index b5cbed6e75d..f62dc78b024 100644 --- a/packages/app/src/entry.tsx +++ b/packages/app/src/entry.tsx @@ -99,9 +99,11 @@ if (!(root instanceof HTMLElement) && import.meta.env.DEV) { const getCurrentUrl = () => { if (location.hostname.includes("opencode.ai")) return "http://localhost:4096" + const serverBaseUrl = + "/" + (import.meta.env.VITE_OPENCODE_SERVER_BASE_URL ?? "/").replace(/^\//, "").replace(/\/$/, "") if (import.meta.env.DEV) - return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}` - return location.origin + return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}{serverBaseUrl}` + return location.origin + serverBaseUrl } const getDefaultUrl = () => { diff --git a/packages/app/src/env.d.ts b/packages/app/src/env.d.ts index 89721f34f29..c8d0a7d2414 100644 --- a/packages/app/src/env.d.ts +++ b/packages/app/src/env.d.ts @@ -1,6 +1,7 @@ import "solid-js" interface ImportMetaEnv { + readonly BASE_URL: string readonly VITE_OPENCODE_SERVER_HOST: string readonly VITE_OPENCODE_SERVER_PORT: string } diff --git a/packages/app/vite.config.ts b/packages/app/vite.config.ts index 6a29ae6345e..9c0685aa034 100644 --- a/packages/app/vite.config.ts +++ b/packages/app/vite.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from "vite" import desktopPlugin from "./vite" export default defineConfig({ + base: process.env.VITE_BASE_URL || "/", plugins: [desktopPlugin] as any, server: { host: "0.0.0.0", From ae08d12ea1d002f68c4021e91eb1c04fbf570953 Mon Sep 17 00:00:00 2001 From: Alexey Volkov Date: Thu, 19 Mar 2026 02:27:48 -0700 Subject: [PATCH 2/2] Normalized the URL slashes --- packages/app/src/entry.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/app/src/entry.tsx b/packages/app/src/entry.tsx index f62dc78b024..d08ccaf1794 100644 --- a/packages/app/src/entry.tsx +++ b/packages/app/src/entry.tsx @@ -98,9 +98,10 @@ if (!(root instanceof HTMLElement) && import.meta.env.DEV) { } const getCurrentUrl = () => { + let serverBaseUrl = import.meta.env.VITE_OPENCODE_SERVER_BASE_URL ?? "" + // Normalizing slashes. Add starting slash if needed, remove trailing slash. Default value will be empty string. + serverBaseUrl = ("/" + serverBaseUrl.replace(/^\//, "")).replace(/\/$/, "") if (location.hostname.includes("opencode.ai")) return "http://localhost:4096" - const serverBaseUrl = - "/" + (import.meta.env.VITE_OPENCODE_SERVER_BASE_URL ?? "/").replace(/^\//, "").replace(/\/$/, "") if (import.meta.env.DEV) return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}{serverBaseUrl}` return location.origin + serverBaseUrl