Skip to content

Publishing & Custom Domains

One-click publish — building, deploying, and going live on the web in seconds

You can ship a Doable project to the public web with one click.

Publish

In the editor toolbar, click Publish.

What happens:

  1. The API runs the project's production build (vite build).
  2. The output is copied to SITES_DIR/<project-slug>/.
  3. The reverse proxy (Caddy or nginx) starts serving the site at <slug>.<DOABLE_DOMAIN>.
  4. The project's row gets a published_at timestamp.

You'll see a green Live badge with the URL — click to open in a new tab.

Re-publish

Each click of Publish rebuilds and redeploys. Old versions aren't kept by default; for that, see Version History.

Unpublish

Project → Settings → Publishing → Unpublish. The site stops being served (returns 404) and published_at is cleared.

The default URL

Your project lives at:

https://<project-slug>.<DOABLE_DOMAIN>

DOABLE_DOMAIN is set by the operator (typically doable.me or a self-hosted equivalent). The slug is derived from the project name and editable in Project → Settings → URL slug.

Custom domains

Want myapp.com instead?

  1. Project → Settings → Domain → Add custom domain.
  2. Enter your domain.
  3. Doable shows the DNS record you need to set on your DNS provider:
  4. For most setups: a CNAME pointing to <DOABLE_DOMAIN>.
  5. For Cloudflare-Tunnel-based deployments: a CNAME to <CLOUDFLARE_TUNNEL_ID>.cfargotunnel.com (orange cloud).
  6. Add the record at your registrar / Cloudflare.
  7. Click Verify. Doable checks DNS, issues an SSL cert (Let's Encrypt or via Cloudflare), and starts serving the site at the custom domain.

The status will move through pending_dnspending_verificationactive. If it gets stuck:

  • Wait — DNS propagation can take up to 48h.
  • Click Re-verify.
  • Check Project → Settings → Domain → Diagnostics for the exact error.

Multiple domains

A project can have multiple custom domains (e.g. myapp.com and www.myapp.com). Add them one at a time.

The free plan limit on custom domains is set by the operator (packages/shared/src/constants.ts).

Apex domains

Most DNS providers don't allow CNAME at the apex (example.com vs www.example.com). Use one of:

  • ALIAS / ANAME / CNAME-flattening records (Cloudflare, DNSimple, Route 53 Alias).
  • An A record to your server's static IP.

SSL

You don't manage certs yourself. Caddy (or nginx + certbot) does it on demand. Renewals happen automatically.

Sites' env vars

Your project can have published-time env vars under Project → Settings → Environment variables. These are baked into the static build (VITE_* prefixed for Vite to expose them to the client).

For server-side env vars (API routes), Doable's published projects are static-only today — you'd need to deploy a separate backend.

Security & isolation

Each published project is served from its own subdirectory in SITES_DIR. The reverse proxy enforces the URL → directory mapping; users can't traverse out of their site root.

The build runs inside the same dovault jail as the dev server — a malicious or buggy build script can't affect other users' files.

See also