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

# CDN Factory

> Create AWS CloudFront CDN distributions with the Fjall CdnFactory for caching, HTTPS, and custom domains.

## Overview

`CdnFactory` creates AWS CloudFront distributions with type-safe configuration. It delivers global content with caching, HTTPS, and custom domain support.

<Note>
  CDN is configured automatically when using the Payload pattern. Use `CdnFactory` directly when breaking out of patterns or building custom architectures.
</Note>

Every configuration requires an `originType`. Use `"auto"` to detect the origin from a connected Fjall resource, or set `"s3"`, `"alb"`, or `"http"` explicitly.

## Basic Usage

```typescript theme={null}
import { App, CdnFactory } from "@fjall/components-infrastructure";

const app = App.getApp("api");

const cdn = app.addCdn(
  CdnFactory.build("AppCdn", {
    originType: "auto",
    origin: serverFunction,
  }),
);
```

## Configuration

### Origin Types

| Type     | Description                          | Use Case          |
| -------- | ------------------------------------ | ----------------- |
| `"auto"` | Auto-detect from connected resources | Most common       |
| `"s3"`   | S3 bucket origin                     | Static websites   |
| `"alb"`  | Application Load Balancer origin     | ECS services      |
| `"http"` | Custom HTTP origin (external URL)    | External backends |

### Full Configuration Example

```typescript theme={null}
const cdn = app.addCdn(
  CdnFactory.build("AppCdn", {
    originType: "auto",
    origin: serverFunction,
    domainNames: ["www.example.com", "example.com"],
    certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/abc-123",
    behaviours: [
      {
        pathPattern: "/_next/static/*",
        origin: assetsBucket,
        cachePolicy: "CACHING_OPTIMIZED",
      },
      {
        pathPattern: "/api/*",
        origin: serverFunction,
        cachePolicy: "CACHING_DISABLED",
      },
      {
        pathPattern: "/media/*",
        origin: assetsBucket,
        cachePolicy: "CACHING_OPTIMIZED",
      },
    ],
  }),
);
```

## Parameters

### Core Parameters

| Parameter        | Type                                | Description                                                             | Default           |
| ---------------- | ----------------------------------- | ----------------------------------------------------------------------- | ----------------- |
| `originType`     | `"auto" \| "s3" \| "alb" \| "http"` | Origin type (required)                                                  | -                 |
| `origin`         | `resource`                          | Default origin resource. Required when `originType` is `"auto"`         | -                 |
| `domainNames`    | `string[]`                          | Custom domain names                                                     | CloudFront domain |
| `certificateArn` | `string`                            | ACM certificate ARN as a string (must be in us-east-1)                  | -                 |
| `certificate`    | `ICertificate`                      | Imported ACM certificate construct. Use `certificateArn` for the string | -                 |

The `origin` field exists only on the `"auto"` variant. The `"s3"`, `"alb"`, and `"http"` variants take `bucket`, `loadBalancer`, and `domainName` respectively (see [Origin-Specific Parameters](#origin-specific-parameters)).

### Behaviour Parameters

Each behaviour accepts these four fields. CloudFront applies viewer protocol policy, origin request policy, and compression automatically.

| Parameter                     | Type                                        | Description                    | Default               |
| ----------------------------- | ------------------------------------------- | ------------------------------ | --------------------- |
| `behaviours`                  | `array`                                     | Cache behaviour configurations | Default behaviour     |
| `behaviours[].pathPattern`    | `string`                                    | URL path pattern to match      | `"*"`                 |
| `behaviours[].origin`         | `resource`                                  | Origin for this path           | Required              |
| `behaviours[].cachePolicy`    | `string`                                    | Cache policy name              | `"CACHING_OPTIMIZED"` |
| `behaviours[].allowedMethods` | `"GET_HEAD" \| "GET_HEAD_OPTIONS" \| "ALL"` | HTTP methods for this path     | `"GET_HEAD"`          |

### Origin-Specific Parameters

When using explicit origin types, additional parameters are available:

#### S3 Origin (`originType: "s3"`)

| Parameter    | Type      | Description                | Default  |
| ------------ | --------- | -------------------------- | -------- |
| `bucket`     | `IBucket` | S3 bucket to use as origin | Required |
| `originPath` | `string`  | Path prefix in the bucket  | `"/"`    |

```typescript theme={null}
CdnFactory.build("StaticCDN", {
  originType: "s3",
  bucket: myBucket,
  originPath: "/public",
});
```

#### ALB Origin (`originType: "alb"`)

| Parameter        | Type                                            | Description            | Default        |
| ---------------- | ----------------------------------------------- | ---------------------- | -------------- |
| `loadBalancer`   | `IApplicationLoadBalancer`                      | ALB to use as origin   | Required       |
| `protocolPolicy` | `"HTTP_ONLY" \| "HTTPS_ONLY" \| "MATCH_VIEWER"` | Origin protocol policy | `"HTTPS_ONLY"` |

```typescript theme={null}
CdnFactory.build("ALBCDN", {
  originType: "alb",
  loadBalancer: myAlb,
  protocolPolicy: "HTTPS_ONLY",
});
```

#### HTTP Origin (`originType: "http"`)

| Parameter        | Type                                            | Description            | Default        |
| ---------------- | ----------------------------------------------- | ---------------------- | -------------- |
| `domainName`     | `string`                                        | External domain name   | Required       |
| `originPath`     | `string`                                        | Path prefix at origin  | `"/"`          |
| `protocolPolicy` | `"HTTP_ONLY" \| "HTTPS_ONLY" \| "MATCH_VIEWER"` | Origin protocol policy | `"HTTPS_ONLY"` |

```typescript theme={null}
CdnFactory.build("ExternalCDN", {
  originType: "http",
  domainName: "api.external-service.com",
  originPath: "/v2",
  protocolPolicy: "HTTPS_ONLY",
});
```

### Additional Configuration

| Parameter               | Type                                                       | Description                      | Default            |
| ----------------------- | ---------------------------------------------------------- | -------------------------------- | ------------------ |
| `comment`               | `string`                                                   | Distribution comment/description | -                  |
| `enableLogging`         | `boolean`                                                  | Enable access logging            | `false`            |
| `logBucket`             | `IBucket`                                                  | S3 bucket for access logs        | -                  |
| `priceClass`            | `"PriceClass_100" \| "PriceClass_200" \| "PriceClass_All"` | Price class (edge locations)     | `"PriceClass_All"` |
| `forwardHostHeader`     | `boolean`                                                  | Forward Host header to origin    | `false`            |
| `defaultAllowedMethods` | `"GET_HEAD" \| "GET_HEAD_OPTIONS" \| "ALL"`                | Default allowed HTTP methods     | `"GET_HEAD"`       |

### Framework-Managed Behaviour Settings

Fjall sets these per-behaviour values internally. They are not configurable through the factory.

| Setting               | Value                                  |
| --------------------- | -------------------------------------- |
| Viewer protocol       | Redirect HTTP to HTTPS                 |
| Origin request policy | Selected automatically for the origin  |
| Compression           | Enabled for compressible content types |

### Cache Policies

| Policy                                         | Description                              |
| ---------------------------------------------- | ---------------------------------------- |
| `"CACHING_OPTIMIZED"`                          | Standard caching for static content      |
| `"CACHING_OPTIMIZED_FOR_UNCOMPRESSED_OBJECTS"` | For already-compressed content           |
| `"CACHING_DISABLED"`                           | No caching (API routes, dynamic content) |

## Common Patterns

### Static Website with S3

```typescript theme={null}
const assetsBucket = app.addStorage(
  StorageFactory.build("Assets", {
    websiteHosting: { indexDocument: "index.html" },
  }),
);

const cdn = app.addCdn(
  CdnFactory.build("WebsiteCdn", {
    originType: "s3",
    bucket: assetsBucket,
    domainNames: ["www.example.com"],
    certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/abc-123",
  }),
);
```

### Lambda Function URL (Auto-Detection)

```typescript theme={null}
const serverFunction = app.addCompute(
  ComputeFactory.build("Server", {
    type: "lambda",
    deployment: "container",
    functionUrl: { authType: FunctionUrlAuthType.NONE },
  }),
);

const cdn = app.addCdn(
  CdnFactory.build("AppCdn", {
    originType: "auto",
    origin: serverFunction,
  }),
);
```

With `originType: "auto"`, the factory detects the Lambda function URL from the compute resource.

### Multi-Origin Setup (OpenNext)

```typescript theme={null}
// Create all resources
const serverFunction = app.addCompute(...);
const imageFunction = app.addCompute(...);
const assetsBucket = app.addStorage(...);

// CDN with multiple origins
const cdn = app.addCdn(
  CdnFactory.build("AppCdn", {
    originType: "auto",
    origin: serverFunction,
    behaviours: [
      {
        pathPattern: "/_next/image*",
        origin: imageFunction,
        cachePolicy: "CACHING_OPTIMIZED",
      },
      {
        pathPattern: "/_next/static/*",
        origin: assetsBucket,
        cachePolicy: "CACHING_OPTIMIZED",
      },
      {
        pathPattern: "/media/*",
        origin: assetsBucket,
        cachePolicy: "CACHING_OPTIMIZED",
      },
    ],
  }),
);
```

### ECS with Load Balancer

The cluster's load balancer is internet-facing by default. Set `routing` to match a path on the shared ALB.

```typescript theme={null}
const service = app.addCompute(
  ComputeFactory.build("Api", {
    type: "ecs",
    cluster: { loadBalancer: "public" },
    services: [
      {
        name: "api",
        capacityProvider: "FARGATE",
        routing: { path: "/api/*" },
      },
    ],
  }),
);

const cdn = app.addCdn(
  CdnFactory.build("ApiCdn", {
    originType: "alb",
    loadBalancer: service,
    behaviours: [
      {
        pathPattern: "/api/*",
        origin: service,
        cachePolicy: "CACHING_DISABLED",
      },
    ],
  }),
);
```

## Custom Domain Setup

### Prerequisites

1. Domain registered and DNS managed (Route 53 recommended)
2. ACM certificate in **us-east-1** (required for CloudFront)

### With Route 53

```typescript theme={null}
const cdn = app.addCdn(
  CdnFactory.build("AppCdn", {
    originType: "auto",
    origin: serverFunction,
    domainNames: ["www.example.com"],
    // Route 53 DNS records are created automatically
    certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/abc-123",
  }),
);
```

### With External DNS

Create a CNAME record pointing to the CloudFront distribution domain:

```
www.example.com CNAME d1234567890.cloudfront.net
```

## Accessing CDN Information

```typescript theme={null}
const cdn = app.addCdn(
  CdnFactory.build("AppCdn", { originType: "auto", origin: serverFunction }),
);

// Read distribution info
const domainName = cdn.getDistributionDomainName();
const distributionId = cdn.getDistributionId();
```

## Security

### Automatic Security Features

* **HTTPS only**: HTTP automatically redirected to HTTPS
* **TLS 1.2+**: Modern TLS protocols only
* **Origin Access Control**: Secure S3 bucket access
* **Signed URLs**: Optional signed URL support for private content

## Best Practices

1. **Use `originType: "auto"`** for most cases. Fjall picks the origin from the connected resource.
2. **Cache static assets** with the `CACHING_OPTIMIZED` policy.
3. **Disable caching for APIs** with `CACHING_DISABLED` to return fresh responses.
4. **Create the certificate in us-east-1.** CloudFront requires certificates in this region.

## Next Steps

<CardGroup cols={2}>
  <Card title="Compute Factory" icon="microchip" href="/patterns/compute-factory">
    Deploy Lambda and ECS origins
  </Card>

  <Card title="Storage Factory" icon="box-archive" href="/patterns/storage-factory">
    Configure S3 bucket origins
  </Card>

  <Card title="Payload Pattern" icon="cube" href="/patterns/payload-pattern">
    Full-stack deployment with CDN
  </Card>

  <Card title="Network Factory" icon="network-wired" href="/patterns/network-factory">
    Configure VPC networking
  </Card>
</CardGroup>
