Docs · Frameworks

Deploy a static site.

Plain HTML, CSS, and JavaScript — no build step, no package.json. If there’s an index.html at the root, Canner serves it. The fastest possible path from folder to URL.

How it works

When a project has an index.html at its root and no package.json, Canner skips the build entirely and serves the files directly, with HTTPS, gzip or Brotli compression, and an SPA-style fallback (unknown paths serve index.html). This works from a drag-and-drop upload, the CLI, or a GitHub repo.

Perfect for AI-generated single pages. A page built by ChatGPT, Claude, or Gemini — one HTML file, maybe a CSS file — deploys in seconds. Zip it, create a project, and upload the archive under Source and it’s live.

From GitHub

A repo that’s just static files deploys the same way — and Canner strips the .git directory from what’s served, so your repo history is never exposed. Pushes to the branch redeploy automatically.

With a build step instead?

If your static site is generated — Astro, Eleventy, Gatsby, Hugo output committed to a repo, or a Vite project — see the Vite and Astro guides; Canner runs the build for you rather than serving the source.

Compression

Text files over 1 KB — HTML, CSS, JavaScript, JSON, SVG, source maps and TTF/OTF fonts — are compressed automatically with Brotli or gzip, whichever the browser asks for. There is nothing to configure. Images and WOFF/WOFF2 fonts are already compressed and are sent as they are. This applies to every site served this way, including the built output of a Vite project.

Custom headers

To set response headers such as Content-Security-Policy, X-Frame-Options or Referrer-Policy, add a file named _headers at the root of the files Canner serves. With Vite, put it in public/_headers and it is copied into dist/. The format is the same as on Netlify and Cloudflare Pages: a path pattern, then its headers indented underneath.

/*
  X-Frame-Options: DENY
  Referrer-Policy: strict-origin-when-cross-origin
  Content-Security-Policy: default-src 'self'; img-src 'self' data:

/assets/*
  Cache-Control: public, max-age=31536000, immutable
  • * matches anything, slashes included; :name matches one path segment.
  • Every matching rule applies, in file order; for the same header, the later one wins. That includes the default Cache-Control, which you can override.
  • Headers are added to every response, including 404s and the SPA fallback.
  • Headers the server manages itself (Content-Length, Content-Encoding, Connection, Transfer-Encoding) and malformed lines are ignored. The file can hold up to 100 rules, and is never served to visitors.
  • This is for static sites. Node, Next.js and other apps set their own headers in code. A site picks up compression and _headers on its next deploy.

Good to know

  • Static sites are light enough that free-plan sleep barely matters — they wake instantly.
  • Custom domains work the same as for any project.
  • Upload caps are per plan and generous — plenty for any static site (see the limits).