Your app is deployed and it works, but it lives at an address like your-project.pages.dev. Putting it on a custom domain, with HTTPS, is the step that makes it look like a real product. It is not difficult, but it involves three systems that are easy to confuse: the registrar where you rent the name, the DNS records that point the name somewhere, and the certificate that makes HTTPS work. This guide explains each one, walks through the order of operations, and covers the mistakes that cause most failed setups.
What a custom domain actually is
A domain name is read from right to left. In app.example.com, "com" is the top-level domain, "example" is the label you registered (MDN calls the label before the top-level domain the secondary level domain), and "app" is a subdomain. Once you control example.com, you can create as many subdomains as you like, each pointing at different content.
One detail surprises people: you never own a domain. MDN puts it plainly: "You cannot 'buy a domain name'." You pay a registrar for the right to use the name for one or more years, and you can renew that right before anyone else. Put the renewal date in your calendar and turn on auto-renew. An expired domain takes your app offline just as surely as a broken deploy.
How DNS connects the name to your host
When someone types your domain, their browser needs an IP address. It checks its local cache first, and if the answer is not there, it asks a DNS server. DNS records are the instructions you publish so that answer is correct. For a web app you will mostly meet these types, described here in Cloudflare's words:
| Record | What it does |
|---|---|
| A and AAAA | "map a domain name to one or multiple IPv4 or IPv6 address(es)" |
| CNAME | "map a domain name to another (canonical) domain name" |
| TXT | "lets you enter text into the DNS system", used for verification |
| CAA | "specifies which Certificate Authorities (CAs) are allowed to issue certificates for a domain" |
| MX | required to deliver email to a mail server |
Changes are not instant everywhere. MDN explains that each DNS server that knows about a domain stores the information for some time before refreshing it, so "it takes some time for DNS servers that know about this domain name to get the up-to-date information." If a change looks right in your DNS dashboard but your browser still shows the old site, wait before you start changing things again. Repeated edits during this window are how simple setups become confusing ones.
Apex domain or subdomain
You have two choices for where the app lives:
- The apex, example.com itself.
- A subdomain, such as app.example.com or www.example.com.
The difference matters because hosts connect them differently, so read your host's custom domain page before you touch DNS. On Cloudflare Pages, for example, a subdomain can point at your project with a CNAME while the domain stays wherever its DNS is today, but an apex domain must be a Cloudflare zone, meaning you move the domain's nameservers to Cloudflare and Cloudflare creates the record for you.
Connecting the domain: the order that works
The exact screens differ by host, but the order is the same everywhere. Using Cloudflare Pages as the worked example:
- Add the domain in your host first. In the Cloudflare dashboard, go to Workers and Pages, open your project, choose Custom domains, then Set up a domain, and enter the name.
- Then create or confirm the DNS record. For a subdomain whose DNS is elsewhere, create a CNAME pointing it at your-project.pages.dev. If the zone is already on Cloudflare, the record is added for you once you confirm.
- Wait for the domain to become active, including its certificate, before announcing the new address.
The order is not a formality. Cloudflare's documentation warns that adding a CNAME to your Pages site without first associating the domain in the Pages dashboard can stop the domain resolving, and visitors see a 522 error. Always associate the domain with the project first, then point DNS at it.
Two more points from the same documentation are worth knowing. If you later change the DNS record to point elsewhere, the custom domain becomes inactive, and pointing it back causes errors until it reactivates. And if you want the old pages.dev address to send visitors to your new domain, Cloudflare suggests account-level Bulk Redirects for that.
The full deployment walk-through is in the step-by-step Cloudflare Pages deployment tutorial. If you have not picked a host yet, where to deploy and why compares the options.
How HTTPS certificates get issued
HTTPS needs a certificate from a certificate authority that browsers trust. Even if your host requests it for you, it helps to know what is happening behind that progress spinner. Let's Encrypt is a useful example because its documentation explains the process openly.
Let's Encrypt uses a protocol called ACME, which aims to "make it possible to set up an HTTPS server and have it automatically obtain browser-trusted certificates" without manual steps. Before issuing, the certificate authority has to confirm you control the domain. It does that with a challenge, and the two you will meet are:
- HTTP-01: your ACME client places a token file under a well-known path on your domain, and Let's Encrypt fetches it over port 80. Easy to automate and works with hosts you point at with a CNAME, but it "cannot be used to issue wildcard certificates."
- DNS-01: your client creates a TXT record under a special acme-challenge name (prefixed with an underscore) on your domain. It supports wildcard certificates, but whatever creates the record needs access to your DNS provider's API.
Let's Encrypt's FAQ covers the practical facts. It does not charge for certificates, though some hosting providers may add a fee. Certificates are valid for 90 days by default, and the FAQ recommends renewing at about the 60-day mark, so renewal has to be automated. Short-lived six-day certificates are available as an opt-in. It issues Domain Validation certificates only, and wildcard certificates must use DNS-01.
When certificate issuance fails
One blocker that is easy to miss, especially on a domain that has been used before, is a CAA record. CAA records list which authorities may issue certificates for the domain, and if yours does not allow the authority your host uses, issuance fails. Cloudflare's Pages documentation calls this out directly and lists the authorities to permit. If your domain status is stuck on the certificate step, check for CAA records before anything else.
Make every visitor use HTTPS
Having a certificate is not the same as every request using it. Three settings close the gap.
Redirect HTTP to HTTPS. Most hosts offer a switch for this. Cloudflare's Always Use HTTPS "redirects all your visitor requests from http to https", and Cloudflare recommends not also performing redirects at your origin server, since that can cause redirect loop errors. Pick one place to redirect.
Encrypt the whole path, not just the first half. If a proxy sits in front of your origin, check how it connects to that origin. In Cloudflare's Flexible mode, traffic from visitors to Cloudflare can be encrypted, "but traffic from Cloudflare to the origin server is not." Cloudflare strongly recommends Full or Full (strict) where possible. If you deploy to Pages directly, Cloudflare is your host, so this setting is mostly relevant when you proxy a separate server.
Fix mixed content. A page served over HTTPS that loads scripts, styles or images over plain HTTP has mixed content. MDN explains that browsers automatically upgrade some requests, such as images, audio and video, and block others, including scripts, stylesheets, iframes, fetch requests and web fonts. A redirect does not fix this; Cloudflare notes that forcing HTTPS does not resolve mixed content. The fix MDN recommends is to serve everything over HTTPS and make references relative or HTTPS. Search your code and content for hard-coded http links after you switch.
HSTS: a decision, not a default
The Strict-Transport-Security header tells browsers that a host should only be reached over HTTPS, and that future HTTP attempts should be upgraded automatically. MDN also notes that browsers will then not let users click through certificate errors on that host.
That is good protection, and it is also a commitment. The max-age value tells the browser how long, in seconds, to remember the rule, and MDN explains you cannot switch HSTS off over plain HTTP. Adding includeSubDomains extends the rule to every subdomain, which can break any subdomain that does not have HTTPS yet. Preloading requires a max-age of at least one year plus includeSubDomains. Start with HTTPS working everywhere and a short max-age, and lengthen it once you are confident.
A checklist before you share the link
- The domain is added in your host, and DNS points at it.
- The certificate is issued and the padlock shows on both the apex and www, or whichever addresses you use.
- Plain HTTP redirects to HTTPS, in exactly one place.
- No mixed-content warnings in the browser console.
- The old platform address redirects to the new domain.
- Your app's canonical URL, sitemap and any auth callback URLs use the new domain.
- Domain auto-renew is on.
The last two items are where launches quietly break; they belong on the pre-launch checklist along with the rest.
Sources
- What is a domain name? (MDN)
- DNS record types (Cloudflare docs)
- Custom domains, Cloudflare Pages (Cloudflare docs)
- How It Works (Let's Encrypt)
- Challenge Types (Let's Encrypt)
- FAQ (Let's Encrypt)
- Encryption modes (Cloudflare docs)
- Always Use HTTPS (Cloudflare docs)
- Mixed content (MDN)
- Strict-Transport-Security (MDN)



