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

# Setup CloudFront

<Note>
  **Internal Service** — This is not an HTTP endpoint. It's called directly by the `generate-all` orchestrator.
</Note>

## Purpose

Creates an AWS CloudFront distribution with Lambda\@Edge for the domain proxy. This allows the AI site to be served from the customer's own domain.

Runs in **GROUP 1g** (parallel with scrape, fire-and-forget). Doesn't need scraped pages.

## Function Signature

```python theme={null}
async def run_cloudfront_setup(url: str, org_slug: str) -> StepResult
```

## Parameters

| Parameter  | Type  | Description                 |
| ---------- | ----- | --------------------------- |
| `url`      | `str` | The business website URL    |
| `org_slug` | `str` | The Clerk organization slug |

## Returns

```json theme={null}
{
  "name": "setup_cloudfront",
  "status": "success",
  "data": {
    "distribution_id": "E1234567890ABC",
    "cloudfront_domain": "d1234567890abc.cloudfront.net"
  }
}
```

## What It Creates

1. **CloudFront Distribution** - CDN distribution for the domain
2. **Lambda\@Edge Function** - Routes requests between original site and AI site
3. **SSL Certificate** - Via AWS Certificate Manager (ACM)

## How The Proxy Works

```mermaid theme={null}
flowchart LR
    User[User Request] --> CF[CloudFront]
    CF --> Lambda[Lambda@Edge]
    Lambda -->|/llms.txt, /robots.txt| AI[AI Site]
    Lambda -->|Everything else| Origin[Original Site]
```

The Lambda\@Edge function intercepts requests and routes:

* `/llms.txt`, `/robots.txt`, `/sitemap.xml`, `/pages/*` → AI Site
* Everything else → Original website

## Database Updates

Updates the `ai_sites` table:

```sql theme={null}
UPDATE ai_sites SET
  cloudfront_distribution_id = 'E1234567890ABC',
  cloudfront_domain = 'd1234567890abc.cloudfront.net'
WHERE entity_id = 'uuid-...';
```

## Code Location

```
src/app/shared/cloudfront/
├── __init__.py
├── service.py              # setup_cloudfront function
├── create_distribution.py  # AWS CloudFront API calls
└── domain_detection.py     # Apex vs subdomain detection
```

## Why Pre-create?

The CloudFront distribution is created during onboarding (before the user connects their domain) so that:

1. DNS propagation can start early
2. The distribution is ready when the user completes domain setup
3. Reduces wait time in the domain connection flow

## Error Handling

```json theme={null}
{
  "name": "setup_cloudfront",
  "status": "error",
  "error": "AWS rate limit exceeded"
}
```

If CloudFront setup fails, the error is logged but onboarding continues. The distribution can be created later during domain setup.
