---
title: "Environment variables"
description: "Every env var Taman reads, where it is defined, and whether you must set it."
canonical_url: "https://vinicunca.dev/taman/getting-started/environment-variables"
---
# Environment variables

> Every env var Taman reads, where it is defined, and whether you must set it.

`create-taman` copies each `.env*.example` to a sibling `.env`. Review those files before deploying. Nitro maps `NITRO_*` names onto `runtimeConfig` (so `NITRO_DATABASE_URL` becomes `runtimeConfig.databaseUrl`).

## API (`apps/api/.env`)

Read via `useRuntimeConfig()` in `apps/api/nitro.config.ts` and `server/auth/better-auth.instance.ts`.

**NITRO_DATABASE_URL** (`string`) *required*: Postgres URL. Default matches Docker Compose: postgresql://postgres:postgres@localhost:5437/taman_db. Also accepted as DATABASE_URL by the seed scripts.

**NITRO_TRUSTED_ORIGINS** (`string`) *required*: Comma-separated browser origins allowed to call the API. Default: http://localhost:5556,http://localhost:5560 (the dev server and the Playwright e2e server). Empty after trim means no origins (CORS allow-list is empty); there is no localhost fallback.

**NITRO_BASE_URL** (`string`) *required*: Public URL of this API. better-auth baseURL. Default: http://localhost:8788.

**NITRO_APP_URL** (`string`) *required*: Public URL of the web app (invitation links). Default: http://localhost:5556.

**NITRO_BETTER_AUTH_SECRET** (`string`) *required*: better-auth secret. At least 32 random characters (openssl rand -base64 32). The example value is a placeholder.

**NITRO_GOOGLE_CLIENT_ID** (`string`): Google OAuth client ID. Empty disables a working Google login until you set both Google vars.

**NITRO_GOOGLE_CLIENT_SECRET** (`string`): Google OAuth client secret.

**NITRO_EMAIL_FROM** (`string`) *required*: From address for transactional email. Default: no-reply@example.com.

**NITRO_EMAIL_FROM_NAME** (`string`): From display name. Default: Taman (rewritten to the project name on generate).

Cloudflare bindings (`TODO_PUBLISHER`, `EMAIL_QUEUE`, `EMAIL`) come from `nitro.config.ts` wrangler config, not `.env`.

## Database package (`packages/server/db-pg/.env`)

Used by drizzle-kit (`studio`, `generate`, `migrate`).

**DATABASE_URL** (`string`) *required*: Same Postgres URL as the API. Default: postgresql://postgres:postgres@localhost:5437/taman_db. drizzle.config.ts throws if this is unset. UAT/prod nx configurations read .env.uat / .env.prod instead.

## Web — shared (`apps/web/.env.example`)

Always loaded. Used for storage keys and the document title.

**VITE_APP_TITLE** (`string`) *required*: Browser tab title and PWA manifest name. Default: Taman.

**VITE_APP_NAMESPACE** (`string`) *required*: Prefix for preferences and store keys. Combined in main.ts as ${namespace}-${version}-${dev|prod}. Default: taman.

**VITE_APP_STORE_SECURE_KEY** (`string`) *required*: Encrypts persisted Pinia state via secure-ls. Replace before production.

## Web — development (`apps/web/.env.development.example`)

Loaded in `vite --mode development`.

**VITE_PORT** (`number`): Dev server port. Default in this file: 5556. vite-config's own fallback is 5173 if unset.

**VITE_BASE** (`string`): Vite base. Default: /.

**VITE_API_URL** (`string`) *required*: API origin used by the oRPC and better-auth clients. Default: http://localhost:8788.

**VITE_NITRO_MOCK** (`boolean`): Nitro mock flag. Default: false.

**VITE_DEVTOOLS** (`boolean`): Vue DevTools plugin. Default: true.

**VITE_INJECT_APP_LOADING** (`boolean`): Injects the loading screen. Default: true.

## Web — production (`apps/web/.env.production.example`)

Loaded in `vite build --mode production`.

**VITE_BASE** (`string`): Same as development.

**VITE_API_URL** (`string`) *required*: Public API URL, e.g. https://api.example.com.

**VITE_COMPRESS** (`string`): Comma-separated gzip / brotli, or none. Default: none.

**VITE_PWA** (`boolean`): Enable vite-plugin-pwa. Default: false.

**VITE_ROUTER_HISTORY** (`string`): hash or history. Default in this file: hash.

**VITE_INJECT_APP_LOADING** (`boolean`): Default: true.

**VITE_ARCHIVER** (`boolean`): Zip dist after build. Default: false.

## Runtime contracts (vite-config)

These names are emitted by `@vinicunca/vite-config` and read by Taman packages:

- `window._TAMAN_ADMIN_DEV_CONFIG_` — in production builds, `VITE_GLOB_*` values are written to `_app-config-[version]-[hash].js` so they can change without a rebuild.
- `__TAMAN_METADATA__` — author, version, build time, dependency versions.
- Loading screen dark-mode key: `localStorage["${VITE_APP_NAMESPACE}-${version}-${dev|prod}-preferences-theme"]`.

See [vite-config](https://vinicunca.dev/taman/packages/tooling) for the full option table.


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
