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, 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=86400

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