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

# Environment Variables

> Complete reference for CharleOS configuration

CharleOS uses environment variables for configuration. The `.env.local` file is included in the repository and pre-configured for local development.

<Info>
  The `.env.local` file is already set up for local development. You typically don't need to modify these values unless you're setting up integrations or testing specific features.
</Info>

## Core Configuration

### Database

| Variable       | Value                        | Description                                        |
| -------------- | ---------------------------- | -------------------------------------------------- |
| `DATABASE_URL` | PostgreSQL connection string | Connection to Neon database (DEV branch for local) |

**Local development:**

* Uses the **DEV branch** of the Neon database
* Safe to experiment without affecting production data
* Automatically configured in `.env.local`

### Authentication

| Variable                        | Value                           | Description                          |
| ------------------------------- | ------------------------------- | ------------------------------------ |
| `BETTER_AUTH_SECRET`            | Random 32+ char string          | Secret for encrypting sessions       |
| `BETTER_AUTH_URL`               | `http://localhost:3000`         | Base URL for auth server             |
| `NEXT_PUBLIC_BETTER_AUTH_URL`   | `http://localhost:3000`         | Public-facing auth URL (client-side) |
| `NEXT_PUBLIC_APP_URL`           | `http://localhost:3000`         | Main app URL                         |
| `NEXT_PUBLIC_CLIENT_PORTAL_URL` | `http://clients.localhost:3000` | Client portal URL                    |

<Warning>
  **Local vs Production:**\
  Auth URLs must be `http://localhost:3000` for local development.\
  Production uses `https://charle.agency`.\
  Never use production URLs locally or you'll get CORS errors.
</Warning>

### Google OAuth

| Variable               | Description                               |
| ---------------------- | ----------------------------------------- |
| `GOOGLE_CLIENT_ID`     | OAuth client ID from Google Cloud Console |
| `GOOGLE_CLIENT_SECRET` | OAuth client secret                       |

**How to get these:**

1. Go to [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
2. Select the CharleOS project
3. Find the OAuth 2.0 Client ID credentials

<Note>
  Only **@charle.co.uk** email addresses are allowed to sign in.
</Note>

## Integrations

### Cloudflare R2 (File Storage)

| Variable                   | Description                                                             |
| -------------------------- | ----------------------------------------------------------------------- |
| `CLOUDFLARE_WORKER_URL`    | URL of the R2 API worker (`https://r2-api.charle.agency`)               |
| `R2_UPLOAD_SECRET`         | Shared secret for worker authentication                                 |
| `CLOUDFLARE_R2_PUBLIC_URL` | Public URL for accessing uploaded files (`https://files.charle.agency`) |

**What it's for:**

* Stores file attachments (task attachments, ticket files, etc.)
* Accessed via a Cloudflare Worker for security
* Files are served from `files.charle.agency`

**Architecture:**

```
CharleOS → Worker (r2-api.charle.agency) → R2 Bucket → Public URL (files.charle.agency)
```

### Pusher (Real-time & Notifications)

CharleOS uses Pusher for two purposes:

#### Pusher Channels (Real-time updates)

| Variable                     | Description                  |
| ---------------------------- | ---------------------------- |
| `NEXT_PUBLIC_PUSHER_KEY`     | Public API key (client-side) |
| `NEXT_PUBLIC_PUSHER_CLUSTER` | Server cluster (`eu`)        |
| `PUSHER_APP_ID`              | Application ID (server-side) |
| `PUSHER_SECRET`              | Secret key (server-side)     |

**What it's for:**

* Real-time updates to task status
* Live notifications in the UI
* Multi-user collaboration features

#### Pusher Beams (Push notifications)

| Variable                               | Description                           |
| -------------------------------------- | ------------------------------------- |
| `NEXT_PUBLIC_PUSHER_BEAMS_INSTANCE_ID` | Beams instance identifier             |
| `PUSHER_BEAMS_SECRET_KEY`              | Secret for sending push notifications |

**What it's for:**

* Browser push notifications
* Desktop notifications for tasks and mentions

### Resend (Email)

| Variable         | Description                |
| ---------------- | -------------------------- |
| `RESEND_API_KEY` | API key for sending emails |

**What it's for:**

* Sending email notifications
* Quote approval emails to clients
* Task assignment notifications
* System alerts

**Get an API key:**

* Go to [Resend Dashboard](https://resend.com/api-keys)
* Create an API key for the CharleOS project

### Algolia (Search)

| Variable                 | Description                                  |
| ------------------------ | -------------------------------------------- |
| `ALGOLIA_APP_ID`         | Algolia application ID                       |
| `ALGOLIA_ADMIN_API_KEY`  | Admin API key (for indexing)                 |
| `ALGOLIA_SEARCH_API_KEY` | Search-only API key (public, read-only)      |
| `ALGOLIA_INDEX_NAME`     | Index name (`search_entities_dev` for local) |

**What it's for:**

* Global search across clients, tasks, quotes, projects
* Instant search results as you type
* Indexed data includes: clients, tasks, quotes, projects, tickets

**Index names:**

* **Local/Dev:** `search_entities_dev`
* **Production:** `search_entities_prod`

### HubSpot (CRM Integration)

| Variable               | Description              |
| ---------------------- | ------------------------ |
| `HUBSPOT_ACCESS_TOKEN` | Private app access token |

**What it's for:**

* Syncing client data with HubSpot CRM
* Creating deals and contacts
* Tracking client interactions

**Optional:** Only needed if using HubSpot integration features.

### OpenAI (AI Features)

| Variable         | Description                    |
| ---------------- | ------------------------------ |
| `OPENAI_API_KEY` | OpenAI API key for AI features |

**What it's for:**

* Alan (AI assistant) for scheduling and task management
* Smart suggestions for task sizing
* Natural language processing for search

### Slack (Notifications)

| Variable               | Description                           |
| ---------------------- | ------------------------------------- |
| `SLACK_BOT_TOKEN`      | Bot user OAuth token (`xoxb-...`)     |
| `SLACK_SIGNING_SECRET` | Signing secret for verifying requests |
| `SLACK_APP_TOKEN`      | App-level token (`xapp-...`)          |
| `SLACK_APP_ID`         | Slack app identifier                  |

**What it's for:**

* Sending notifications to Slack channels
* Task updates in Slack
* Quote approvals and mentions
* Integration with team communication

**Setup:**

1. Go to [Slack API Dashboard](https://api.slack.com/apps)
2. Select the CharleOS app
3. Find credentials in "OAuth & Permissions" and "Basic Information"

### Sentry (Error Tracking)

| Variable            | Description                          |
| ------------------- | ------------------------------------ |
| `SENTRY_AUTH_TOKEN` | Auth token for uploading source maps |

**What it's for:**

* Error tracking and monitoring
* Performance monitoring
* Release tracking with source maps

**Get a token:**

* Go to [Sentry Settings](https://sentry.io/settings/account/api/auth-tokens/)
* Create a token with `project:releases` and `org:read` scopes

## Environment-Specific Values

### Local Development (`.env.local`)

| Variable                        | Local Value                     |
| ------------------------------- | ------------------------------- |
| `DATABASE_URL`                  | DEV database branch             |
| `BETTER_AUTH_URL`               | `http://localhost:3000`         |
| `NEXT_PUBLIC_BETTER_AUTH_URL`   | `http://localhost:3000`         |
| `NEXT_PUBLIC_CLIENT_PORTAL_URL` | `http://clients.localhost:3000` |
| `ALGOLIA_INDEX_NAME`            | `search_entities_dev`           |

### Production (`.env.production`)

| Variable                        | Production Value                 |
| ------------------------------- | -------------------------------- |
| `DATABASE_URL`                  | Production database (via Vercel) |
| `BETTER_AUTH_URL`               | `https://charle.agency`          |
| `NEXT_PUBLIC_BETTER_AUTH_URL`   | `https://charle.agency`          |
| `NEXT_PUBLIC_CLIENT_PORTAL_URL` | `https://clients.charle.agency`  |
| `ALGOLIA_INDEX_NAME`            | `search_entities_prod`           |

<Warning>
  **Never use production credentials locally** - the `.env.local` file is configured with safe development values. Production credentials are managed via Vercel.
</Warning>

## Required vs Optional Variables

### Required for Core Functionality

These are **required** for the app to run:

* `DATABASE_URL` - Database connection
* `BETTER_AUTH_SECRET` - Auth encryption
* `BETTER_AUTH_URL` and public variants - Auth configuration
* `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` - OAuth sign-in

### Optional (Feature-Specific)

These are **optional** and only needed for specific features:

* **Pusher** - Real-time updates (app works without, but no live updates)
* **Resend** - Email notifications (app works without, but no emails sent)
* **Algolia** - Search (app works without, but search will be slower/limited)
* **HubSpot** - CRM integration (purely optional)
* **OpenAI** - AI features (Alan won't work without this)
* **Slack** - Slack notifications (purely optional)
* **Sentry** - Error tracking (purely optional, for monitoring)
* **Cloudflare R2** - File uploads (attachments won't work without this)

## Managing Environment Variables

### Local Development

The `.env.local` file is **already configured** and checked into the repository. You don't need to create or modify it unless:

* You're testing a specific integration
* You need to use a different database branch
* You're debugging auth issues

### Adding New Variables

If you add new environment variables to the codebase:

1. **Add to `.env.local`** with a dev/test value
2. **Add to `.env.example`** with a placeholder
3. **Document here** in this page
4. **Add to Vercel** for production (via Vercel Dashboard)

### Security Best Practices

<AccordionGroup>
  <Accordion title="Never Commit Secrets" icon="lock">
    * `.env.local` is in the repo but **only has dev/test credentials**
    * Never commit production API keys or secrets
    * Production secrets are managed via Vercel environment variables
  </Accordion>

  <Accordion title="Use Environment-Specific Values" icon="code-branch">
    * Development values in `.env.local`
    * Production values in Vercel Dashboard
    * Never mix environments
  </Accordion>

  <Accordion title="Rotate Compromised Secrets" icon="rotate">
    If a secret is exposed:

    1. Immediately rotate it in the service (Google, Pusher, etc.)
    2. Update Vercel environment variables
    3. Update `.env.local` if it's a dev credential
    4. Redeploy if necessary
  </Accordion>

  <Accordion title="Use Public Variables Correctly" icon="eye">
    Variables prefixed with `NEXT_PUBLIC_` are exposed to the client:

    * Only use for public, non-sensitive data
    * Examples: `NEXT_PUBLIC_PUSHER_KEY` (read-only), `NEXT_PUBLIC_APP_URL`
    * Never use for API secrets or tokens
  </Accordion>
</AccordionGroup>

## Troubleshooting

### Missing Variable Errors

**Error:** "Missing environment variable: X"

**Fix:**

1. Check if the variable exists in `.env.local`
2. If missing, add it (check `.env.example` for reference)
3. Restart the dev server: `npm run dev`

### Wrong Environment

**Error:** Auth URLs point to production / CORS errors

**Fix:**

1. Verify `.env.local` has `BETTER_AUTH_URL=http://localhost:3000`
2. Check you haven't accidentally modified `.env.local` with production values
3. Restore from git if needed: `git checkout .env.local`

### Integration Not Working

If an integration (Pusher, Algolia, etc.) isn't working:

1. **Check the variable is set** in `.env.local`
2. **Verify the credential is valid** in the service's dashboard
3. **Restart the dev server** - env vars are loaded on startup
4. **Check service status** - the external service might be down

## Related Documentation

<CardGroup cols={2}>
  <Card title="Local Setup" icon="rocket" href="/developer/getting-started/local-setup">
    Step-by-step guide to setting up your local environment
  </Card>

  <Card title="Authentication" icon="lock" href="/developer/auth">
    How Better Auth uses these environment variables
  </Card>

  <Card title="Deployment" icon="cloud" href="/developer/deployment">
    Managing environment variables in production
  </Card>
</CardGroup>
