Environment variables
What each setting in the API's and the dashboard's .env files does, which ones you need, and the Docker Compose options.
For the Full Stack package
Where the settings live
| File | Read by | Holds secrets |
|---|---|---|
back-end/.env | The API, with yarn dev and inside Docker Compose | Yes. Never commit it. |
front-end/.env | The dashboard. Its NEXT_PUBLIC_* values are compiled in at build time | Only WEATHER_API_KEY, which stays on the dashboard's server |
.env beside docker-compose.yml | Docker Compose, for both apps | Only WEATHER_API_KEY |
Create each app's file from the .env.example beside it, which documents every variable: cp .env.example .env. The examples work as they are for a local run. None of the files is needed for Docker Compose.
Where the settings live
One optional file, .env in the dashboard's folder. With no file, the dashboard runs on its built-in mock API. .env.example points it at an API on http://localhost:8000: copy it with cp .env.example .env when you have one.
With Docker, the NEXT_PUBLIC_* values are build arguments (docker build --build-arg NAME=value), and WEATHER_API_KEY is a run option (docker run -e WEATHER_API_KEY=...).
API essentials
The API checks JWT_SECRET and, in production, CORS_ORIGIN before it starts. If one is missing or unusable, it stops with one line saying what to fix. Variables already set in the process, by Docker or a host, win over the file.
| Variable | Default | What it does |
|---|---|---|
NODE_ENV | development | development creates and updates the tables on start. production never touches the tables, and refuses to start on the example JWT_SECRET or without CORS_ORIGIN. |
PORT | 8000 | The API's port. The dashboard points at it. |
DB_TYPE | sqlite | sqlite or mysql. |
SQLITE_DATABASE | ./database.sqlite | The SQLite file, relative to back-end. |
JWT_SECRET | The example value | Signs every sign-in. Required. The example value is accepted outside production only. |
JWT_EXPIRATION | 7d | How long a sign-in lasts. |
CORS_ORIGIN | http://localhost:3030 | The dashboard's address, comma separated if there are several. Required in production. |
FRONTEND_URL | http://localhost:3030 | The one address the live permission updates accept: the dashboard's. |
RATE_LIMIT_LOGIN | 10 | Failed sign-ins one address may make in 15 minutes before the sign-in answers 429. |
TRUST_PROXY | Empty | The number of reverse proxies in front of the API, such as 1 behind Nginx or Caddy, so the sign-in limit counts visitors rather than the proxy. |
Generate your own JWT_SECRET with:
node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"Before going live. Every seed (yarn seed, yarn seed:prod and the first Docker start) creates the sample admins with the passwords printed in the guides. Change their passwords or delete them, and set your own JWT_SECRET, before the dashboard is reachable by anyone else.
Use MySQL instead of SQLite
Create an empty database, then set the driver and the connection in back-end/.env:
DB_TYPE=mysql
DB_HOST=your-mysql-host
DB_PORT=3306
DB_USERNAME=your-mysql-username
DB_PASSWORD=your-mysql-password
DB_DATABASE=your-database-nameThen run yarn seed, which creates the tables and the sample data. The running API creates and updates the tables itself only with NODE_ENV=development, so with NODE_ENV=production run yarn seed:prod once after yarn build, before the first start.
The dashboard
Every NEXT_PUBLIC_* value is compiled into the JavaScript the browser loads, and anyone who opens the page can read it. Never put a secret in one, and restart yarn dev or rebuild after changing one.
| Variable | Default | What it does |
|---|---|---|
NEXT_PUBLIC_API_BASE_URL | Empty: the mock API | The API's address including /api, such as http://localhost:8000/api. Empty runs the dashboard on its built-in mock API with sample data. |
NEXT_PUBLIC_WEBSOCKET_BASE_URL | The API's address without /api | The API server, for the live permission updates. Unused on the mock API. |
NEXT_PUBLIC_BASE_URL | http://localhost:3030 | The dashboard's own public address, without a trailing slash. robots.txt, the sitemap and absolute metadata addresses are built from it. |
WEATHER_API_KEY | Empty | A WeatherAPI.com key for the weather in the overview's greeting, read on the dashboard's server only. Empty leaves the weather out. |
PORT | 3030 | The port yarn dev and yarn start use. |
BUILD_STANDALONE | Unset | true makes yarn build emit a self-contained server, which the Dockerfile sets. Leave it unset otherwise. |
There are no AI provider keys in the dashboard: they live in the API's .env only.
Docker Compose options
Nothing has to be set for a local run. To change something, put it in a .env file in the dashboard-2-full-stack folder, beside docker-compose.yml, and run docker compose up --build again: the dashboard compiles the API's address in.
| Variable | Default | What it does |
|---|---|---|
DASHBOARD_PORT | 3030 | The dashboard's port on your computer. |
API_PORT | 8000 | The API's port on your computer. |
DASHBOARD_URL | http://localhost: and DASHBOARD_PORT | Where the browser reaches the dashboard. The API's CORS_ORIGIN and FRONTEND_URL, and the dashboard's own address, are set from it. |
API_URL | http://localhost: and API_PORT | Where the browser reaches the API. The dashboard is built with it, followed by /api. |
WEATHER_API_KEY | Empty | The weather in the overview's greeting. |
DASHBOARD_PORT=3040Change a port when another program already uses it, as above. Set DASHBOARD_URL and API_URL both when you serve the stack on your own domains.
The API container also reads back-end/.env when it exists, so the AI keys, R2 and the MCP key are set in one place for yarn dev and Docker. The compose file wins for the values that differ inside a container: NODE_ENV=production, the port, the SQLite file in the dashboard-2-data volume, the two addresses above, and demo mode, which it keeps off. Without a JWT_SECRET of your own, the API generates one and keeps it in the volume.
Image uploads
Profile pictures and the assistant's image attachments are stored in a Cloudflare R2 bucket. Set all five variables; without them the upload answers that it is not set up, and everything else works.
R2_ACCESS_KEY_ID=your-r2-access-key-id
R2_SECRET_ACCESS_KEY=your-r2-secret-access-key
R2_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
R2_BUCKET_NAME=your-bucket-name
R2_PUBLIC_URL=https://your-public-url.r2.devR2_PUBLIC_URL is the bucket's public address, so the bucket must allow public reads. Each upload is an image of at most 10 MB, saved as a JPEG of at most 1920 pixels wide, with a smaller copy beside it.
AI assistant keys
Included with your purchase. Sign in to read, or open it in your download.
Which variables turn on each AI provider, and what happens when one is left empty.
The MCP server
Included with your purchase. Sign in to read, or open it in your download.
Letting coding agents and other MCP clients use the assistant's tools: the key and the endpoint.
Demo mode
Included with your purchase. Sign in to read, or open it in your download.
Running a public demo: the demo switches, the free assistant messages per visitor, and what visitors can change.