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

# Deploy a static site

> Deploy an Astro, Vite or Hugo site to the CDN with no container.

A static site is built once and served from the CDN. There is no container, so there is no
compute allocation and no compute charge. You are metered on bandwidth only.

## Prerequisites

A site in a GitHub or GitLab repository whose build writes to a directory.

## Add slipway.yaml

**Astro**

```yaml slipway.yaml theme={"system"}
version: 1

services:
  - name: site
    type: static
    runtime: node
    runtimeVersion: "22"
    buildCommand: npm run build
    publish: dist
```

**Vite or React**

```yaml slipway.yaml theme={"system"}
version: 1

services:
  - name: site
    type: static
    runtime: node
    runtimeVersion: "22"
    buildCommand: npm run build
    publish: dist
    notFound: /index.html
```

`notFound` makes client-side routes resolve.

**Hugo**

```yaml slipway.yaml theme={"system"}
version: 1

services:
  - name: site
    type: static
    publish: public
```

Commit the built output, or add a `buildCommand` with a runtime that can run Hugo.

Getting `publish` wrong is the most common failure: the deploy goes green and the URL
returns 404. The build log reports how many files were uploaded, and the service's **Files**
view lists what is there.

| Tool | `publish` |
| - | - |
| Vite, Astro | `dist` |
| Create React App, SvelteKit static | `build` |
| Next.js export | `out` |
| Hugo, Gatsby | `public` |
| Jekyll, Eleventy | `_site` |

## Point it at an API

A static site's `env` applies to the **build**, so the value is baked into the files:

```yaml slipway.yaml theme={"system"}
services:
  - name: api
    runtime: docker
    ports:
      - port: 8080
        public: true

  - name: site
    type: static
    runtime: node
    buildCommand: npm run build
    publish: dist
    env:
      VITE_API_URL: ${service.api.public_url}
```

> [!WARNING]
>
> Anything referenced in a static site's `env` ends up inside the built files, which are
> public. Never put a secret there.

Use `public_url`, not `url`. A browser cannot reach the in-cluster address.

## Redirects and headers

```yaml slipway.yaml theme={"system"}
    redirects:
      - { from: /old-blog/*, to: /blog/:splat, status: 301 }
    headers:
      - for: /assets/*
        values:
          Cache-Control: "public, max-age=31536000, immutable"
```

slipway also reads `_redirects` and `_headers` files in the Netlify and Cloudflare Pages
format, so a site moving from either works unchanged. See
[Redirects and headers](/networking/static-routing).

## Upload instead of building

A static site is the one thing slipway serves with no repository. In **New → Static site**,
switch the source to **Upload a build** and drop a `.zip` of your output.

## Next steps

> **[Static sites](/services/static)**
>
> Caching, SPA fallback, atomic deploys and rollback.

> **[Custom domains](/networking/domains)**
>
> Serve under your own zone.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.