Skip to content

Configure the Environment ​

TT Time Tracker uses a single environment file, .env, at the repo root. The NestJS API and BullMQ worker load it at runtime; the Vue frontend's VITE_* values are inlined into the client at build time.

Copy from the template:

bash
cp .env.example .env

Frontend (VITE_*) ​

VariableRequiredDefaultDescription
VITE_APP_VERSIONNo0.0.0Version string shown in the UI.

The client talks to the API over a relative /api path (reverse-proxied to the NestJS service on the same origin), so there is no API-URL variable to set.

WARNING

VITE_* variables are inlined at build time. If you change them, you must rebuild the frontend. They are visible in the compiled JavaScript — do not put secrets here.

Backend ​

Required ​

VariableDescription
DATABASE_URLPostgreSQL connection string, e.g. postgresql://tt:password@localhost:5432/tt?schema=public
POSTGRES_PASSWORDPassword for the postgres Docker container (must match DATABASE_URL)
REDIS_URLRedis connection string, e.g. redis://localhost:6379
BETTER_AUTH_SECRETSession signing secret. Generate with openssl rand -base64 32. Minimum 32 characters.
BETTER_AUTH_URLPublic URL of the API, e.g. http://localhost:3000. Used for OAuth redirect URIs.
RUSTFS_ACCESS_KEYAccess key for the S3-compatible file store.
RUSTFS_SECRET_KEYSecret key for the S3-compatible file store.

Google OAuth (required for login) ​

VariableDescription
GOOGLE_CLIENT_IDOAuth client ID from Google Cloud Console
GOOGLE_CLIENT_SECRETOAuth client secret

Create credentials at console.cloud.google.com → APIs & Services → Credentials → Create OAuth 2.0 Client. Set the authorized redirect URI to {BETTER_AUTH_URL}/api/auth/callback/google.

File storage ​

VariableDefaultDescription
RUSTFS_ENDPOINThttp://localhost:9000S3-compatible storage endpoint
RUSTFS_BUCKETtt-invoicesBucket name for invoice files

In production you can point this at AWS S3 or MinIO by changing RUSTFS_ENDPOINT and using the appropriate credentials.

AI invoice extraction ​

VariableDescription
OPENROUTER_KEYOpenRouter API key for extracting structured data from invoices
EXTRACTION_MODELOptional model override (default: google/gemini-2.5-flash)
EXTRACTION_FALLBACK_MODELOptional fallback model (default: openai/gpt-5-mini)

The key is required to run the worker — it refuses to boot without it. The API and client run fine without the worker; uploaded invoices then simply stay unprocessed until a worker is running.

(GOOGLE_APPLICATION_CREDENTIALS is not an app variable — it is only used by the one-off scripts/data-migration Firestore→Postgres tooling, which authenticates to Firebase via Google application-default credentials.)

Observability (optional) ​

All observability integrations are no-ops when their environment variables are unset — safe to skip in local development.

VariableDescription
SENTRY_DSNSentry DSN for backend (api + worker) error tracking
SENTRY_DSN_FRONTENDSentry DSN for frontend error tracking (returned via /config)

TT Time Tracker — Internal Documentation