> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aspfox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Environment Variables

> Every environment variable in .env.example, what it does, and example values.

Copy `.env.example` to `.env` and fill in the values. Variables marked **Required** must be set for the application to start. Optional variables enable specific features that degrade gracefully when absent.

<Note>
  Setting `ENVIRONMENT=Production` changes several behaviors: Swagger is disabled, detailed error messages are suppressed, and missing Stripe configuration throws on startup rather than logging a warning.
</Note>

## Database

| Variable            | Required     | Description                                               | Example                                                                |
| ------------------- | ------------ | --------------------------------------------------------- | ---------------------------------------------------------------------- |
| `DATABASE_URL`      | Yes          | Full PostgreSQL connection string                         | `Host=localhost;Port=5432;Database=acme;Username=acme;Password=secret` |
| `POSTGRES_DB`       | Yes (Docker) | Database name (used by the postgres Docker container)     | `acme`                                                                 |
| `POSTGRES_USER`     | Yes (Docker) | Database username (used by the postgres Docker container) | `acme`                                                                 |
| `POSTGRES_PASSWORD` | Yes (Docker) | Database password (used by the postgres Docker container) | `supersecretpassword`                                                  |

`DATABASE_URL` is used by the .NET application. `POSTGRES_DB`, `POSTGRES_USER`, and `POSTGRES_PASSWORD` are used by the `postgres` Docker container to initialize the database. They should be consistent with each other.

## Redis

| Variable         | Required | Description                                 | Example          |
| ---------------- | -------- | ------------------------------------------- | ---------------- |
| `REDIS_URL`      | Yes      | Redis connection string                     | `localhost:6379` |
| `REDIS_PASSWORD` | No       | Redis password if authentication is enabled | `redispassword`  |

For local development with the Docker Compose setup, use `REDIS_URL=redis:6379` (the service name). For production, use your Redis host and port.

## JWT

| Variable                          | Required | Description                                 | Example                      |
| --------------------------------- | -------- | ------------------------------------------- | ---------------------------- |
| `JWT_PRIVATE_KEY`                 | Yes      | Base64-encoded RSA private key (PEM format) | `LS0tLS1CRUdJTi…`            |
| `JWT_PUBLIC_KEY`                  | Yes      | Base64-encoded RSA public key (PEM format)  | `LS0tLS1CRUdJTi…`            |
| `JWT_ISSUER`                      | Yes      | Token issuer claim (`iss`)                  | `https://api.yourdomain.com` |
| `JWT_AUDIENCE`                    | Yes      | Token audience claim (`aud`)                | `https://yourdomain.com`     |
| `JWT_ACCESS_TOKEN_EXPIRY_MINUTES` | No       | Access token lifetime in minutes            | `15` (default)               |
| `JWT_REFRESH_TOKEN_EXPIRY_DAYS`   | No       | Refresh token lifetime in days              | `7` (default)                |

Both key variables must be base64-encoded PEM format with no line breaks. See [JWT Key Generation](/configuration/jwt-keys) for the exact commands.

## Stripe

| Variable                   | Required | Description                           | Example                        |
| -------------------------- | -------- | ------------------------------------- | ------------------------------ |
| `STRIPE_SECRET_KEY`        | Yes\*    | Stripe secret API key                 | `sk_test_51…` or `sk_live_51…` |
| `STRIPE_WEBHOOK_SECRET`    | Yes\*    | Stripe webhook signing secret         | `whsec_…`                      |
| `STRIPE_PRO_PRICE_ID`      | Yes\*    | Stripe Price ID for the Pro plan      | `price_1ABC…`                  |
| `STRIPE_BUSINESS_PRICE_ID` | Yes\*    | Stripe Price ID for the Business plan | `price_1DEF…`                  |

\*Required in `Production`. In `Development`, missing Stripe config logs a warning and the application starts; billing endpoints will return errors.

Test keys start with `sk_test_`. Live keys start with `sk_live_`. Never use live keys in development.

## Resend (email)

| Variable             | Required | Description                 | Example                  |
| -------------------- | -------- | --------------------------- | ------------------------ |
| `RESEND_API_KEY`     | Yes\*    | Resend API key              | `re_…`                   |
| `EMAIL_FROM_ADDRESS` | Yes\*    | Sending email address       | `noreply@yourdomain.com` |
| `EMAIL_FROM_NAME`    | No       | Display name in From header | `Acme`                   |

\*Required in `Production`. In `Development`, missing Resend config logs a warning; email sending fails silently and the error is logged.

For local development, you can use `onboarding@resend.dev` as `EMAIL_FROM_ADDRESS` without domain verification.

## OAuth

| Variable               | Required | Description                    | Example                                    |
| ---------------------- | -------- | ------------------------------ | ------------------------------------------ |
| `GOOGLE_CLIENT_ID`     | No       | Google OAuth 2.0 client ID     | `123456789-abc…apps.googleusercontent.com` |
| `GOOGLE_CLIENT_SECRET` | No       | Google OAuth 2.0 client secret | `GOCSPX-…`                                 |
| `GITHUB_CLIENT_ID`     | No       | GitHub OAuth App client ID     | `Iv1.abc123…`                              |
| `GITHUB_CLIENT_SECRET` | No       | GitHub OAuth App client secret | `abc123def456…`                            |

OAuth providers are optional. The application works without them — only the Google and GitHub login buttons on the login page will fail.

## Application

| Variable         | Required | Description                         | Example                                                 |
| ---------------- | -------- | ----------------------------------- | ------------------------------------------------------- |
| `APP_URL`        | Yes      | Frontend application URL            | `http://localhost:5173` or `https://app.yourdomain.com` |
| `API_URL`        | Yes      | Backend API URL                     | `http://localhost:5000` or `https://api.yourdomain.com` |
| `ENVIRONMENT`    | Yes      | `Development` or `Production`       | `Development`                                           |
| `ADMIN_EMAIL`    | No       | Overrides the seeded admin email    | `admin@yourdomain.com`                                  |
| `ADMIN_PASSWORD` | No       | Overrides the seeded admin password | A strong password                                       |

`APP_URL` is used in email templates to build links (e.g., the email verification link, magic link). `API_URL` is the backend's own base URL, used in OAuth callback construction.

## Frontend

| Variable       | Required | Description                                     | Example                                                 |
| -------------- | -------- | ----------------------------------------------- | ------------------------------------------------------- |
| `VITE_API_URL` | Yes      | Backend API URL, used by Vite and the React app | `http://localhost:5000` or `https://api.yourdomain.com` |

Vite only exposes environment variables prefixed with `VITE_` to the browser bundle. `VITE_API_URL` is the only frontend environment variable — everything else is server-side.
