# Frontend Configuration

The frontend is configured through environment variables. The canonical list and
defaults live in
[`frontend/.env.example`](https://github.com/vibexp/vibexp/blob/main/frontend/.env.example).

## Build-time vs runtime

This is the most important distinction:

- **`VITE_*` variables are inlined at _build_ time.** They are baked into the
  JavaScript bundle when `vite build` runs. In practice you set them in
  `frontend/.env` for **local development** (the Vite dev server reads them);
  the published image bakes only deployment-neutral values.
- **Deploy-time values come from the _runtime_ `/config.js`.** In production the
  backend renders `/config.js` from its `frontend.*` configuration (see
  [Backend Configuration](/docs/developer-guide/backend/configuration/)), setting
  `window.__VIBEXP_ENV__` before the SPA bundle runs. The MCP endpoint and
  analytics are injected this way — changing them needs a restart, **not a
  rebuild**. In local dev there is no backend-rendered
  `/config.js` (the request 404s harmlessly) and the app falls back to the
  build-time `import.meta.env` values.

:::tip[Why the API base URL is relative]
The published image is built with `VITE_API_BASE_URL=/api/v1` so requests are
same-origin — the backend serves the SPA and the API from the same port. Do not
hardcode a backend origin into the build. See
[Building & Serving](/docs/developer-guide/frontend/building/).
:::

## Backend API

| Variable | Default | Notes |
|---|---|---|
| `VITE_API_BASE_URL` | `/api/v1` (image build) | Backend API base, including version prefix. Leave empty/relative for same-origin requests (the combined image). The local-dev `.env.example` points it at `http://localhost:8080/api/v1`, targeting `make backend-run-dev`. |

## Release stamps

Build-time only, set by the release pipeline (build args in
`backend/Dockerfile`); shown in the UI for support/debugging.

| Variable | Default | Notes |
|---|---|---|
| `VITE_RELEASE_SHA` | `dev` | Commit SHA of the build. `release.yml` passes `github.sha`. |
| `VITE_RELEASE_DATE` | `unknown` | Build date stamp. |

## Branding

Company branding is not a `VITE_*` variable. Since v0.15.0 the name, logo and
support and legal links are the instance's **site info**, which an instance
admin edits in the admin area: see
[Site Info (Branding)](/docs/user-guide/self-hosting/site-info/).

The backend inlines the eight values into the same `/config.js`, as
`window.__VIBEXP_SITE_INFO__`, so the first paint is already branded, and
serves them again at `GET /api/v1/site-info`. Components read them through the
`useSiteInfo()` hook, never from `getEnv()`. In local dev, where there is no
backend-rendered `/config.js`, the app starts unbranded.

## MCP

| Variable | Notes |
|---|---|
| `VITE_MCP_ENDPOINT` | The MCP endpoint advertised in client-setup snippets, e.g. `https://<your-mcp-host>/mcp/v1/common`. Runtime-injectable via `frontend.mcp_endpoint`. |

## Error reporting / problem details

| Variable | Notes |
|---|---|
| `VITE_ERROR_TYPE_BASE_URI` | Base URI for building RFC 9457 problem-detail `type` fields client-side (e.g. `<base>/errors/UNKNOWN`). Empty falls back to `about:blank`. |

## Analytics (Google Tag Manager / GA4)

Off by default: set a container ID to opt in. Runtime-injectable via the
backend's `frontend.gtm_id` / `frontend.ga4_measurement_id` config.

| Variable | Default | Notes |
|---|---|---|
| `VITE_GTM_ID` | — | GTM container ID (e.g. `GTM-XXXXXXX`). Setting it **is** the opt-in: GTM loads only when it is non-empty. There is no separate enable flag. |
| `VITE_GA4_MEASUREMENT_ID` | — | GA4 Measurement ID (e.g. `G-XXXXXXXXXX`) for client-ID capture. |

VibeXP ships no cookie-consent gate of its own: once an ID is set, the tag loads
unconditionally. If your deployment needs Consent Mode, configure it inside your
own GTM container.

## Web push (removed)

Browser push notifications (Firebase Cloud Messaging) were **removed in
v0.9.0** along with the seven `VITE_FIREBASE_*` variables.
`src/utils/serviceWorker.ts` and `public/{sw,dev-sw}.js` still exist solely to
evict legacy workers from returning browsers.

## Related

- [Frontend Overview](/docs/developer-guide/frontend/overview/)
- [Building & Serving](/docs/developer-guide/frontend/building/)
- [Backend Configuration](/docs/developer-guide/backend/configuration/)