Custom Domains
Enable your customers to use their own domain names with automatic SSL provisioning via DigitalOcean App Platform.
Overview
Custom domains allow your customers to use their own domain names (e.g., events.example.com) instead of the default subdomain.yourdomain.com URL.
Two modes are available:
| Mode | How It Works | Best For |
|---|---|---|
| Redirect | Customer sets up Cloudflare to 301 redirect their domain to the schedule URL | Simple setup, no server configuration needed |
| Direct | Schedule is served directly on the customer's domain with automatic SSL | Seamless experience, domain stays in the address bar |
Prerequisites
Direct mode requires:
- DigitalOcean App Platform - Your app must be deployed on DigitalOcean App Platform, which handles SSL provisioning for custom domains.
- DO API Token - A DigitalOcean personal access token with read/write access to Apps.
- App ID - Your DigitalOcean App Platform app ID.
Redirect mode does not require any server-side configuration. Customers set up their own Cloudflare redirect rules.
Environment Setup
Add the following variables to your .env file:
DO_API_TOKEN=your_digitalocean_api_token
DO_APP_ID=your_app_id
DO_APP_HOSTNAME=your-app.ondigitalocean.app
DO_API_TOKEN
Your DigitalOcean personal access token. Generate one at cloud.digitalocean.com/account/api/tokens. Select Custom Scopes, then expand the app resource and check read and update.
DO_APP_ID
Your App Platform app ID. Find it in the DigitalOcean dashboard URL: cloud.digitalocean.com/apps/YOUR_APP_ID.
DO_APP_HOSTNAME
The starter domain of your DigitalOcean app. Find it under Settings > Domains, it ends in .ondigitalocean.app. Customers will create CNAME records pointing to this value.
How It Works
Redirect Mode
In redirect mode, the customer sets up a Cloudflare page rule that 301 redirects their domain to their subdomain.yourdomain.com URL. No server-side changes are needed.
Direct Mode
When a customer saves their domain in Direct mode:
- The domain is registered with DigitalOcean App Platform via API
- The customer adds a CNAME record pointing to your app's hostname
- DigitalOcean automatically provisions an SSL certificate
- Incoming requests on the custom domain are routed to the correct schedule via middleware
- All URLs in the HTML output are rewritten to use the custom domain
The ResolveCustomDomain middleware rewrites the HTTP Host header so that existing subdomain-based routes match without any route changes. After the response is generated, subdomain URLs are replaced with the custom domain in the HTML output.
DNS Setup for Customers
When a customer selects Direct mode, they need to create a CNAME record at their domain registrar:
| Record Type | Name | Value |
|---|---|---|
| CNAME | @ or subdomain (e.g., events) |
Your DO_APP_HOSTNAME value |
DNS propagation can take up to 48 hours. SSL provisioning happens automatically once DigitalOcean verifies the CNAME record. The domain status in the admin panel will change from "pending" to "active" once complete.
Admin Management
The /admin/domains page provides a dashboard for monitoring and managing all custom domains:
- Summary cards - Total custom domains, direct mode count, active count, and pending count.
- Domain table - Lists all schedules with custom domains, showing mode, status, and live DigitalOcean status.
- Re-provision - Removes and re-adds a domain to DigitalOcean, useful if SSL provisioning gets stuck.
- Remove - Removes the domain configuration from DigitalOcean and clears the mode/status fields.
Troubleshooting
Domain stuck on "pending"
Verify the CNAME record is correctly configured. DNS propagation can take up to 48 hours. If it persists beyond that, try re-provisioning from the admin panel.
SSL certificate not provisioning
DigitalOcean requires the CNAME to be resolvable before issuing an SSL certificate. Ensure there are no conflicting A records for the domain. If using Cloudflare DNS, disable the proxy (orange cloud) for the CNAME record.
Domain shows "failed" status
Check the DigitalOcean dashboard for specific error details. Common causes: invalid CNAME, domain already registered with another app, or API token permissions. Try re-provisioning after fixing the issue.
404 error on custom domain
The domain must have custom_domain_status set to "active" for the middleware to serve content. Check the admin panel to verify the domain status. The middleware caches domain lookups for 10 minutes.