kad.dev alpha
kad.dev · docs

Deploy from a Git URL

Updated Oct 8, 2026

Paste the URL on the home page, pick a branch or tag, deploy. Framework, port and build commands are detected and stay editable. Each deployed commit gets its own URL, private until you expose it.

What each preset runs

A framework named in the manifest wins over its build tool, which wins over the bare runtime. Install and Build are editable in Settings → Build; the start command is not.

Preset Install · Build Runs Port
static none nginx on the repo root or Output dir 8080
vite, vue npm install · npm run build nginx on dist 8080
astro, svelte, angular same nginx on dist 4321, 5000, 4200
react same nginx on build 3000
node same your server, npm run start 8080
nextjs, nuxt, remix, sveltekit same your server 3000
go go mod download -x · go build -v -o /out/app . the binary alone 8080
fastapi pip install -r requirements.txt uvicorn main:app 8000

flask (port 5000) and django (8000) share the Python builder.

The traps

illustration
Three repos become three images: nginx keeps only the output folder, Go only the binary at /app, Python the whole tree under /app
  • Go ships the binary alone: embed templates and static files with //go:embed. The Build command must write /out/app, the only path copied. CGO_ENABLED=1 in the environment switches to Debian-based images.
  • Python installs requirements.txt and nothing else, so it must list uvicorn or gunicorn. A pyproject.toml-only repo is detected, then fails at install: set Install to pip install -e .. Entry points are fixed: main:app, app:app, config.wsgi:application.
  • Static output must hold an index.html, or the build fails and names the folder. nginx answers index.html for every path without a file, so there is no custom 404 page. A VITE_ variable is baked in at build time: keep its Include in build switch on (the default), rebuild after changing it; it is public.
  • No server, no backends. The nginx presets cannot use Postgres or the bucket. A Vite repo whose start script runs your own server is detected as node instead.

Port and health check

Port is injected as PORT and wins over your own; listen on it, on all interfaces. Health check takes a path such as /healthz, empty means a TCP probe; a failing path blocks readiness and restarts the container.

Versions and monorepos

  • Node: the Node picker (18 to 24), then .nvmrc, .node-version, engines.node (first major of a range), then 22.
  • Python: runtime_version via update_settings (3.10 to 3.13; no dashboard picker), .python-version, runtime.txt, then 3.12.
  • Go: the go line of go.mod, else 1.24.
  • Monorepo: Root directory in Settings → Build.

Without an account

A public repo deploys without logging in, as a temporary project: 72 hours, then it stops and is removed, data included. Your first action (branch lookup, deploy, nickname) creates a guest with one temporary project; reading stores nothing. Log in with GitHub or Google to keep it: a live project turns permanent when the slot is free, otherwise press Make permanent under Project lifetime. A private repository needs Authorize private repos, a GitHub App, so an account.

Limits

  • One container per app: one port, one replica, 1 CPU, 1 GiB of memory. No workers, no cron.
  • No deploy on push, no webhook: a build starts from the dashboard or from an agent.
  • 20 builds per day per account, whoever starts them.
  • A free account holds one permanent project and one temporary one; guest sign-ups are rate-limited per network.
  • Public alpha, no SLA: keep your own backups.
BUILT SLOWLY · SOLO · EU-HOSTED | BUILD 2a0ff80