How it works
flypod has two planes. A deploy pipeline ingests a zip into an immutable version, and a serve plane routes a subdomain to that version's files.
flypod is two planes. The deploy pipeline turns an uploaded zip into an immutable version and points a site at it. The serve plane maps an incoming request's subdomain to that site and returns its files. Everything else (versioning, TTL, ownership) hangs off these two.
The deploy pipeline
A deploy is a single POST /sites with a zip body. flypod processes it in
order:
Ingest the zip. Files are unpacked under size and count caps, with a path-traversal guard so no entry can escape the site root.
Render Markdown (if needed). If the upload has no index.html but does
contain Markdown files, flypod renders them into a small styled site.
Ensure an index.html exists. Every site must resolve / to something, so
flypod guarantees an index page is present.
Abuse scan. Contents are checked against abuse rules before anything goes live.
Detect SPA. flypod inspects the site to decide whether it's a single-page app. This flag drives the serve-plane fallback (below).
Store an immutable version. The processed content is hashed and stored as a version that never changes.
Create or point the site. A new site is created (or an existing one's live pointer is moved) to serve that version.
The response carries the live URL, the credentials (tokens), the expiry, any warnings, and a render summary.
The serve plane
Each site lives at https://<site_id>.flypod.dev. The subdomain selects the
site. That's the entire routing model. A request to / serves the site's
/index.html.
Responses are cacheable and revalidate cheaply:
ETag: "<live_version_id>:<path>"
cache-control: public, max-age=60, stale-while-revalidate=86400The ETag is the live version id plus the path, so a request that matches gets a
304 Not Modified. Because the version id changes on every deploy, a new
version automatically invalidates old cache entries.
SPA fallback
If a request path has no file extension and no file matches, flypod falls
back to serving index.html, but only if the live version was detected as a
single-page app. This lets client-side routers handle /about without a
real about.html. Static sites get a normal 404 for the same request.
Status codes
| Status | When |
|---|---|
200 | File found and served |
304 | ETag matched (If-None-Match) |
404 | Unknown host, or a missing file on a non-SPA site |
410 Gone | The site expired |
451 | The site was disabled by an operator |
SEO and indexing
flypod injects invisible attribution into served HTML: meta tags and JSON-LD,
no visible badge. Anonymous sites are additionally served with
x-robots-tag: noindex, keeping ephemeral deploys out of search engines.
HTTP API
The flypod REST API at https://flypod.dev deploys sites from a zip, redeploys new versions, rolls back, and manages accounts with bearer-token auth.
Versioning
Every deploy is an immutable version identified by a hash of its content; a single live pointer selects which version a site serves, moved by update and rollback.