Skip to main content
Documentation

Custom domains

Connect a domain you own or buy a new domain for your DeepSpace app.

On this page

By default, every deployed app lives at <name>.app.space - a fully production-grade URL with SSL that most apps ship and stay on. When you want a branded URL, you can attach your own domain - myapp.com, myapp.ai, myapp.io - directly from the CLI. For domains bought through DeepSpace, purchase, DNS, and SSL are handled end-to-end. Domains you already own stay at your registrar and connect through DNS verification.

Connect a domain you already own#

Available in SDK v0.33.0. Use this flow for a domain registered at Cloudflare, Namecheap, or another registrar. No purchase or transfer is involved.

# Prepare ownership verification for this app
npx deepspace@latest app domain attach example.com --external --app my-app --json

# After adding the returned TXT record at your DNS provider
npx deepspace@latest app domain verify example.com --app my-app --json
bash

The first command returns a TXT record tied to your account and the target app. Add it at the domain's DNS provider, then run the returned verification command. DeepSpace creates the certificate after DNS ownership is proven and returns the remaining records: a routing CNAME and any additional Cloudflare ownership TXT. Add these records, then repeat verify until the hostname and certificate are active. Finally, open your domain over HTTPS to confirm that it serves your app.

Starting with v0.33.1, new external-domain certificates use automatic HTTP validation and renewal. No _acme-challenge record is needed for these attachments. Older attachments that return a certificate CNAME still require that record to remain DNS-only for automatic renewal.

The routing CNAME must keep pointing to the SaaS target returned by the command. Root domains require CNAME flattening; Cloudflare DNS supports it. The flow connects exactly the requested hostname. For www, configure a redirect to the root in your DNS provider's hosting controls, or attach and verify that hostname separately.

list and status include verified external domains. Purchase costs and registration renewals remain managed at your existing registrar. To connect the domain to a different app, detach it first and repeat the flow for that app; the DNS proof changes with the target app. Detaching removes DeepSpace routing and its certificate. Remove the DeepSpace DNS records yourself when you stop using the service; registration remains intact.

How purchases work#

DeepSpace registers domains through a hybrid backend:

  • Cloudflare Registrar for ~27 TLDs at cost (.com, .dev, .app, .xyz, and others)
  • Porkbun for .ai, .io, .me, .co, ccTLDs, and other variants

Routing uses Cloudflare Custom Hostnames against the platform's SaaS zone (app.space). After purchase, the platform provisions ownership and DCV records on the new domain's zone, then activates a hostname route.

Billing is via Stripe Checkout - the same payment flow as in-app purchases. Auto-renew is on by default.

Search and buy#

# Find an available domain and its price
npx deepspace app domain search my-startup
npx deepspace app domain search my-startup --limit 20

# Buy via Stripe Checkout (browser opens for payment)
npx deepspace app domain buy my-startup.com
bash

buy opens a Stripe Checkout tab in your browser. After payment, the CLI polls for provisioning:

  • Cloudflare Registrar TLDs (.com, .dev, .app): ~60-90 seconds
  • Porkbun TLDs (.ai, .io, .me): 15-60 minutes (registry-side NS propagation)

You can Ctrl-C out of the polling loop without losing progress - provisioning continues server-side. Re-check with domain status <domain>.

Buy options#

# Print the Checkout URL instead of opening a browser
npx deepspace app domain buy myapp.com --no-open

# Exit immediately after Checkout session is created (no polling)
npx deepspace app domain buy myapp.com --no-wait

# Skip the confirmation prompt (required in non-TTY contexts)
npx deepspace app domain buy myapp.com --yes

# Combine with --app to buy and attach in one command
npx deepspace app domain buy myapp.com --app my-app
bash

For buy, attach, and verify, --app accepts the immutable app id or the current live name; without it, the CLI resolves DEEPSPACE_APP_ID from the surrounding app directory. Names are URL leases, not durable identity, so scripts should prefer the id — see app identity.

With --json, buy returns the Checkout session immediately without polling, and supplies the domain status follow-up action to run once payment completes.

List, inspect, and manage#

# Domains you own
npx deepspace app domain list
npx deepspace app domain list --json

# Detail for one domain (registrar status, hostname status, expiry, errors)
npx deepspace app domain status myapp.com
npx deepspace app domain status myapp.com --json
bash

Domains, billing, and renewal status are also visible in the web dashboard at dashboard.deep.space.

Re-point a domain at a different app#

npx deepspace app domain attach myapp.com --app new-app-name
bash

attach re-points an owned registration to the resolved immutable app id - the CLI resolves whatever you pass to --app (id or live name) to the id and binds that. Use it when:

  • You want to move a domain from a staging app to production
  • You're consolidating multiple domains under one app

Because the binding is to the id, renaming an app does not require re-attaching its domain. The domain follows the app through any rename, along with data, secrets, and collaborators - see app identity.

Detach without releasing#

npx deepspace app domain detach myapp.com --yes
bash

detach removes routing but keeps the registration on file. You keep owning the domain and can re-attach later. There is no domain release - releasing a registration goes through the registrar's own portal.

Auto-renew#

# Disable auto-renew (will expire at end of term)
npx deepspace app domain renew myapp.com --auto off

# Re-enable
npx deepspace app domain renew myapp.com --auto on
bash

Agent-friendly flags#

The CLI is designed for both humans and automation:

FlagAvailable onPurpose
--jsonsearch, buy, list, status, attach, verifyMachine-readable stdout
--yesbuy, detachSkip confirmation prompt (required in non-TTY)
--no-waitbuyExit after Checkout session creation
--no-openbuyPrint URL instead of opening browser
--externalattachConnect a domain bought elsewhere
--limit <n>searchCap the number of results

Pitfalls#

`--app` defaults to your current directory

If you run deepspace app domain buy myapp.com outside an app directory without --app, the CLI errors with No app specified. Pass --app <name>, or run from an app directory with a wrangler.toml.

Premium domains can have different registration and renewal prices

chargedCents in list / status is what you paid this year. The pricing object exposes separate registrationCost / renewalCost. For non-premium TLDs they match; for premium domains, introductory pricing can reset at renewal - read domain status before assuming.

Don't wrap `buy` in `timeout N`

The CLI polls for up to 5 minutes (Cloudflare TLDs) or 60 minutes (Porkbun TLDs). An artificial timeout aborts before payment completes. Use --no-wait for fire-and-forget; otherwise let it run and Ctrl-C if needed (safe; provisioning continues server-side).

Pricing visibility#

The CLI shows the price during search and the Checkout flow. The price starts from the registrar's cost (Cloudflare Registrar or Porkbun) and DeepSpace adds a markup: you pay the registrar cost × 1.3, plus a $1 fee. Renewals charge to your saved Stripe card automatically.

Next steps#