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

# Deploy a Static Website to S3 and CloudFront

> Build your static site from GitHub, publish the output to S3, and serve it globally through CloudFront — all inside your own AWS account.

A static website in Springwinter is built from your GitHub repository and published to an S3 bucket sitting behind a CloudFront distribution, both provisioned inside your own AWS account. Springwinter runs your build command on every push, uploads the output to S3, and invalidates the CloudFront cache so your visitors always see the latest version.

## Use Cases

Static websites work well for any project that produces a folder of HTML, CSS, and JavaScript files at build time:

<CardGroup cols={2}>
  <Card title="Marketing Sites" icon="bullhorn">
    Fast, globally distributed pages for your product or company homepage.
  </Card>

  <Card title="Single-Page Applications" icon="window-maximize">
    React, Vue, Svelte, or any other SPA framework that outputs a `dist` or `build` directory.
  </Card>

  <Card title="Documentation Sites" icon="book">
    Statically generated docs built with tools like Docusaurus, VitePress, or Hugo.
  </Card>

  <Card title="Landing Pages" icon="rectangle-ad">
    Campaign pages, event registrations, and product launches that need zero cold-start time.
  </Card>
</CardGroup>

## Requirements

Before you deploy a static website, make sure you have:

* A GitHub repository with a build command that outputs static files to a known directory.
* An AWS account connected to Springwinter. See [Connect Your AWS Account](/connect-aws).
* A GitHub account connected via the Springwinter GitHub App. See [Connect GitHub](/connect-github).

## Deploy a Static Website

<Steps>
  <Step title="Add the resource">
    Open your project in the Springwinter dashboard, click **Add resource**, and select **Static website**.
  </Step>

  <Step title="Select a repository and branch">
    Choose the GitHub repository to deploy from and the branch to track. Springwinter will build and publish on every push to that branch when auto-deploy is enabled.
  </Step>

  <Step title="Set the build command">
    Enter the command that compiles your site — for example, `npm run build`, `yarn build`, or `hugo`. Springwinter runs this command inside a clean environment with your repository checked out.
  </Step>

  <Step title="Set the publish directory">
    Enter the directory that contains the built output — for example, `dist`, `build`, `out`, or `public`. Springwinter uploads the contents of this directory to your S3 bucket.
  </Step>

  <Step title="Deploy">
    Click **Deploy**. Springwinter runs your build command, syncs the output to S3, and invalidates the CloudFront cache. Your site is live at the assigned CloudFront URL as soon as the invalidation completes.
  </Step>
</Steps>

## How Builds Work

Every deployment follows the same sequence:

1. Springwinter checks out the latest commit on the tracked branch.
2. Your **build command** runs in an isolated environment.
3. The contents of your **publish directory** are uploaded to your S3 bucket.
4. Springwinter creates a CloudFront cache invalidation so all cached files are purged.
5. CloudFront begins serving the new files from the nearest edge location.

<Info>
  The S3 bucket is not publicly accessible on its own. CloudFront is the only entry point, and Springwinter configures an Origin Access Control (OAC) policy to enforce this.
</Info>

## Configuration Options

<Accordion title="Build command">
  The shell command Springwinter runs to produce your static output — for example, `npm run build` or `yarn export`. The command runs from the repository root.
</Accordion>

<Accordion title="Publish directory">
  The path, relative to the repository root, where your build command writes its output files. Common values are `dist`, `build`, `out`, and `public`.
</Accordion>

<Accordion title="Auto-deploy">
  When enabled, every push to the tracked branch triggers a new build and deploy automatically. Disable auto-deploy if you need manual control over when updates go live.
</Accordion>

<Accordion title="Environment variables">
  Injected into the build environment at build time. Use them to pass API endpoints, feature flags, or other values your build tool needs. See [Environment Variables](/concepts/environment-variables).
</Accordion>

## API Reference

### Create a Static Website

```http theme={null}
POST /api/projects/{project_id}/static_websites
Authorization: Bearer <token>
Content-Type: application/json
```

```json theme={null}
{
  "name": "my-marketing-site",
  "repository": "my-org/my-site",
  "branch": "main",
  "build_command": "npm run build",
  "publish_directory": "dist",
  "auto_deploy": true
}
```

### Get a Static Website

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}
Authorization: Bearer <token>
```

### Update a Static Website

```http theme={null}
PATCH /api/projects/{project_id}/static_websites/{id}
Authorization: Bearer <token>
Content-Type: application/json
```

```json theme={null}
{
  "build_command": "yarn build",
  "publish_directory": "out"
}
```

## Redeploy

To trigger a manual rebuild and republish without pushing a commit:

```http theme={null}
POST /api/projects/{project_id}/static_websites/{id}/redeploy
Authorization: Bearer <token>
```

## Branch Previews

Each branch in your repository can have its own preview deployment with its own CloudFront URL, letting you verify changes before merging. Create a preview via the API:

```http theme={null}
POST /api/projects/{project_id}/static_websites/{id}/previews
Authorization: Bearer <token>
Content-Type: application/json
```

```json theme={null}
{
  "branch": "feature/new-landing-page"
}
```

<Tip>
  Share the preview URL with your team or stakeholders to get sign-off before merging to your production branch.
</Tip>

## Environment Variables

Retrieve the current build-time environment variables for a static website:

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/environment
Authorization: Bearer <token>
```

Replace all environment variables at once:

```http theme={null}
PUT /api/projects/{project_id}/static_websites/{id}/environment
Authorization: Bearer <token>
Content-Type: application/json
```

```json theme={null}
{
  "NEXT_PUBLIC_API_URL": "https://api.example.com",
  "NEXT_PUBLIC_ANALYTICS_ID": "UA-XXXXXXXXX"
}
```

<Note>
  For static websites, environment variables are injected at **build time**, not at runtime. Update your environment variables and trigger a redeploy to pick up changes.
</Note>

## Logs and Metrics

Build logs are available from the **Logs** tab in the dashboard or via:

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/logs
Authorization: Bearer <token>
```

CloudFront request and error metrics are available from the **Metrics** tab or via:

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/metrics
Authorization: Bearer <token>
```

## Cost Estimate

Retrieve the current S3 and CloudFront cost estimate for a static website:

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/cost
Authorization: Bearer <token>
```

## Teardown

To delete a static website and remove the S3 bucket and CloudFront distribution from your AWS account:

```http theme={null}
DELETE /api/projects/{project_id}/static_websites/{id}
Authorization: Bearer <token>
```

<Warning>
  Deleting a static website removes the S3 bucket and all its contents, along with the CloudFront distribution. This action cannot be undone. Download any assets you need to preserve before deleting.
</Warning>
