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

# Static Websites API: Deploy and Manage Sites

> Deploy, update, and monitor static websites backed by S3 and CloudFront in your AWS account using the Springwinter API.

Static websites are frontend applications that Springwinter builds from your GitHub repository and serves globally via Amazon S3 and CloudFront — all inside your own AWS account. Springwinter handles the build pipeline, S3 bucket configuration, CloudFront distribution, cache invalidation on each deploy, and optional branch preview URLs. This approach gives you the performance of a global CDN with the data sovereignty and cost visibility of your own infrastructure. All requests require a valid `Authorization: Bearer <token>` header or an active cookie session with a CSRF token.

***

## Launch a Static Website

```http theme={null}
POST /api/projects/{project_id}/static_websites
```

Creates and deploys a new static website. Springwinter clones the repository, runs your build command, uploads the output to S3, and creates a CloudFront distribution pointing at the bucket.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that will own this static website.
</ParamField>

### Body Parameters

<ParamField body="name" type="string" required>
  Display name for the static website. Used in the dashboard and to derive the CloudFront subdomain.
</ParamField>

<ParamField body="repo" type="string" required>
  GitHub repository full name in `owner/repo` format (e.g. `acme/marketing-site`). The Springwinter GitHub App must already be installed on this repository.
</ParamField>

<ParamField body="branch" type="string" required>
  Git branch to build and deploy (e.g. `main`).
</ParamField>

<ParamField body="build_command" type="string" required>
  Shell command Springwinter runs to produce the static output (e.g. `npm run build` or `hugo`).
</ParamField>

<ParamField body="publish_dir" type="string" required>
  Directory that contains the built output files to upload to S3 (e.g. `dist`, `out`, `public`).
</ParamField>

<ParamField body="auto_deploy" type="boolean" default="false">
  When `true`, Springwinter automatically rebuilds and deploys the site on every push to the configured branch.
</ParamField>

```json theme={null}
{
  "name": "marketing-site",
  "repo": "acme/marketing-site",
  "branch": "main",
  "build_command": "npm run build",
  "publish_dir": "dist",
  "auto_deploy": true
}
```

### Response — `201 Created`

```json theme={null}
{
  "id": "sw_01h8xkr2m4fgz3nvq7p0c5w9",
  "name": "marketing-site",
  "status": "deploying",
  "url": "https://marketing-site.storefront.springwinter.app",
  "repo": "acme/marketing-site",
  "branch": "main",
  "build_command": "npm run build",
  "publish_dir": "dist",
  "auto_deploy": true
}
```

***

## Get a Static Website

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}
```

Returns the current configuration and deployment status of a static website.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

### Response

```json theme={null}
{
  "id": "sw_01h8xkr2m4fgz3nvq7p0c5w9",
  "name": "marketing-site",
  "status": "running",
  "url": "https://marketing-site.storefront.springwinter.app",
  "repo": "acme/marketing-site",
  "branch": "main",
  "build_command": "npm run build",
  "publish_dir": "dist",
  "auto_deploy": true
}
```

***

## Update a Static Website

```http theme={null}
PATCH /api/projects/{project_id}/static_websites/{id}
```

Updates one or more mutable settings on a static website. Changing build settings or the source branch triggers an automatic rebuild and redeploy.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website to update.
</ParamField>

### Body Parameters

<ParamField body="branch" type="string">
  Switch deployments to a different Git branch.
</ParamField>

<ParamField body="build_command" type="string">
  Updated build command.
</ParamField>

<ParamField body="publish_dir" type="string">
  Updated publish directory.
</ParamField>

<ParamField body="auto_deploy" type="boolean">
  Enable or disable automatic deployments on push.
</ParamField>

### Response

Returns the updated static website object with `"status": "deploying"` if a rebuild was triggered.

```json theme={null}
{
  "id": "sw_01h8xkr2m4fgz3nvq7p0c5w9",
  "name": "marketing-site",
  "status": "deploying",
  "url": "https://marketing-site.storefront.springwinter.app",
  "repo": "acme/marketing-site",
  "branch": "release",
  "build_command": "npm run build",
  "publish_dir": "dist",
  "auto_deploy": true
}
```

***

## Delete a Static Website

```http theme={null}
DELETE /api/projects/{project_id}/static_websites/{id}
```

Tears down the CloudFront distribution, empties and deletes the S3 bucket, and removes all other AWS resources associated with this site. This operation is irreversible.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website to delete.
</ParamField>

### Response — `204 No Content`

An empty body on success.

***

## Redeploy a Static Website

```http theme={null}
POST /api/projects/{project_id}/static_websites/{id}/redeploy
```

Triggers an immediate rebuild and redeploy from the current branch, regardless of whether any new commits exist. Springwinter runs the build command, syncs the output to S3, and issues a CloudFront cache invalidation.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

### Response — `202 Accepted`

```json theme={null}
{
  "status": "deploying"
}
```

***

## Get Build Logs

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/logs
```

Returns log lines from the most recent build run for this static website. Build logs capture the output of your `build_command` and Springwinter's S3 upload step.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

### Response

```json theme={null}
{
  "lines": [
    {
      "timestamp": "2024-06-01T14:00:01Z",
      "message": "Running build command: npm run build"
    },
    {
      "timestamp": "2024-06-01T14:00:28Z",
      "message": "Build succeeded. Uploading 412 files to S3..."
    },
    {
      "timestamp": "2024-06-01T14:00:31Z",
      "message": "Upload complete. Issuing CloudFront invalidation."
    }
  ]
}
```

***

## Get Metrics

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/metrics
```

Returns CloudFront and S3 metrics for the static website including request count, bytes transferred, and error rate.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

### Response

```json theme={null}
{
  "requests_1h": 52341,
  "bytes_transferred_1h": 4831200000,
  "error_rate_percent": 0.03,
  "cache_hit_rate_percent": 97.8
}
```

***

## Get Cost Estimate

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/cost
```

Returns the estimated spend to date this month and the projected monthly run rate for this static website based on CloudFront data transfer, S3 storage, and request counts.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

### Response

```json theme={null}
{
  "spend_this_month_usd": 0.94,
  "monthly_run_rate_usd": 3.10,
  "currency": "USD"
}
```

***

## Get Environment Variables

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/environment
```

Returns the build-time environment variables injected into the static website's build command.

<Note>
  Environment variables for static websites are **build-time only**. They are available during `build_command` execution (e.g. as `VITE_` or `NEXT_PUBLIC_` prefixed variables that get inlined into your bundle), but they are **not** injected at runtime into the served files. Changing environment variables triggers a full rebuild so the new values are baked into the next deployment.
</Note>

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

### Response

```json theme={null}
{
  "environment": [
    { "name": "VITE_API_URL", "value": "https://api.storefront.springwinter.app" },
    { "name": "VITE_ANALYTICS_ID", "value": "UA-123456789-1" }
  ]
}
```

***

## Replace Environment Variables

```http theme={null}
PUT /api/projects/{project_id}/static_websites/{id}/environment
```

Replaces the complete set of build-time environment variables for this static website and triggers a rebuild so the new values are baked into the next deployment.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

### Body Parameters

<ParamField body="environment" type="array" required>
  Array of `{ "name": string, "value": string }` objects. This list fully replaces the existing build environment — any variable not included in the request is removed.
</ParamField>

<Warning>
  This endpoint performs a full replacement, not a merge. Any environment variable you omit from the request body will be permanently deleted. Fetch the current environment with `GET .../environment` first, merge your changes, and then submit the complete list. Because these variables are build-time only, a new deployment is triggered automatically after each successful PUT.
</Warning>

```json theme={null}
{
  "environment": [
    { "name": "VITE_API_URL", "value": "https://api.storefront.springwinter.app" },
    { "name": "VITE_ANALYTICS_ID", "value": "UA-123456789-1" },
    { "name": "VITE_FEATURE_FLAG", "value": "true" }
  ]
}
```

### Response — `202 Accepted`

```json theme={null}
{
  "status": "deploying"
}
```

***

## Previews

Static website previews let you deploy every branch to its own CloudFront distribution with a unique URL. This is ideal for design review, stakeholder sign-off, and end-to-end testing before merging into the production branch.

### Create a Preview

```http theme={null}
POST /api/projects/{project_id}/static_websites/{id}/previews
```

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

#### Body Parameters

<ParamField body="branch" type="string" required>
  The Git branch to build and deploy as a preview site.
</ParamField>

```json theme={null}
{ "branch": "feat/homepage-redesign" }
```

**Response — `201 Created`**

```json theme={null}
{
  "id": "prev_05m2bos6q8jke7ryu1t4g9a3",
  "branch": "feat/homepage-redesign",
  "url": "https://marketing-site-feat-homepage-redesign.storefront.springwinter.app",
  "status": "deploying"
}
```

***

### Get a Preview

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/previews/{preview_id}
```

Returns the preview object including its URL, source branch, and current status.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

<ParamField path="preview_id" type="string" required>
  The unique ID of the preview deployment.
</ParamField>

#### Response

```json theme={null}
{
  "id": "prev_05m2bos6q8jke7ryu1t4g9a3",
  "branch": "feat/homepage-redesign",
  "url": "https://marketing-site-feat-homepage-redesign.storefront.springwinter.app",
  "status": "running"
}
```

***

### Delete a Preview

```http theme={null}
DELETE /api/projects/{project_id}/static_websites/{id}/previews/{preview_id}
```

Empties the preview S3 bucket, removes the CloudFront distribution, and clears all DNS records for the preview URL.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

<ParamField path="preview_id" type="string" required>
  The unique ID of the preview deployment to delete.
</ParamField>

#### Response — `204 No Content`

An empty body on success.

<Tip>
  Springwinter can automatically delete previews when their source branch is merged or deleted in GitHub. Enable this in your project's GitHub settings to keep your AWS account free of stale CloudFront distributions.
</Tip>

***

### Preview Build Logs

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/previews/{preview_id}/logs
```

Returns build log lines for the preview deployment in the same format as the main site logs endpoint.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

<ParamField path="preview_id" type="string" required>
  The unique ID of the preview deployment.
</ParamField>

#### Response

```json theme={null}
{
  "lines": [
    {
      "timestamp": "2024-06-01T16:00:01Z",
      "message": "Running build command: npm run build"
    },
    {
      "timestamp": "2024-06-01T16:00:24Z",
      "message": "Build succeeded. Uploading 412 files to S3..."
    },
    {
      "timestamp": "2024-06-01T16:00:27Z",
      "message": "Upload complete. Issuing CloudFront invalidation."
    }
  ]
}
```

***

### Preview Metrics

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/previews/{preview_id}/metrics
```

Returns CloudFront request and error metrics for the preview deployment.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

<ParamField path="preview_id" type="string" required>
  The unique ID of the preview deployment.
</ParamField>

#### Response

```json theme={null}
{
  "requests_1h": 87,
  "bytes_transferred_1h": 9830400,
  "error_rate_percent": 0.0,
  "cache_hit_rate_percent": 94.3
}
```

***

### Preview Environment Variables

```http theme={null}
GET /api/projects/{project_id}/static_websites/{id}/previews/{preview_id}/environment
```

Returns the build-time environment variables used when the preview was last built. These are the values that were baked into the preview's static assets at build time.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the static website.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the static website.
</ParamField>

<ParamField path="preview_id" type="string" required>
  The unique ID of the preview deployment.
</ParamField>

#### Response

```json theme={null}
{
  "environment": [
    { "name": "VITE_API_URL", "value": "https://api.storefront.springwinter.app" },
    { "name": "VITE_ANALYTICS_ID", "value": "UA-123456789-1" },
    { "name": "VITE_FEATURE_FLAG", "value": "true" }
  ]
}
```
