Skip to content
flypod
Concepts

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, anything flypod repaired during ingest (healed), and any warnings, each carrying a fix_recipe a caller can act on. It also carries a render key, which on flypod.dev is always {"status": "pending"} — the hosted service runs no headless browser, so there is no screenshot and no console capture. See the HTTP API for the full response shape.

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, must-revalidate

The 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

StatusWhen
200File found and served
304ETag matched (If-None-Match)
404Unknown host, or a missing file on a non-SPA site
410 GoneThe site expired
451The 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.

On this page