Documentation

What we support. How to ship it.

aft.page is a file host plus a permission layer for small software. Build locally if needed, upload ready files, get a durable live URL — then claim, share, and manage.

Agents: short index at https://aft.page/docs.md · tool schemas at /mcp.md. Humans: use the guides below (HTML is the detailed source of truth).

Quick start

Agents today: MCP or CLI. Humans: Drop or CLI. Same result: https://{slug}.aft.page.

API (one-shot)

curl -X POST https://api.aft.page/v1/deploy \
  -H 'Content-Type: text/html' \
  -H 'X-Aft-Client: curl' \
  --data '<h1>Hello from aft.page</h1>'

Multi-file: JSON { "files": [{ "path", "content" }] } or multipart. Optional ?slug=vite-hello. A collision gets a numeric suffix — an existing slug is never overwritten by a new, unrelated deploy. Full schemas: /mcp.md.

What we support

aft.page does not run npm run build. You (or your agent) detect the project, build locally if needed, then upload ready files.

Kind Ship Live
Plain HTML One file via Drop / MCP deploy hello.aft.page
Multi-file static HTML + CSS + JS share-checklist
Vite / React / Vue / Svelte / Astro dist/ only vite-hello.aft.page
Next.js static export out/ only
Next SSR / Worker Next.js (SSR) + upstream next-hello.aft.page

Never upload src/, node_modules, or .next/. Always include index.html for static sites. Per-framework build steps, verified vs. untested frameworks, and what still needs a runtime we don't run yet: Frameworks guide.

Logs

Owner and editors: project page → Logs, or GET /v1/sites/{slug}/logs. Request-level hits and errors for the live site, plus recent deploy failures. No IP addresses. Kept 7 days.

{
  "slug": "my-app",
  "views": { "today": 12, "d7": 340 },
  "lastServedAt": "2026-08-12T09:14:02.000Z",
  "events": [
    { "createdAt": "2026-08-12T09:14:02.000Z", "method": "GET",
      "path": "/api/widgets", "status": 500, "bytes": 214, "country": "US" }
  ],
  "deployFailures": [],
  "observability": {
    "window": "12h",
    "totals": { "ok": 40, "fourxx": 2, "fivexx": 1, "bytes": 12000, "requests": 43 },
    "buckets": [],
    "countries": [{ "country": "US", "n": 30 }, { "country": "IN", "n": 13 }]
  }
}

events is capped at the most recent 100 rows; only document-shaped hits and non-2xx responses stick around — noisy favicon/robots-style paths are filtered before they're stored.

Source

Owner, editors, and viewers: project page → Source, or GET /v1/sites/{slug}/files. File list for the current deploy (or an older one via ?deployId=); click a text file to preview its contents. This is a private read of what you uploaded — it's not a public URL, and the live site is unchanged by looking at it.

{
  "slug": "my-app",
  "deployId": "dep_abc123def456",
  "files": [
    { "path": "index.html", "bytes": 1820 },
    { "path": "assets/app.js", "bytes": 44210 }
  ]
}

Limits

Static worker / next
Files 500 500
Per file 25 MB 25 MB
Total 100 MB 100 MB

Claim within 60 minutes or drop again. Claim guide.

Examples

Source: examples/ in the aft.page repo.