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

# Deployment

> Deploy the Charley API (Docker/ECS) and dashboard (S3/CDN)

## API Deployment

The API is packaged as a Docker image and designed to run on AWS ECS Fargate, though any container runtime works.

### Building the Image

```bash theme={null}
cd apps/api
docker build -t charley-api .
```

### Running Locally

```bash theme={null}
docker run -p 3001:3001 --env-file .env charley-api
```

### Pushing to ECR

```bash theme={null}
aws ecr get-login-password --region us-east-1 \
  | docker login --username AWS --password-stdin <account_id>.dkr.ecr.us-east-1.amazonaws.com

docker tag charley-api:latest <account_id>.dkr.ecr.us-east-1.amazonaws.com/charley-api:latest
docker push <account_id>.dkr.ecr.us-east-1.amazonaws.com/charley-api:latest
```

### ECS Fargate

The repository's CI/CD pipeline (`.github/workflows/`) handles ECS deployment automatically on merge to `main`. For manual deployments:

1. Push the image to ECR (above).
2. Update the ECS service to use the new image revision:

```bash theme={null}
aws ecs update-service \
  --cluster <cluster_name> \
  --service <service_name> \
  --force-new-deployment
```

### Required IAM Permissions

The ECS task role needs:

* `ses:SendEmail` — for transactional email
* `ecr:GetAuthorizationToken`, `ecr:BatchGetImage` — to pull the image

***

## Dashboard Deployment

The dashboard is a Vite-built SPA that can be hosted on any static file host.

### Building

```bash theme={null}
cd apps/web
npm run build
```

The output is in `apps/web/dist/`.

### S3 + CloudFront

```bash theme={null}
# Sync build output to S3
aws s3 sync apps/web/dist/ s3://<bucket_name>/ --delete

# Invalidate CloudFront cache
aws cloudfront create-invalidation \
  --distribution-id <distribution_id> \
  --paths "/*"
```

Configure the S3 bucket for static website hosting and set up a CloudFront distribution pointing to it. Set the **error document** to `index.html` to support React Router client-side routing.

### Vercel / Netlify

Both platforms support Vite out of the box:

1. Set the build command to `npm run build`.
2. Set the publish directory to `dist`.
3. Add your `VITE_*` environment variables in the platform's settings UI.
4. Configure rewrites so all paths resolve to `index.html` (for React Router).

***

## CI/CD Pipeline

The repository uses GitHub Actions. The pipeline:

1. **Static checks** — TypeScript compilation, ESLint
2. **Unit tests** — Vitest
3. **API trace tests** — Tusk Drift replay
4. **Deploy** — Docker build → ECR push → ECS update (API) + S3 sync + CloudFront invalidation (dashboard)

Deployments to the **dev environment** are triggered by merges to `develop`. Production deployments require a PR from `develop` to `main`.

### Required GitHub Secrets

| Secret                       | Description                          |
| ---------------------------- | ------------------------------------ |
| `AWS_ACCOUNT_ID`             | AWS account ID                       |
| `AWS_ROLE_ARN`               | IAM role for OIDC federation         |
| `ECR_REPOSITORY`             | ECR repository name                  |
| `ECS_CLUSTER`                | ECS cluster name                     |
| `ECS_SERVICE`                | ECS service name                     |
| `S3_BUCKET`                  | Frontend S3 bucket name              |
| `CLOUDFRONT_DISTRIBUTION_ID` | CloudFront distribution ID           |
| `AUTH0_DOMAIN`               | Auth0 tenant domain                  |
| `DATABASE_RO_URL`            | Read-only database URL               |
| `DATABASE_RW_URL`            | Read-write database URL              |
| `STRIPE_SECRET_KEY`          | Stripe secret key                    |
| `STRIPE_WEBHOOK_SECRET`      | Stripe webhook secret                |
| `TUSK_API_KEY`               | Tusk Drift API key (for trace tests) |
