On this page5
  1. Port (`PORT`)
  2. Scratch disk (`/tmp` and `/data`)
  3. Verify before buyer review
  4. Other requirements
  5. Layout
Developers

Web delivery format

Web app delivery requirements: bind PORT (8080), implement GET /healthz, and ship something the live review can open.

Use Web when the delivery is an HTTP app on https://{slug}.velcio.app, or when it needs inbound webhooks or any public HTTP endpoint.

Workers (no public URL): Delivery format. Worker vs Web: Choosing Worker or Web.

Web means your app binds $PORT and implements GET /healthz. It is not WordPress or classic PHP CMS hosting (not supported).

Port (PORT)

Velcio sets PORT=8080 and sends public HTTPS to that port.

Your process must:

  1. Listen on 0.0.0.0
  2. Bind env PORT (do not hardcode 8000, 3000 or similar)
  3. Implement GET /healthz on that port and return HTTP 2xx when ready

Velcio does not add /healthz for you. A 404 there means you need the route in your code, then redeploy. Velcio also checks GET /healthz → HTTP 2xx on the public preview URL before you can Send to buyer for review.

Do not ship secrets in .env* files. At build time Velcio writes a .dockerignore that excludes .env* (including .env.example). Use Production secrets instead.

Wrong port → public 502 Bad Gateway even when the container looks healthy.

Scratch disk (/tmp and /data)

Read-only root filesystem. Writable space:

PathEnvDefault capUse for
/tmpOS default / TMPDIR64 MB tmpfs, noexecOS temp, Python tempfile, short-lived files
/dataVELCIO_DATA_DIR (/data)~25% of plan RAM (capped 256 MB), noexecScratch / caches during a run

Both are ephemeral: they survive process restarts in the same container, wiped on redeploy. Do not store durable uploads or databases on local disk. VELCIO_DATA_DIR is platform-owned and cannot be overridden via secrets.

Python (Uvicorn):

import os
import uvicorn

port = int(os.environ["PORT"])  # Velcio sets PORT=8080
uvicorn.run("main:app", host="0.0.0.0", port=port)

Node.js:

const port = Number(process.env.PORT || 8080);
app.listen(port, "0.0.0.0");

Verify before buyer review

When deploy is running, open the public URL on the project page and confirm the app works. GET /healthz must return HTTP 2xx on that preview URL. Velcio enforces that check when you Send to buyer for review. If the check fails, fix the route or app startup, redeploy if needed, then confirm again.

Revision preview confirms are not health-probed yet (no public preview URL for revisions).

After accept, the buyer can rename the subdomain and optionally attach one hostname they already own via CNAME (domain purchased elsewhere). Old platform URLs keep working as aliases for webhooks.

Other requirements

  • Build with Auto (buildpacks) or Dockerfile
  • Declare required env var names in Velcio. Never bake secret values into the ZIP.

Layout

Same ZIP / GitHub rules as Delivery format, plus the HTTP contract above.

Web delivery format | Velcio Docs