title: Deploy
shell: standard
components:
- type: header
title: Deploy
eyebrow: Any static host works
subtitle: "Run `kazam build . --out dist --release` once — the output is a self-contained folder of HTML, CSS, and assets. Every recipe below is just how to upload that folder somewhere with a URL."
- type: section
eyebrow: Recipes
heading: Pick a host
components:
- type: tabs
tabs:
- label: Vercel
components:
- type: markdown
body: |
Zero config. Install the CLI, point it at a built directory.
- type: code
language: bash
code: |
kazam build . --out dist --release
# One-time:
npm i -g vercel
vercel login
# Deploy (first time prompts to link a project):
vercel --prod dist
- type: markdown
body: |
For Git-driven deploys, check in a `vercel.json`:
- type: code
language: json
code: |
{
"buildCommand": "cargo install --git https://github.com/tdiderich/kazam && kazam build . --out dist --release",
"outputDirectory": "dist",
"framework": null
}
- label: Netlify
components:
- type: markdown
body: |
Same drill — Netlify treats any directory as a static site.
- type: code
language: bash
code: |
kazam build . --out dist --release
# One-time:
npm i -g netlify-cli
netlify login
# Deploy:
netlify deploy --prod --dir=dist
- type: markdown
body: |
For Git-driven builds, add a `netlify.toml`:
- type: code
language: toml
code: |
[build]
command = "cargo install --git https://github.com/tdiderich/kazam && kazam build . --out dist --release"
publish = "dist"
- label: Cloudflare Pages
components:
- type: markdown
body: |
Free, fast edge hosting with a generous free tier.
- type: code
language: bash
code: |
kazam build . --out dist --release
# One-time:
npm i -g wrangler
wrangler login
# Deploy:
wrangler pages deploy dist --project-name my-site
- type: markdown
body: |
For Git-driven builds in the Cloudflare dashboard, set:
**Build command**: `cargo install --git https://github.com/tdiderich/kazam && kazam build . --out dist --release` ·
**Output directory**: `dist`
- label: GitHub Pages
components:
- type: markdown
body: |
Free, ties cleanly to a repo. Save this as
`.github/workflows/deploy.yml`:
- type: code
language: yaml
code: |
name: Deploy to GitHub Pages
on:
push: { branches: [main] }
workflow_dispatch:
permissions:
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo install --git https://github.com/tdiderich/kazam
- run: kazam build . --out dist --release
- uses: actions/upload-pages-artifact@v3
with: { path: dist }
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
- label: AWS S3 + CloudFront
components:
- type: markdown
body: |
Most boilerplate, most control. One-time setup creates a
bucket, a CloudFront distribution, and an origin access
policy. Then every deploy is just `aws s3 sync`.
- type: code
language: bash
code: |
# One-time setup (replace names):
BUCKET=my-kazam-site
REGION=us-east-1
aws s3api create-bucket --bucket $BUCKET --region $REGION
aws s3 website s3://$BUCKET --index-document index.html
# (Create a CloudFront distribution in the console pointing
# at this bucket, with a default root object of index.html.)
- type: code
language: bash
code: |
# Every deploy:
kazam build . --out dist --release
aws s3 sync dist/ s3://$BUCKET --delete \
--cache-control "public, max-age=300"
# Invalidate the CDN cache:
aws cloudfront create-invalidation \
--distribution-id $CF_ID --paths "/*"
- type: callout
variant: info
title: Tip
body: "Serve `*.html` with a short max-age (300s) and hash-named assets with a long one — but kazam doesn't hash asset filenames, so keep everything short-lived or add a cache-busting query string to `src=` paths in YAML."
- label: Firebase Hosting
components:
- type: code
language: bash
code: |
# One-time:
npm i -g firebase-tools
firebase login
firebase init hosting # choose "existing files", public = dist
- type: code
language: bash
code: |
# Every deploy:
kazam build . --out dist --release
firebase deploy --only hosting
- type: markdown
body: |
Your `firebase.json` should look something like:
- type: code
language: json
code: |
{
"hosting": {
"public": "dist",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
}
}
- label: Self-hosted
components:
- type: markdown
body: |
Any web server that serves static files works. Nginx
example — copy the build and reload:
- type: code
language: bash
code: |
kazam build . --out dist --release
rsync -a --delete dist/ user@host:/var/www/my-site/
ssh user@host "sudo nginx -s reload"
- type: code
language: nginx
code: |
server {
listen 443 ssl http2;
server_name example.com;
root /var/www/my-site;
index index.html;
# kazam emits plain .html files — this lets /guide
# resolve to /guide.html automatically
location / {
try_files $uri $uri.html $uri/ =404;
}
}
- type: section
eyebrow: Gotchas
heading: Things to watch for
components:
- type: card_grid
min_width: 280
cards:
- title: Relative asset paths
description: "kazam rewrites nav hrefs per-page based on directory depth, so `index.html` works from any subfolder. Avoid hand-written absolute URLs like `/foo` unless you know the deploy path will match."
- title: Trailing slashes
description: "Some hosts serve `/guide/` but not `/guide.html` (or vice versa) by default. Test after deploy, or add a rewrite rule if links break."
- title: Cache headers
description: "HTML pages can change on every build. Default to short cache lifetimes (5 min) for `.html` unless you're sure nothing links to a stale version."
- title: Minify for prod
description: "Always pass `--release` on production builds — it strips whitespace from HTML/CSS/inline JS, shrinking pages by ~40%."
- type: callout
variant: success
title: Nothing fancy required
body: "If your host can serve a folder of static files, it can serve a kazam build. If it can't, it's probably not worth the headache — pick one of the recipes above."
- type: callout
variant: info
title: Next up
body: That's the full loop — write YAML, build, deploy. Browse the component reference to see what else you can compose into a page.
links:
- label: Components reference
href: components/index.html
variant: primary
- label: Back to home
href: index.html
variant: secondary