> ## 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.

# Storage Factory

> Create encrypted AWS S3 bucket resources with the Fjall StorageFactory pattern and sensible defaults.

## Overview

The `StorageFactory` creates S3 bucket resources with type-safe configurations. All buckets use the single `S3Bucket` class, with different property combinations controlling behaviour (private, website hosting, public read access).

<Note>
  For databases (Aurora, RDS, DynamoDB), use the [DatabaseFactory](/patterns/database-factory) instead.
</Note>

## Basic Usage

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

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

const assets = app.addStorage(StorageFactory.build("Assets", {}));
```

## Bucket Configurations

### Private Bucket (Default)

Standard bucket with no public access. Best for application assets, uploads, and caches:

```typescript theme={null}
const assets = app.addStorage(
  StorageFactory.build("Assets", {
    versioned: true,
    encryption: "AES256",
  }),
);
```

**Features:**

* Private by default (no public access)
* Optional versioning
* Optional encryption (AES256 or KMS)

### Website Hosting Bucket

Configure a bucket for static website hosting using the `websiteHosting` property:

```typescript theme={null}
const site = app.addStorage(
  StorageFactory.build("StaticSite", {
    websiteHosting: {
      indexDocument: "index.html",
      errorDocument: "404.html",
    },
  }),
);
```

**Features:**

* Static website hosting enabled
* Configurable index and error documents
* CORS support

### Public Read Access Bucket

Enable public read access for all objects using the `publicReadAccess` property:

```typescript theme={null}
const publicAssets = app.addStorage(
  StorageFactory.build("PublicAssets", {
    publicReadAccess: true,
  }),
);
```

**Features:**

* All objects publicly readable
* Best for CDN origin buckets
* Optional versioning and encryption

## Configuration Parameters

| Parameter                      | Type                              | Description                                             | Default        |
| ------------------------------ | --------------------------------- | ------------------------------------------------------- | -------------- |
| `versioned`                    | `boolean`                         | Enable versioning                                       | `false`        |
| `encryption`                   | `"AES256" \| "KMS"`               | Encryption type                                         | None           |
| `kmsKeyArn`                    | `string`                          | KMS key ARN (if using KMS encryption)                   | -              |
| `publicReadAccess`             | `boolean`                         | Allow public read access                                | `false`        |
| `websiteHosting`               | `object`                          | Website hosting configuration                           | -              |
| `websiteHosting.indexDocument` | `string`                          | Index document name                                     | `"index.html"` |
| `websiteHosting.errorDocument` | `string`                          | Error document name                                     | -              |
| `cors`                         | `array`                           | CORS rules                                              | -              |
| `stackPlacement`               | `"storage" \| "cdn" \| "compute"` | Which CDK stack to place the bucket in                  | `"storage"`    |
| `backupVaultTier`              | `BackupTier`                      | AWS Backup tier (`standard`, `resilient`, `enterprise`) | -              |
| `deployment`                   | `object`                          | Auto-deploy files from local path                       | -              |

## Common Patterns

### Media Uploads

Store user-uploaded media with versioning:

```typescript theme={null}
const media = app.addStorage(
  StorageFactory.build("Media", {
    versioned: true,
    encryption: "AES256",
  }),
);
```

### Static Assets with Deployment

Auto-deploy static assets during CDK deployment:

```typescript theme={null}
const assets = app.addStorage(
  StorageFactory.build("Assets", {
    deployment: {
      source: "./public/assets",
      prune: true,
      cacheControl: {
        maxAge: 31536000, // 1 year
        immutable: true,
      },
    },
  }),
);
```

### ISR Cache Bucket

Cache bucket for Next.js ISR:

```typescript theme={null}
const cache = app.addStorage(StorageFactory.build("Cache", {}));
```

### Website with CORS

Website bucket with CORS for API requests:

```typescript theme={null}
const site = app.addStorage(
  StorageFactory.build("Website", {
    websiteHosting: {
      indexDocument: "index.html",
      errorDocument: "error.html",
    },
    cors: [
      {
        allowedOrigins: ["https://api.example.com"],
        allowedMethods: ["GET", "HEAD"],
      },
    ],
  }),
);
```

### CDN Origin Bucket

Place a bucket in the CDN stack to avoid circular dependencies:

```typescript theme={null}
const cdnAssets = app.addStorage(
  StorageFactory.build("CDNAssets", {
    stackPlacement: "cdn",
    encryption: "AES256",
  }),
);
```

### KMS Encryption

```typescript theme={null}
const encrypted = app.addStorage(
  StorageFactory.build("Secure", {
    encryption: "KMS",
    kmsKeyArn: "arn:aws:kms:ap-southeast-2:123456789:key/abc-123",
  }),
);
```

## Accessing Bucket Information

```typescript theme={null}
const storage = app.addStorage(StorageFactory.build("Assets", {}));

// Get bucket information
const name = storage.getBucketName();
const arn = storage.getBucketArn();
const domainName = storage.getBucketDomainName();
```

## Connecting to Compute Resources

```typescript theme={null}
const assets = app.addStorage(StorageFactory.build("Assets", {}));

// Lambda with S3 access
const api = app.addCompute(
  ComputeFactory.build("Api", {
    type: "lambda",
    deployment: "code",
    handler: "api.handler",
  }),
);

// ECS with S3 access via environment variables
const service = app.addCompute(
  ComputeFactory.build("Service", {
    type: "ecs",
    services: [
      {
        name: "web",
        capacityProvider: "FARGATE",
        containers: [
          {
            port: 3000,
            environment: {
              ASSETS_BUCKET: assets.getBucketName(),
            },
          },
        ],
      },
    ],
  }),
);
```

## Granting Access

```typescript theme={null}
const storage = app.addStorage(StorageFactory.build("Assets", {}));

// Grant read access
storage.grantRead(lambdaFunction);

// Grant write access
storage.grantWrite(lambdaFunction);

// Grant read/write access
storage.grantReadWrite(lambdaFunction);

// Grant public access to specific prefix
storage.grantPublicAccess("public/*");
```

## Security

### Automatic Security Features

* **Private by default**: No public access unless explicitly configured
* **Encryption options**: S3-managed (AES256) or customer-managed KMS keys
* **Block public access**: Enabled by default on private buckets
* **IAM policies**: Automatic least-privilege policies

## Event Notifications

```typescript theme={null}
import { EventType } from "aws-cdk-lib/aws-s3";

const storage = app.addStorage(StorageFactory.build("Uploads", {}));

// Notify Lambda when objects are created
storage.addObjectCreatedNotification(lambdaDestination, {
  prefix: "uploads/",
  suffix: ".jpg",
});

// Custom event notification
storage.addEventNotification(EventType.OBJECT_REMOVED, sqsDestination, {
  prefix: "temp/",
});
```

## Best Practices

1. **Keep buckets private by default** - Only enable `publicReadAccess` or `websiteHosting` when needed
2. **Enable versioning** for important data that may need recovery
3. **Use encryption** for sensitive data
4. **Use deployment config** for static assets instead of manual S3 sync
5. **Set `stackPlacement`** to `"cdn"` when the bucket is used as a CloudFront origin

## Next Steps

<CardGroup cols={2}>
  <Card title="Database Factory" icon="database" href="/patterns/database-factory">
    Create Aurora, RDS, and DynamoDB databases
  </Card>

  <Card title="Compute Factory" icon="microchip" href="/patterns/compute-factory">
    Deploy Lambda and ECS compute resources
  </Card>

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

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