# Environment Variables

Vela uses environment variables to configure the project. The environment variables are stored in the local `.env` file by default. The Vela CLI and PocketBase backend rely on the following environment variables:

```ts
POCKETBASE_URL=http://localhost:8090
POCKETBASE_SUPERUSER_EMAIL=admin@example.com
POCKETBASE_SUPERUSER_PASSWORD=password
```

You'll be prompted to create a PocketBase superuser account by whichever command gives the project its database — [`vela create`](/docs/create) for a new project, [`vela bless`](/docs/bless) for an existing SvelteKit one, or [`vela enable backend`](/docs/enable/backend) for a project that had no backend. The login details are saved in the `.env` file. The superuser account is used by the CLI, the admin interface and the REST API.

### One model, three environments

Everything that differs between environments is an environment variable, for the app and for PocketBase alike. What is the same everywhere — the app's name, its canonical URL — is code, in [`src/lib/site.ts`](/docs/cli/project-structure). The database keeps only what an admin changes at runtime, such as the backup schedule. There is no project config file.

- **Locally**, `.env`, gitignored. `.env.example` is committed and documents what the app reads; it is a nudge, not a contract — a project's own example is full of keys it means to leave unset.
- **On a server**, three layers per target managed with [`vela env`](/docs/env): one every target shares (`-t all`), one every preview shares (`-t preview`), and the instance's own. A higher layer wins. Values are secret unless set `--public`; `PUBLIC_*` keys are public regardless.
- **Derived** by Vela, never typed: `ORIGIN`, `POCKETBASE_URL`, `PORT`, `VELA_ENV`, `VELA_APP_ID`, `VELA_RELEASE`, `VELA_DATA_DIR`, and PocketBase's app URL.

The repository never carries environment but `.env.example`. A build runs with the target's environment, not your `.env`: see [`vela deploy`](/docs/deploy).

### PocketBase

With a backend, PocketBase reads its own settings from the same environment and shows them locked in the [admin panel](/docs/admin). `APP_NAME` and `APP_URL` are plain; the rest is `PB_`-prefixed so that an app's own `SMTP_HOST` or `S3_BUCKET` cannot switch PocketBase mail or storage on.

```ts
APP_NAME=My App                 # from src/lib/site.ts, set by vela dev and vela deploy
APP_URL=https://example.com     # defaults to ORIGIN, the address the instance is served on
PB_SENDER_NAME=My App
PB_SENDER_ADDRESS=hello@example.com
PB_SMTP_HOST=smtp.example.com   # setting it turns SMTP on
PB_SMTP_PORT=587
PB_SMTP_USERNAME=
PB_SMTP_PASSWORD=
PB_SMTP_TLS=true
PB_S3_ENDPOINT=                 # setting it moves uploads to the bucket
PB_S3_BUCKET=
PB_S3_REGION=
PB_S3_ACCESS_KEY=
PB_S3_SECRET=
PB_S3_FORCE_PATH_STYLE=false
PB_BACKUPS_S3_*                 # the same six, for where backups are kept
```

The WhatsApp plugin reads `WHATSAPP_MODE`, `VELASTACK_API_KEY`, `VELASTACK_RELAY_URL` and `WHATSAPP_PHONE_NUMBER_ID`, `WHATSAPP_WABA_ID`, `WHATSAPP_ACCESS_TOKEN`, `WHATSAPP_TEMPLATE_NAME`, `WHATSAPP_TEMPLATE_LANGUAGES`, `WHATSAPP_GRAPH_VERSION`. With `WHATSAPP_MODE` unset, the credentials pick the sender: `VELASTACK_API_KEY` selects VelaStack, `WHATSAPP_ACCESS_TOKEN` the direct Cloud API. Locally, `WHATSAPP_MODE=dev` logs the codes instead of sending them.

Booleans accept `true`, `1` or `yes`. A variable that is set but empty still counts as set.

### Workflows

The [workflow](/docs/workflows) worker reads two optional variables:

```ts
WORKFLOWS_CONCURRENCY=5
WORKFLOWS_ENABLED=true
```

`WORKFLOWS_CONCURRENCY` caps how many runs one server executes at once. `WORKFLOWS_ENABLED=false` keeps a server from executing runs while still letting it queue them.