Deploy

Build output

Every template generates a static site:

npm run build    # → dist/

The dist/ folder contains plain HTML, CSS, JS and images — upload it to any static host.

Before you deploy

Update the site URL in astro.config.mjs:

export default defineConfig({
  site: "https://www.yourdomain.com",
  // ...
});

This sets canonical URLs, OG image paths and the sitemap base.

Cloudflare Pages

  1. Push your repo to GitHub or GitLab
  2. Cloudflare dashboard → Pages → Create project → Connect repository
  3. Build settings:
    • Build command: npm run build
    • Build output directory: dist
    • Node version: auto-detected from .node-version (22)
  4. Add your custom domain in Pages → Custom domains

Every push triggers a new deploy automatically.

Netlify

  1. Push your repo to GitHub or GitLab
  2. Netlify → Add new site → Import from Git
  3. Build settings are pre-configured in netlify.toml (included in every template):
    [build]
      command = "npm run build"
      publish = "dist"
  4. Add your custom domain in Site settings → Domain management

Vercel

  1. Push your repo to GitHub or GitLab
  2. Vercel → New project → Import repository
  3. Framework preset: Astro (auto-detected)
  4. Build command: npm run build, output: dist
  5. Set Node version to 22 in Settings → General

Any other host

npm run build
# Upload the contents of dist/ to your host

Templates are host-agnostic: the .node-version file and netlify.toml ship with every template for convenience, but work on any platform that serves static files.

Forms on different hosts

The reservation/contact form works differently depending on your host:

Host Setup
Formspree / Basin Paste your endpoint URL into formAction in site.ts — works everywhere
Netlify Forms work automatically via data-netlify="true" (already in markup)
Cloudflare / Vercel Use Formspree, Basin or any form API — set the endpoint in site.ts