Hanzo AI

Vercel

Vercel builds a repo and serves the result. Here that is two capabilities — /v1/platform (37) builds and runs an app, /v1/projects (27) serves a static export — and which one you want depends on whether your output needs a server.

Vercel takes a repository, builds it, and serves the output. Two capabilities answer that, and picking the right one is the whole migration:

  • /v1/platform (37 operations) — an app that is built and run. It has the build (POST /v1/platform/runner, listed at /v1/platform/builds), a deploy, per-deployment logs, preview, promote, rollback, env and domains. This is the like-for-like Vercel replacement.
  • /v1/projects (27 operations) — a static site. You bring a built directory; it stores it as a content-addressed release and points a domain at one. No build, because there is nothing to build.

If your project is next build with route handlers, ISR or middleware, it is an app: use /v1/platform. If it is output: 'export' — a directory of HTML — the Sites plane is simpler and cheaper. This documentation site is the first; the marketing site is the second.

Start here

Register the app against your repo, then deploy it — two calls, no dashboard.

# 1. mint a key — sk- belongs on a server, pk- is safe in a browser
curl -sS -X POST https://api.hanzo.ai/v1/account/keys \
  -H "Authorization: Bearer $HANZO_SESSION" \
  -H 'Content-Type: application/json' \
  -d '{"type":"secret"}'

# 2. register the app against a git repo — it lands in draft, nothing built yet
curl -sS -X POST https://api.hanzo.ai/v1/platform/projects/default/apps \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"name":"web","source":"git","repo":{"url":"https://github.com/acme/web","branch":"main"},"port":3000}'

# 3. build it and run it
curl -sS -X POST https://api.hanzo.ai/v1/platform/projects/default/apps/web/deploy \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"commit":"main"}'

Step 2 answers 201 with the app in draft and its canonical HTTPS host already attached; the default project needs no creating, because every org has one. Step 3 answers 202 — an accepted deployment, not a live one — and comes back building while BuildKit runs, which is why the logs call below exists.

Core capabilities

CapabilityWhat it doesOperations
/v1/platformBuilds a repo and runs it: deploy, per-deployment logs, preview, promote, rollback, env, domains37
/v1/projectsServes a directory you already built, as content-addressed releases with domains and purge27
/v1/functionsPublishes one handler with no app around it, and invokes it11

Nouns

Vercel is not only deploys, and neither is this. The left column is their product surface; the right is the capability that answers it.

Building and serving

VercelHanzo
TeamYour org, taken from the validated key
ProjectProject — IAM owns it; apps and sites live under it
Deployment (built for you)POST /v1/platform/projects/{project}/apps/{app}/deploy
Build logsGET .../apps/{app}/deployments/{id}/logs
Preview deploymentPOST .../apps/{app}/preview
Promote to productionPOST .../apps/{app}/promote
Instant rollbackPOST .../apps/{app}/rollback
Environment variablesPUT .../apps/{app}/env
Domain, and verifying it.../apps/{app}/domains, then /{host}/verify
Purely static output/v1/projects (27) — upload a directory, activate a release
Rollback, staticPOST /v1/projects/{slug}/releases/{release}/activate
Edge cache purgePOST /v1/projects/{slug}/purge

The rest of the platform

VercelHanzo
Serverless / Edge Functions/v1/functions (11)
Cron Jobs/v1/tasks (5) — a durable engine, not a timer on a deployment
Vercel KV/v1/kv (6)
Vercel Blob/v1/s3 (6)
Vercel Postgres / storage you provision/v1/provisioning (28)
Edge Config/v1/flags (8) — a definition and a deterministic decision
Web Analytics/v1/event (12)
Speed Insights, Log Drains, traces/v1/o11y (381)
Firewall, rate limiting, allowed origins/v1/gateway (3)
Domains bought and held/v1/domain (7)
AI SDK / AI Gateway/v1/ai (272) — the models, not a proxy to somebody else's

The counts are the operations each capability publishes in the document this site is built from. /v1/ai being the largest is the point of the whole platform rather than an add-on to hosting.

The call

Vercel:

vercel deploy --prod

Hanzo, as an app that builds — the shape that matches:

curl -sS -X POST \
  "https://api.hanzo.ai/v1/platform/projects/acme/apps/web/deploy" \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"commit":"main"}'

Then watch it, and promote when you are happy:

curl -sS "https://api.hanzo.ai/v1/platform/projects/acme/apps/web/deployments/$ID/logs" \
  -H "Authorization: Bearer $HANZO_API_KEY"

curl -sS -X POST \
  "https://api.hanzo.ai/v1/platform/projects/acme/apps/web/promote" \
  -H "Authorization: Bearer $HANZO_API_KEY"

Static instead, when the output needs no server — enqueue, upload, complete:

curl -sS -X POST https://api.hanzo.ai/v1/projects/my-site/deployments \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"commit":"'"$GIT_SHA"'"}'

The bytes go straight to object storage with the grant that call hands back, so CI never holds a standing storage credential and the edge body limit never applies to your largest asset. A release is addressed by the digest of its own manifest, so rolling back is activating an earlier one — the bytes never move.

What does not carry

Short, because most of Vercel's surface has an answer above. What genuinely differs:

Git-push-to-deploy is opt-in, not ambient. Vercel watches every branch of a connected repo and deploys what it finds. A push here reaches cloud.OnGitPush and an app rebuilds when it tracks that repo — you say which repo an app tracks, rather than the connection implying it for all of them.

No *.vercel.app hostname per commit. preview gives you a running deployment; a memorable per-commit subdomain minted automatically is not part of it. Point a domain at what you want to share.

Framework detection is Pack's job, and it is the default. Hanzo Pack is a zero-config builder: it analyses the repository, picks the provider and writes the image, for Node, Python, Go, PHP and more, with BuildKit layer and mount caching underneath. So this is not the difference it looks like — what you give up is Vercel's opinion about their framework list specifically, not detection itself.

No image optimization in the request path. Vercel rewrites and caches images per request from next/image. Nothing here transforms an image as it is served, so pre-size them at build.

Cron is a durable engine, not a field on a deployment. vercel.json's crons ships with the deployment and disappears with it. /v1/tasks outlives any one deploy, which is what you want and is a different thing to port.

On the static plane specifically: /v1/projects does not build and has no per-request compute, and its completion manifest is a single body subject to the edge limit — a full prerender of very many pages is what makes that bite. Those are properties of choosing the static plane over /v1/platform, not of the platform.

How is this guide?