What it is
aft.page hosts small software — one-pagers, prototypes, agent-built HTML, static SPAs — at a shareable HTTPS URL in seconds. The name comes from the aft of a ship: the back of the vessel — take what you built and put it out into the world.
Prefer the MCP tools below. If MCP is unavailable, call the HTTP API directly.
Quick start
Local package lives at apps/mcp
((@aft.page/mcp). Transport: stdio.
Node 20+.
cd apps/mcp
npm install
npm start
MCP host config
Add a server named aft-page. Point
args at the absolute path of
apps/mcp/src/index.ts:
{
"mcpServers": {
"aft-page": {
"command": "npx",
"args": [
"tsx",
"/ABSOLUTE/PATH/TO/aft.page/apps/mcp/src/index.ts"
]
}
}
}
Optional env: AFT_API_BASE (default
https://api.aft.page). Reload the host, then ask:
Deploy this HTML to aft.page
The agent should call deploy_html and return a live
URL.
Tools
deploy_html
Publish a single HTML document (inline CSS/JS fine) to
https://{slug}.aft.page. Use for one-file pages.
| Input | Type | Required | Notes |
|---|---|---|---|
html |
string | yes | Full document; prefer <!DOCTYPE html>…</html> |
preferred_slug |
string | no |
Hint like about-me. Pattern
^[a-z0-9](?:[a-z0-9-]{0,46}[a-z0-9])?$.
Never overwrites — collision gets a suffix
(about-me-mist.
|
Returns text + structured content:
Live: https://{slug}.aft.page
Manage/claim: https://aft.page/preview?url=…
slug: …
deploy: dep_…
files: 1
deploy_files
Publish multiple static files as one site. Use for multi-file
pages or SPA build output. Always include
index.html.
| Input | Type | Required | Notes |
|---|---|---|---|
files |
array | yes | 1–50 items |
files[].path |
string | yes |
Relative path, e.g. index.html,
assets/app.js
|
files[].content |
string | yes | UTF-8, or base64 if encoding set |
files[].encoding |
utf8 | base64 |
no | Default utf8 |
preferred_slug |
string | no | Same rules as deploy_html |
Limits: 50 files · 2 MB each · 5 MB total. Paths: no
.., no leading /, no
\.
aft_health
Ping the deploy API. No inputs. Returns
ok and the API base.
Prompt: deploy_to_aft
Optional prompt that steers the agent:
- Prefer
deploy_htmlfor one document. - Prefer
deploy_filesfor multi-file / SPA. - Pass
preferred_slugwhen sensible. - Return the live HTTPS URL as the deliverable.
- Do not invent account or repository setup steps.
Arg: html_or_files (optional context string).
HTTP API (no MCP)
Base: https://api.aft.page.
CORS: * on deploy + site GET.
GET /health
{ "ok": true }
POST /v1/deploy
Query: optional ?slug=preferred-name. Optional header
X-Aft-Client: mcp|web|extension|curl|cli (metrics).
Three body
shapes:
A) Raw HTML
POST /v1/deploy?slug=hello
Content-Type: text/html; charset=utf-8
<!DOCTYPE html><html><body><h1>Hi</h1></body></html>
B) JSON files (agents)
POST /v1/deploy
Content-Type: application/json
{
"files": [
{ "path": "index.html", "content": "<h1>App</h1>" },
{ "path": "style.css", "content": "body{margin:0}" }
]
}
C) Multipart — fields
file0 + file0_path, …
Success (200)
{
"ok": true,
"slug": "hello",
"deployId": "dep_…",
"url": "https://hello.aft.page",
"files": 1,
"bytes": 42
}
Errors include no_files,
too_many_files, file_too_large,
payload_too_large, bad_path,
reserved_slug, slug_exhausted,
internal. Invalid ?slug= patterns are
ignored (random unique slug); only reserved names return
reserved_slug.
Serving
| URL | Behavior |
|---|---|
https://{slug}.aft.page/ |
Primary — index.html |
https://{slug}.aft.page/{path} |
Static asset |
https://api.aft.page/s/{slug}/ |
Path fallback |
If the requested object is missing, the Worker soft-falls back to
that deploy’s index.html (SPA-style). Content-Type
follows the file extension when the upload type is missing or
application/octet-stream (so CSS is
text/css).
Slugs
- Prefer valid
?slug=/preferred_slugwhen provided. - Else allocate a random unique slug.
-
Clients (paste UI, extension, agents) may derive a hint from
<title>/<h1>and pass it as?slug=— the Worker does not parse HTML for a name. - Never overwrite — append a short word suffix on collision.
-
Reserved:
www,api,app,admin,docs,status, …
Preview shell
https://aft.page/preview?url=https://{slug}.aft.page
Live iframe, indented source, copy link, download HTML, claim /
visibility stubs. Only *.aft.page URLs allowed in
url=. Optional from= (chat URL) enables
“Back to chat”.
Limits (today)
| Limit | Value |
|---|---|
| Files per deploy | 50 |
| Per-file size | 2 MB |
| Total payload | 5 MB |
| Auth | None (anonymous) |
| Overwrite | Never |
| Custom domains / private invite | Later |
Examples
Minimal HTML via curl
curl -sS -X POST "https://api.aft.page/v1/deploy?slug=curl-smoke" \
-H "content-type: text/html; charset=utf-8" \
--data-binary @index.html
Agent rule of thumb
- Prefer MCP
deploy_htmlordeploy_files. - Return the live
https://{slug}.aft.pageURL. - Optionally link the preview shell.
- Do not invent auth steps that do not exist yet.
Troubleshoot
| Symptom | Fix |
|---|---|
| MCP tools missing | Reload host; check absolute path; Node 20+ |
reserved_slug |
Change title / slug |
| Size errors | Stay under 2 MB / file, 5 MB total |
| Unstyled CSS | Ensure path ends in .css; re-deploy |
| Site 404 | Wait for DNS; try /s/{slug}/ on API host |