diff --git a/.changeset/sites-docs.md b/.changeset/sites-docs.md new file mode 100644 index 00000000..1d6daa8d --- /dev/null +++ b/.changeset/sites-docs.md @@ -0,0 +1,5 @@ +--- +"@bunny.net/cli": patch +--- + +Correct the `bunny sites` command reference and agent skill: `deployments delete`, `--tier`, `ci init --force`, and which commands take `--site` and `--link` diff --git a/README.md b/README.md index 91a5275d..9da1354c 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ bun ny stream transcribe 1a2b3c4d-... --languages en,de # paid: transcribe the bun ny stream smart 1a2b3c4d-... --title --chapters # paid: generate a title and chapters from the transcript (offers to transcribe first if the video has no captions) ``` -Every deploy is published as the live site. Deploys are immutable under their own ID, so `bun ny sites deployments publish` rolls back to any earlier one without re-uploading. Preconfigure the `sites` block in `bunny.jsonc` (`name`, `build`, `dir`) so a deploy needs no flags: `bun ny sites deploy --build`. `bun ny sites ci init` writes the same `build` and `dir` into the generated workflow. See [`examples/sites/`](examples/sites/) for ready-to-copy configs (Vite, Astro, Next.js static export, Hugo, plain HTML, and a combined app + site file). +Every deploy is published as the live site. Deploys are immutable under their own ID, so `bun ny sites deployments publish` rolls back to any earlier one without re-uploading. Preconfigure the `sites` block in `bunny.jsonc` (`name`, `build`, `dir`, `spa`) so a deploy needs no flags: `bun ny sites deploy --build`. `bun ny sites ci init` writes the same `build` and `dir` into the generated workflow. See [`examples/sites/`](examples/sites/) for ready-to-copy configs (Vite, Astro, Next.js static export, Hugo, plain HTML, and a combined app + site file). ### Available scripts diff --git a/examples/sites/README.md b/examples/sites/README.md index 698b6b7a..5984b9a4 100644 --- a/examples/sites/README.md +++ b/examples/sites/README.md @@ -23,7 +23,6 @@ With `name`, `build`, and `dir` set, the entire deploy is one command: ```bash bun ny sites deploy --build # runs `build`, uploads `dir`, publishes it live -bun ny sites deploy --build # same, published as the live site ``` No `--site`, no build command, no directory argument. Without the config you'd diff --git a/packages/cli/README.md b/packages/cli/README.md index f87bd5ce..0f665dbf 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1037,13 +1037,14 @@ Host static sites on bunny.net. Each site is two resources provisioned and wired Deploys are immutable: every `sites deploy` uploads to its own `deploys//` directory and then goes live. Publishing retargets the pull zone's rewrite rule and purges the cache, so going live and rolling back to any earlier deploy are instant and move no files. HTML is served with `max-age=0` so browsers pick up new deploys immediately, while static assets get a one-day browser cache. Deploy IDs are the git short SHA when the working tree is clean and a content hash otherwise, which makes redeploying identical content a no-op. -Commands take the site as an optional positional (`[site]`), except `deploy`, `ci init`, and `deployments publish`, which use `--site`. Either accepts the site name or its storage zone ID. When omitted, the site resolves from the directory's linked site (`.bunny/site.json`, written by `sites link` or by `create`/`deploy`), then `sites.name` in `bunny.jsonc`, then an interactive picker that offers to link. Non-interactive runs (`--output json`, no TTY, or `--force` on a destructive command) error instead of prompting. +Commands take the site as an optional positional (`[site]`), except `deploy`, `ci init`, `deployments publish`, and `deployments delete`, which use `--site`. Either accepts the site name or its storage zone ID. When omitted, the site resolves from the directory's linked site (`.bunny/site.json`, written by `sites link` or by `create`/`deploy`), then `sites.name` in `bunny.jsonc`, then an interactive picker that offers to link. Non-interactive runs (`--output json`, no TTY, or `--force` on a destructive command) error instead of prompting. ```bash # Provision a site bunny sites create # interactive: prompts for a name (directory-name suggestion) bunny sites create my-site # served at sites-my-site-.b-cdn.net bunny sites create my-site --region NY # store the files in New York (default: DE) +bunny sites create my-site --tier ssd # Edge (SSD) storage tier; DE only, fixed at creation bunny sites create my-site --domain example.com # also attach a custom production domain bunny sites create my-site --from-zone my-zone # import an existing storage zone + pull zone, keeping its hostnames @@ -1055,11 +1056,12 @@ bunny sites deploy --build "npm run build" --env API_URL=https://api.example.com bunny sites deploy ./dist --site my-site --force # target a site explicitly; redeploy unchanged content bunny sites deploy ./catalog --deploy-id 20260827-1433-r42 # your own release ID instead of the git sha / content hash -# Deploys: list, publish (roll back), prune +# Deploys: list, publish (roll back), prune, delete bunny sites deployments list # ● Live / ○ Previous markers, created, source, files, size bunny sites deployments publish a1b2c3d4 # promote a past deploy (alias: promote) bunny sites deployments publish --previous # instant rollback bunny sites deployments prune --keep 10 # delete old deploys (default keeps 5; never live/previous) +bunny sites deployments delete a1b2c3d4 --force # delete one deploy (never the live or rollback deploy) # Custom production domains bunny sites domains list @@ -1091,24 +1093,26 @@ Preconfigure the `sites` block in `bunny.jsonc` (`name`, `build`, `dir`, `spa`) Every deploy publishes: the files land in an immutable `deploys//` directory and the rewrite rule is pointed at it, so `deployments publish` rolls back to any earlier deploy by moving that pointer, with no files moving and nothing re-uploaded. The ID is the git short-sha when the tree is clean, a content hash otherwise, or whatever `--deploy-id` supplies (letters, digits, `-`, `_`, `.`; 4-64 chars; case-sensitive): a custom ID never aliases onto another deploy's content, and reusing one for different content asks before replacing (`--force` skips the prompt); a replacement clears the old files first, so nothing stale survives. The live deploy and the rollback target are never replaced in place; deploy those under a new ID. Content is root-served, so absolute asset paths work as-is. Direct `/deploys//` URLs are blocked at the edge. Site state lives at `_bunny/site.json` inside the storage zone (also blocked at the edge); `.bunny/site.json` is only a local pointer, so a fresh clone can `sites link` and pick up where the last machine left off. -| Flag | Commands | Description | -| -------------------------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| `--region`, `--domain` | `create` | Main storage region code (default `DE`); custom production domain to attach | -| `--from-zone` | `create` | Import an existing storage zone (name or ID) and its pull zone instead of creating them | -| `--site` | `deploy`, `ci init`, `deployments publish` | Site name or storage zone ID (defaults to the linked site) | -| `--build [cmd]`, `--env`, `--env-file` | `deploy` | Build before deploying (bare flag uses the configured or detected build); build-time env overrides | -| `--force` | `deploy` | Deploy even when the content is unchanged, and replace an existing `--deploy-id` without asking | -| `--deploy-id` | `deploy` | Identify the deploy yourself (release tag, catalog ID); case-sensitive, used exactly as given | -| `--spa`, `--no-spa` | `deploy` | Serve `index.html` for client-side routes, or the 404 page; beats `sites.spa` and framework detection, skips the prompt | -| `--previous` | `deployments publish` | Publish the previous deploy (instant rollback) | -| `--keep` | `deployments prune` | Number of recent deploys to keep (default 5; live and previous are always kept) | -| `--ssl`, `--wait`, `--force-ssl` | `domains add` | Issue SSL now; wait up to 10 minutes for DNS then issue it; `--no-force-ssl` keeps HTTP working | -| `--force-ssl` | `ssl` | Force HTTP→HTTPS on the system host; `--no-force-ssl` allows plain HTTP | -| `--framework` | `ci init` | Framework preset for the workflow's build steps (default: detected) | -| `--print` | `open` | Print the URL instead of opening a browser | -| `--link` | `create`, `deploy`, `show`, `ci init`, `deployments` | Link the directory to the site; `--no-link` never links | -| `--keep-storage` | `delete` | Delete the pull zone but keep the storage zone and its deploy files | -| `--force`, `-f` | `create --from-zone`, `deployments publish`, `prune`, `domains remove`, `delete` | Skip the confirmation prompts | +| Flag | Commands | Description | +| -------------------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `--region`, `--domain` | `create` | Main storage region code (default `DE`); custom production domain to attach | +| `--tier` | `create` | Storage tier, `hdd` or `ssd` (`ssd` is `DE` only); fixed once the site exists | +| `--from-zone` | `create` | Import an existing storage zone (name or ID) and its pull zone instead of creating them | +| `--site` | `deploy`, `ci init`, `deployments publish`, `deployments delete` | Site name or storage zone ID (defaults to the linked site) | +| `--build [cmd]`, `--env`, `--env-file` | `deploy` | Build before deploying (bare flag uses the configured or detected build); build-time env overrides | +| `--force` | `deploy` | Deploy even when the content is unchanged, and replace an existing `--deploy-id` without asking | +| `--deploy-id` | `deploy` | Identify the deploy yourself (release tag, catalog ID); case-sensitive, used exactly as given | +| `--spa`, `--no-spa` | `deploy` | Serve `index.html` for client-side routes, or the 404 page; beats `sites.spa` and framework detection, skips the prompt | +| `--previous` | `deployments publish` | Publish the previous deploy (instant rollback) | +| `--keep` | `deployments prune` | Number of recent deploys to keep (default 5; live and previous are always kept) | +| `--ssl`, `--wait`, `--force-ssl` | `domains add` | Issue SSL now; wait up to 10 minutes for DNS then issue it; `--no-force-ssl` keeps HTTP working | +| `--force-ssl` | `ssl` | Force HTTP→HTTPS on the system host; `--no-force-ssl` allows plain HTTP | +| `--framework` | `ci init` | Framework preset for the workflow's build steps (default: detected) | +| `--force` | `ci init` | Overwrite an existing workflow file | +| `--print` | `open` | Print the URL instead of opening a browser | +| `--link` | `create`, `deploy`, `show`, `ci init`, `deployments list`, `deployments publish` | Link the directory to the site; `--no-link` never links | +| `--keep-storage` | `delete` | Delete the pull zone but keep the storage zone and its deploy files | +| `--force`, `-f` | `create --from-zone`, `deployments publish`/`prune`/`delete`, `domains remove`, `delete` | Skip the confirmation prompts | ### `bunny stream` diff --git a/skills/bunny-cli/references/sites.md b/skills/bunny-cli/references/sites.md index 8b907231..5b98bb1f 100644 --- a/skills/bunny-cli/references/sites.md +++ b/skills/bunny-cli/references/sites.md @@ -39,7 +39,7 @@ This is the rule that shapes every other command here: - Deploys stay immutable under their own ID, so `deployments publish ` rolls back to any earlier one by retargeting the edge rule; no files move and nothing is re-uploaded. - Custom domains are vanity hostnames on the site's pull zone; without one the site serves at `https://sites--.b-cdn.net`. -Content is root-served, so root-absolute assets work as-is. Single-page apps get `index.html` for extensionless misses when the detected framework is client-routed (Vite, CRA, React Router, Angular, Vue CLI, Ember, Preact) and the output has no root `404.html`; `sites.spa` in `bunny.jsonc` or `--spa`/`--no-spa` on the deploy decides explicitly, and otherwise a root `404.html` is the not-found page. The mode is recorded per deploy and follows rollbacks. Deploys are not individually addressable: `/deploys//` URLs are internal to the storage layout and are not publicly served. To review a change before it goes live, build and serve it locally, or deploy it to a separate site. +Content is root-served, so root-absolute assets work as-is. Single-page apps get `index.html` for extensionless misses when the detected framework is client-routed (Vite, CRA, React Router, Angular, Vue CLI, Ember, Preact, Blazor WebAssembly) and the output has no root `404.html`; `sites.spa` in `bunny.jsonc` or `--spa`/`--no-spa` on the deploy decides explicitly, and otherwise a root `404.html` is the not-found page. The mode is recorded per deploy and follows rollbacks. Deploys are not individually addressable: `/deploys//` URLs are internal to the storage layout and are not publicly served. To review a change before it goes live, build and serve it locally, or deploy it to a separate site. ## Deploy IDs @@ -53,7 +53,7 @@ Content is root-served, so root-absolute assets work as-is. Single-page apps get --- -## `bunny sites create`; Provision a site +## `bunny sites create`: Provision a site ```bash bunny sites create # uses `sites.name` from bunny.jsonc, else prompts (directory-name suggestion), then a custom domain @@ -64,18 +64,20 @@ bunny sites create my-site --domain example.com bunny sites create my-site --no-link # don't write .bunny/site.json ``` -| Flag | Description | -| ---------- | -------------------------------------------------------------------------------------------------- | -| `--region` | Main storage region code (default `DE`) | -| `--tier` | Storage tier: `hdd` (Standard) or `ssd` (Edge, always `DE`); create-time only | -| `--domain` | Attach a custom production domain after provisioning; interactive runs prompt for one when omitted | -| `--link` | Link this directory (default true; `--no-link` to skip) | +| Flag | Description | +| --------------- | --------------------------------------------------------------------------------------------------- | +| `--region` | Main storage region code (default `DE`) | +| `--tier` | Storage tier: `hdd` (Standard) or `ssd` (Edge, always `DE`); create-time only | +| `--domain` | Attach a custom production domain after provisioning; interactive runs prompt for one when omitted | +| `--link` | Link this directory (default true; `--no-link` to skip) | +| `--from-zone` | Import an existing storage zone (name or ID) and its pull zone as the site instead of creating them | +| `--force`, `-f` | Skip the import confirmation (only with `--from-zone`) | Site names are 3-47 lowercase letters, digits, and dashes. The storage zone, pull zone, and b-cdn.net subdomain become `sites--xxxxxx` (a `sites-` prefix marking them in the dashboard, plus a shared random suffix since zone names are global across bunny.net); commands still take the clean site name. Creation is idempotent; a failed create re-runs cleanly, reusing whatever was already provisioned. --- -## `bunny sites deploy`; Deploy a directory +## `bunny sites deploy`: Deploy a directory ```bash bunny sites deploy ./dist # deploy and publish as the live site @@ -83,15 +85,17 @@ bunny sites deploy --build # run `sites.build` from bunny.jsonc bunny sites deploy ./out --build "npm run build" --env VITE_FLAG=1 ``` -| Flag | Description | -| ------------ | -------------------------------------------------------------------- | -| `[dir]` | Directory to deploy (default: `sites.dir` in bunny.jsonc, then cwd) | -| `--build` | Run a build first (bare flag: `sites.build`, else a detected build) | -| `--env` | Build-time env override `KEY=VALUE` (repeatable; requires `--build`) | -| `--env-file` | Dotenv file of build-time overrides (requires `--build`) | -| `--force` | Deploy even when content is unchanged | -| `--site` | Target site (name or storage zone ID) | -| `--link` | Link this directory to the deployed site (`--no-link` never links) | +| Flag | Description | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| `[dir]` | Directory to deploy (default: `sites.dir` in bunny.jsonc, then the detected framework's output dir when building, then cwd) | +| `--build` | Run a build first (bare flag: `sites.build`, else a detected build) | +| `--env` | Build-time env override `KEY=VALUE` (repeatable; requires `--build`) | +| `--env-file` | Dotenv file of build-time overrides (requires `--build`) | +| `--force` | Deploy even when content is unchanged | +| `--site` | Target site (name or storage zone ID) | +| `--link` | Link this directory to the deployed site (`--no-link` never links) | +| `--deploy-id` | Your own deploy ID (release tag, catalog build); see Deploy IDs | +| `--spa`, `--no-spa` | Serve `index.html` for client-side routes, or the 404 page; beats `sites.spa` and detection | With `--build`, the build runs in your shell environment plus the `--env`/`--env-file` overrides; there is no remote env store; put build-time values in your local `.env` or CI secrets. Redeploying content that is already uploaded skips the upload and just republishes it; when it is already live, the deploy is a no-op unless you pass `--force`. @@ -103,14 +107,14 @@ Interactive `deploy` adds two conveniences (both skipped under `--output json`): --- -## `bunny sites deployments`; List, publish, prune, delete +## `bunny sites deployments`: List, publish, prune, delete ```bash bunny sites deployments list bunny sites deployments publish a1b2c3d4 # confirm prompt; --force to skip bunny sites deployments publish --previous # instant rollback bunny sites deployments prune --keep 10 # never prunes current/previous -bunny sites deployments prune my-site # or --site my-site +bunny sites deployments prune my-site # target a site other than the linked one bunny sites deployments delete a1b2c3d4 --force # delete one deploy ``` @@ -120,7 +124,7 @@ bunny sites deployments delete a1b2c3d4 --force # delete one deploy --- -## `bunny sites domains`; Custom domains +## `bunny sites domains`: Custom domains ```bash bunny sites domains add example.com --wait # wait for DNS, then issue SSL @@ -133,7 +137,7 @@ A custom domain is the site's production URL and nothing more. The first added d --- -## `bunny sites ci init`; GitHub Actions deployments +## `bunny sites ci init`: GitHub Actions deployments ```bash bunny sites ci init # detect the framework, write .github/workflows/bunny-sites.yml @@ -167,13 +171,14 @@ An optional `sites` block configures the deploy defaults (validated on its own, "name": "my-site", // resolves the site when nothing is linked "dir": "./dist", // default deploy directory "build": "npm run build", // command for `deploy --build` + "spa": true, // serve index.html for client-side routes (omit to detect) }, } ``` ## CI / agents -- Pass `--force` on anything with a confirmation (publish, prune, remove, delete); without a TTY they error with a hint rather than waiting on a prompt. +- Pass `--force` on anything with a confirmation (publish, prune, remove, delete, `create --from-zone`); without a TTY they error with a hint rather than waiting on a prompt. - Pass the site explicitly (or commit `bunny.jsonc` with `sites.name`); the interactive picker is disabled under `--output json` and by `--force`, so `sites delete --force` with nothing linked errors instead of prompting. - `--output json` on every command emits machine-readable results. `deploy` prints `{ id, production, unchanged, live }`, where `production` is `null` on a site whose hostname couldn't be read. - The first-deploy custom-domain prompt never runs under `--output json` or without a TTY, so CI deploys are unaffected.