# Deployment

> Publish a vagejs site to Cloudflare Workers, GitHub Pages or Cloudflare Pages safely, with checks first and no downtime on Cloudflare.

Every deploy runs `vage check` and `vage build` first, shows you its plan, and asks before it changes anything. Use `--dry-run` to see the plan, and `--yes` once you've reviewed it. A deploy only reports success when the live site answers.

## Cloudflare Workers (recommended on Cloudflare)

Cloudflare now hosts new static sites as Workers. Set the target once:

```ts
// vage.config.ts
deploy: { target: "cloudflare-workers", cloudflareWorker: "my-site" },
```

```bash
npx vage deploy
```

vagejs uploads a new version and switches all traffic to it, so a custom domain never goes offline during a deploy. Your 404 page, redirects (as real 301s) and security headers all work.

**Custom domains:** add a `wrangler.jsonc` with your routes. vagejs uses it, shows its Worker name in the plan, and refuses to deploy if the file points at a different Worker or folder than expected:

```jsonc
{
  "name": "my-site",
  "compatibility_date": "2026-10-01",
  "routes": [{ "pattern": "example.com", "custom_domain": true }],
  "assets": { "directory": "dist", "not_found_handling": "404-page" }
}
```

Sign in with `npx wrangler login`, or set `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID`.

## GitHub Pages

```bash
npx vage deploy:github --remote https://github.com/you/site.git   # first push
npx vage deploy                                                  # target: github-pages (the default)
```

`deploy:github` refuses to commit secret-looking files, `dist/` or `node_modules/`, and never force-pushes. `deploy` adds a GitHub Actions workflow that checks, builds and publishes, then waits for GitHub to confirm. GitHub Pages needs a custom domain or a `<user>.github.io` repository.

## Cloudflare Pages

```bash
npx vage deploy --target cloudflare-pages --project my-site
```

For existing Pages projects. Branches other than production get their own preview address. For new sites, use Workers.

## After you deploy

```bash
npx vage verify                          # the live site matches your files
npx vage indexnow --changed-since HEAD~1 # tell IndexNow search engines what changed
```

`verify` catches anything on the live site that isn't in your project, such as injected links, scripts or pages. IndexNow needs a key in `integrations.indexNow` and is a hint, not a guarantee of crawling.
