# Static Sites



Clusterbase can serve static sites — HTML, CSS, JavaScript, images — alongside your handler function. HTML files are inlined into your handler at build time, while other assets are served via the edge CDN.

## Getting Started [#getting-started]

Use the static template:

```bash
ccp init my-site --template static
```

This creates:

```
my-site/
  index.ts            # Handler that serves HTML
  public/
    index.html        # Your HTML page
  globals.d.ts        # TypeScript types for __pages
  .ccp/config.json
  package.json
```

## How It Works [#how-it-works]

When you deploy with `--public-dir`, the CLI:

1. Reads all `.html` files from the public directory
2. Inlines them as strings into a `__pages` global object at build time
3. Uploads all non-HTML files (CSS, JS, images) to the CDN
4. Your handler serves HTML from `__pages`, and the CDN serves everything else

## The `__pages` Global [#the-__pages-global]

HTML files from your public directory are available as `__pages`:

```ts
export function handler(request: Request): Response {
  return new Response(__pages["index.html"], {
    headers: { "Content-Type": "text/html" },
  });
}
```

The `globals.d.ts` file provides the TypeScript type:

```ts
declare const __pages: Record<string, string>;
```

## SPA Routing [#spa-routing]

For single-page apps, serve `index.html` for all non-asset routes:

```ts
export function handler(request: Request): Response {
  const url = new URL(request.url);

  // API routes
  if (url.pathname.startsWith("/api/")) {
    return Response.json({ message: "Hello" });
  }

  // Serve the SPA shell for all other routes
  return new Response(__pages["index.html"], {
    headers: { "Content-Type": "text/html" },
  });
}
```

## Deploying [#deploying]

```bash
# Deploy with the public directory
ccp deploy --prod --public-dir public

# Or if .ccp/config.json has "assets": "public"
ccp deploy --prod
```

The `--public-dir` flag can also be set permanently in `.ccp/config.json`:

```json
{
  "assets": "public"
}
```

## CDN Asset Serving [#cdn-asset-serving]

Non-HTML assets (JS, CSS, images, fonts) are served via Clusterbase's edge CDN with:

* **gzip compression**
* **301 redirect** from your function domain to the CDN URL
* **Handler-first model** for HTML — your handler controls HTML responses, not the CDN

### Nested directories [#nested-directories]

Subdirectories under `public/` are preserved at their URL path — no need to
flatten your assets:

```
public/
  index.html
  styles/app.css        → /styles/app.css
  fonts/Inter.woff2     → /fonts/Inter.woff2
  posts/index.json      → /posts/index.json
```

Each file is served at its original public path regardless of nesting depth.

## Local Development [#local-development]

```bash
ccp dev --public-dir public
```

Static files are served directly from disk during local dev. Changes to HTML files trigger a hot reload.
