Environment Variables
Load .env files, use typed imports, and understand the four-tier prefix system.
.env File Loading
Bosia loads environment variables from .env files in order (later overrides earlier):
.env.env.local.env.[mode](e.g..env.development,.env.production).env.[mode].local
System environment variables always take highest precedence — .env files never overwrite existing system vars.
Prefix System
Variable names control where and when they're available:
| Prefix | Client | Server | Timing | Example |
|---|---|---|---|---|
PUBLIC_STATIC_ |
Yes | Yes | Build-time | PUBLIC_STATIC_APP_NAME |
PUBLIC_ |
Yes | Yes | Runtime | PUBLIC_API_URL |
STATIC_ |
No | Yes | Build-time | STATIC_BUILD_ID |
| (no prefix) | No | Yes | Runtime | DATABASE_URL |
- Build-time variables are inlined during
bosia build— changing them requires a rebuild - Runtime variables are read from
process.envon each request - Client variables are safely exposed to the browser; Server variables never leave the server
Accessing Variables
Import from the $env virtual module:
import { PUBLIC_API_URL, DATABASE_URL } from "$env";Only variables declared in your .env files are available through this import. The module is type-safe with auto-generated type declarations.
Framework Variables
These variables are reserved by Bosia and control framework behavior:
| Variable | Default | Description |
|---|---|---|
PORT |
9000 |
Server port |
NODE_ENV |
— | development or production |
BODY_SIZE_LIMIT |
512K |
Max request body size (supports K, M, G, Infinity) |
IDLE_TIMEOUT |
10 |
Bun.serve idle timeout in seconds (max 255). Raise when API routes hold streaming responses with long gaps between chunks — e.g. an AI chat endpoint waiting for a tool call that shells out to bunx bosia add. Set to 0 to disable. |
MAX_INFLIGHT |
Infinity |
Soft cap on concurrent in-flight requests. When set, requests above the cap get a fast 503 Service Unavailable with Retry-After: 1 before any work is done — protects single-replica container deploys from OOM under traffic spikes. /_health is always exempt so orchestrator liveness probes keep working while the app sheds load. Pick a value below what your container's memory can support per concurrent SSR render (a safe starting point is 500; tune from there). |
CACHE_KEYS |
session,sid,auth,token,jwt,Authorization |
Comma-separated cookie/header names that contribute to the response cache identity. Pages with different values for any of these names are cached separately so per-user content never leaks. See Response cache. |
CACHE_MAX_ENTRIES |
500 |
LRU capacity of the in-memory response cache. Set to 0 to disable the cache entirely. Each entry holds raw + gzip + brotli bytes for one URL/identity pair. See Response cache. |
LOAD_TIMEOUT |
— | Timeout for load() in ms |
METADATA_TIMEOUT |
— | Timeout for metadata() in ms |
PRERENDER_TIMEOUT |
— | Timeout for prerender fetch in ms |
CSRF_ALLOWED_ORIGINS |
— | Comma-separated allowed origins for CSRF |
CORS_ALLOWED_ORIGINS |
— | Comma-separated allowed origins for CORS |
CORS_ALLOWED_METHODS |
— | Comma-separated allowed methods |
CORS_ALLOWED_HEADERS |
— | Comma-separated allowed headers |
CORS_EXPOSED_HEADERS |
— | Comma-separated exposed headers |
CORS_CREDENTIALS |
false |
Set to "true" to allow credentials |
CORS_MAX_AGE |
86400 |
Preflight cache duration in seconds |
TRUST_PROXY |
false |
Trust X-Forwarded-Host / X-Forwarded-Proto for CSRF origin checks. Only enable when behind a reverse proxy that strips client-supplied forwarded headers. See Security › Reverse-proxy deployments. |
DISABLE_X_FRAME_OPTIONS |
false |
Set to "true" to omit the X-Frame-Options: SAMEORIGIN header. Use when the app is intentionally embedded as an iframe by a different origin. See Security › Disabling X-Frame-Options. |
BOSIA_OUT_DIR |
./dist |
Build output directory (read by bosia build + bosia start). Use a custom path to run a verification build without colliding with a running bosia dev — e.g. BOSIA_OUT_DIR=.bosia/verify bun run build. bosia dev ignores this and always writes to .bosia/dev/. |
Framework variables are accessed via process.env directly, not through $env.
Example .env File
# Public — available on client and server at runtime
PUBLIC_API_URL=https://api.example.com
PUBLIC_APP_NAME=My App
# Public static — inlined at build time
PUBLIC_STATIC_VERSION=1.0.0
# Private — server only
DATABASE_URL=postgres://localhost:5432/mydb
# Also supported (see /guides/database):
# DATABASE_URL=mysql://user:pass@host:3306/mydb
# DATABASE_URL=sqlite://./data/app.db
# DATABASE_URL=sqlite://:memory: # dev/test only — flushes on restart
API_SECRET=sk_live_abc123
# Framework config
PORT=3000
BODY_SIZE_LIMIT=1M
CORS_ALLOWED_ORIGINS=https://app.example.comSecurity
Only PUBLIC_* variables declared in .env files are sent to the client. Variables set only as system env vars (not in .env files) are never exposed to the browser, even if they have a PUBLIC_ prefix.