Skip to main content
CharleOS uses environment variables for configuration. The .env.local file is included in the repository and pre-configured for local development.
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.

Core Configuration

Database

VariableValueDescription
DATABASE_URLPostgreSQL connection stringConnection 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

VariableValueDescription
BETTER_AUTH_SECRETRandom 32+ char stringSecret for encrypting sessions
BETTER_AUTH_URLhttp://localhost:3000Base URL for auth server
NEXT_PUBLIC_BETTER_AUTH_URLhttp://localhost:3000Public-facing auth URL (client-side)
NEXT_PUBLIC_APP_URLhttp://localhost:3000Main app URL
NEXT_PUBLIC_CLIENT_PORTAL_URLhttp://clients.localhost:3000Client portal URL
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.

Google OAuth

VariableDescription
GOOGLE_CLIENT_IDOAuth client ID from Google Cloud Console
GOOGLE_CLIENT_SECRETOAuth client secret
How to get these:
  1. Go to Google Cloud Console
  2. Select the CharleOS project
  3. Find the OAuth 2.0 Client ID credentials
Only @charle.co.uk email addresses are allowed to sign in.

Integrations

Cloudflare R2 (File Storage)

VariableDescription
CLOUDFLARE_WORKER_URLURL of the R2 API worker (https://r2-api.charle.agency)
R2_UPLOAD_SECRETShared secret for worker authentication
CLOUDFLARE_R2_PUBLIC_URLPublic 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)

VariableDescription
NEXT_PUBLIC_PUSHER_KEYPublic API key (client-side)
NEXT_PUBLIC_PUSHER_CLUSTERServer cluster (eu)
PUSHER_APP_IDApplication ID (server-side)
PUSHER_SECRETSecret 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)

VariableDescription
NEXT_PUBLIC_PUSHER_BEAMS_INSTANCE_IDBeams instance identifier
PUSHER_BEAMS_SECRET_KEYSecret for sending push notifications
What it’s for:
  • Browser push notifications
  • Desktop notifications for tasks and mentions

Resend (Email)

VariableDescription
RESEND_API_KEYAPI 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:
VariableDescription
ALGOLIA_APP_IDAlgolia application ID
ALGOLIA_ADMIN_API_KEYAdmin API key (for indexing)
ALGOLIA_SEARCH_API_KEYSearch-only API key (public, read-only)
ALGOLIA_INDEX_NAMEIndex 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)

VariableDescription
HUBSPOT_ACCESS_TOKENPrivate 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)

VariableDescription
OPENAI_API_KEYOpenAI 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)

VariableDescription
SLACK_BOT_TOKENBot user OAuth token (xoxb-...)
SLACK_SIGNING_SECRETSigning secret for verifying requests
SLACK_APP_TOKENApp-level token (xapp-...)
SLACK_APP_IDSlack 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
  2. Select the CharleOS app
  3. Find credentials in “OAuth & Permissions” and “Basic Information”

Sentry (Error Tracking)

VariableDescription
SENTRY_AUTH_TOKENAuth 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
  • Create a token with project:releases and org:read scopes

Environment-Specific Values

Local Development (.env.local)

VariableLocal Value
DATABASE_URLDEV database branch
BETTER_AUTH_URLhttp://localhost:3000
NEXT_PUBLIC_BETTER_AUTH_URLhttp://localhost:3000
NEXT_PUBLIC_CLIENT_PORTAL_URLhttp://clients.localhost:3000
ALGOLIA_INDEX_NAMEsearch_entities_dev

Production (.env.production)

VariableProduction Value
DATABASE_URLProduction database (via Vercel)
BETTER_AUTH_URLhttps://charle.agency
NEXT_PUBLIC_BETTER_AUTH_URLhttps://charle.agency
NEXT_PUBLIC_CLIENT_PORTAL_URLhttps://clients.charle.agency
ALGOLIA_INDEX_NAMEsearch_entities_prod
Never use production credentials locally - the .env.local file is configured with safe development values. Production credentials are managed via Vercel.

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

  • .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
  • Development values in .env.local
  • Production values in Vercel Dashboard
  • Never mix environments
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
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

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