16Docs

Domains

Give your hosted app a shareable URL: a vanity <slug>.bounded.page (free), or your own custom domain (Pro). Your appId stays in project config and CLI flags; it is not the URL you publish to users.

Publish the built web client

Build the client-rendered UI, then publish its output directory on the same Bounded app as the policy and runtime:

npm run build
bounded site deploy ./dist --app-id <id>
bounded domains slug myapp --app-id <id>

Vanity subdomain (free)

Claim one canonical vanity subdomain for your app. This is the default public Bounded URL to share before you add a custom domain.

bounded domains slug myapp --app-id <id>      # → https://myapp.bounded.page
bounded domains slug --release --app-id <id>  # free it
RuleBehavior
Globally uniqueA slug is a subdomain. Taken names are rejected with a suggested alternative.
One per appChanging the slug frees the old one; your appId remains the stable internal project id.
Reserved names blockedwww, api, auth, admin, … and appId-shaped names are rejected.
Auth just worksThe slug is added to your app’s allowedOrigins automatically (CORS + login).
API too<slug>-api.bounded.page is the Bounded-managed API hostname for that app.

Custom domain (Pro)

Bring a domain you own. Bounded issues the SSL cert (Cloudflare for SaaS); you add a couple of DNS records and it validates automatically.

bounded domains add app.yourdomain.com --app-id <id>   # prints DNS records to add
bounded domains list --app-id <id>                     # pending → active
bounded domains remove app.yourdomain.com --app-id <id>

Flow: add returns the DNS records (a CNAME + ownership / SSL TXT records) to paste at your registrar. Once DNS propagates the cert validates, list flips the domain to active, and https://app.yourdomain.com serves your app (added to allowedOrigins). remove tears it all down.

How it routes

All app assets are keyed by appId internally. At the edge, a request's host is resolved to an appId: a vanity slug and a custom domain both resolve to your app and serve the same deployed assets. Each host maps to exactly one app; an unmapped host returns 404 (fail-closed). A domain can never serve the wrong app.