# Environment Variables

All server config is validated at startup by `src/lib/env.ts` (zod). Invalid
config fails fast with the offending variable named. Copy `.env.example` →
`.env` for development. Real secrets live only in the deployment platform's
secret store.

| Variable | Required | Default | Purpose |
| --- | --- | --- | --- |
| `NODE_ENV` | no | development | Standard mode flag |
| `APP_NAME` | no | North West SEO | Server-side product name (emails, logs) |
| `NEXT_PUBLIC_APP_NAME` | no | North West SEO | Client-visible product name (rebrandable) |
| `APP_URL` | yes (prod) | http://localhost:3000 | Canonical origin; all email links derive from it |
| `NEXT_PUBLIC_APP_URL` | no | http://localhost:3000 | Client-side origin (robots.txt sitemap URL) |
| `COOKIE_DOMAIN` | no | unset | Only for cross-subdomain cookies (`.northwestcar.group`); applied in production only |
| `DATABASE_URL` | yes | local dev URL | PostgreSQL. Add `pgbouncer=true` behind transaction-mode poolers |
| `REDIS_URL` | yes for crawls | redis://localhost:6379 | BullMQ queue |
| `SESSION_COOKIE_NAME` | no | nws_session | |
| `SESSION_TTL_DAYS` | no | 30 | Server-enforced session expiry |
| `CREDENTIAL_ENCRYPTION_KEY` | yes when integrations enabled | unset | 64 hex chars; AES-256-GCM for stored integration credentials. Empty string = unset |
| `MAIL_FROM` | no | seo@northwestcar.group | Sender identity |
| `SMTP_URL` | prod | unset | Unset ⇒ dev mailer logs emails to console |
| `CRAWLER_USER_AGENT` | no | NorthWestSEOBot/1.0 (+https://seo.northwestcar.group/bot) | Identifying UA |
| `CRAWLER_MAX_REDIRECTS` | no | 5 | Per-fetch redirect cap |
| `CRAWLER_MAX_RESPONSE_BYTES` | no | 5242880 | Per-page download cap |
| `CRAWLER_CONNECT_TIMEOUT_MS` | no | 10000 | |
| `CRAWLER_READ_TIMEOUT_MS` | no | 20000 | |
| `LOG_LEVEL` | no | debug (dev) / info (prod) | pino level |

Per-environment values:

```env
# Development
APP_URL="http://localhost:3000"

# Staging
APP_URL="https://seo-staging.northwestcar.group"

# Production
APP_URL="https://seo.northwestcar.group"
```

Generate the encryption key once per environment:

```bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
