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

# Publish a Canopy site

> Create, update, and redeploy static sites

Publishing routes require an ECS API key with `canopy:write`.

## Asset format

`assets` maps site-relative file paths to file descriptors:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "index.html": {
    "content": "<!doctype html><html><body><h1>Hello</h1></body></html>"
  },
  "styles.css": {
    "content": "body { color: seagreen; }"
  },
  "app.js": {
    "content": "console.log('hello');",
    "encoding": "utf-8"
  }
}
```

`encoding` defaults to `utf-8` and may be `base64`. Use `base64` for images, fonts, archives, and other binary files.

Asset paths are site-relative. Include every referenced CSS, JavaScript, image, font, and data file in the asset map.

## Create a site

`POST /canopy/sites`

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "name": "marketing-site",
  "spa": true,
  "assets": {
    "index.html": {
      "content": "<!doctype html><html><body><div id=\"app\"></div></body></html>"
    }
  }
}
```

`name` and `assets` are required. `spa` defaults to `false`.

The response is `201 Created` and includes a `revision_id` and `revision_status`. Save the revision ID for status checks.

## Redeploy a site

`PATCH /canopy/sites/:name`

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "assets": {
    "index.html": {
      "content": "<!doctype html><html><body>Updated</body></html>"
    }
  }
}
```

`assets` is required. Redeploy with the complete asset map for the desired site version. Treat the request as the next published site state rather than a partial file patch.

## List and inspect

* `GET /canopy/sites` returns `{ "sites": [...] }`.
* `GET /canopy/sites/:name` returns one site record.

Both require `canopy:read`.

## Delete

`DELETE /canopy/sites/:name` requires `canopy:delete` and returns `204 No Content`.

## Publish checklist

* Include `index.html`.
* Check path casing in every reference.
* Use `base64` for binary assets.
* Enable `spa` if browser-side routing owns application paths.
* Poll status before promoting the new site URL.
