# Connect a custom domain

Source: https://modulify.ai/docs/publish/custom-domains

Point a domain you own at your published site, and understand why a domain sits on Pending instead of failing.

A custom domain puts your site on an address you own. Your free `.modulify.website` address keeps working alongside it, so nothing breaks while you set this up.

## Before you begin

You need three things: a domain you already own, the ability to add DNS records for it, and a paid plan. On a free workspace the **Custom Domain** field is disabled and the row carries a **Paid** badge. See [Plans](/docs/plans/plans).

Adding or removing a domain needs the **Manage domains** permission, which the workspace owner always has and which a custom role can be given. Without it the **Connect** button is disabled with the tooltip `You do not have permission to do this.` See [Members and roles](/docs/reference/members-and-roles).

You can connect a domain before your first publish, but nothing answers on it until the site is published. The field says as much: `Connect a custom branded domain. Takes effect immediately if an initial publish exists.`

## Open the Domain panel

Open the project, click **More** in the tab strip, then **Domain**. The address is `/dashboard/projects/<project>/domain`, and the panel is headed **Domain**, `Connect a custom domain to your published site.`

The panel holds three things stacked: your free subdomain, the custom domain section, and your project's details. Only the middle one matters here. The free subdomain is covered in [Your free web address](/docs/publish/your-web-address).

## Enter the domain

Type the hostname into the **Custom Domain** field. The placeholder shows the two shapes it accepts, `modulify.ai or blog.modulify.ai`. Press Enter or click **Connect**.

Enter the bare hostname. The field validates as you type and refuses four things.

| Message | Cause |
| --- | --- |
| Domain should not include http:// or https://! | You pasted a full URL |
| Domain should not include a path! | The value contains a `/` |
| Domain must be between 4 and 253 characters! | Too short or too long to be a hostname |
| Domain must be a valid domain! | Not a well formed hostname |

A leading `www.` is not an error. Modulify strips it and connects the root instead, then attaches the www hostname as the companion, so `www.example.com` and `example.com` reach the same place. See [www and apex domains](/docs/publish/www-and-apex).

## What happens on Connect

Modulify sets up the site's production server if it does not exist yet, requests a TLS certificate for your domain, requests a second one for the www companion, and reads back the DNS records both of them need.

You get a **Domain added** toast naming what is now waiting, for example `example.com and www.example.com are both waiting on DNS. Add the required records at your DNS host to finish connecting them.` The section then becomes **Your custom domain** with a **Pending** badge and a table of records underneath.

If the domain is already taken by this site or another one, Connect returns instead of proceeding. `Site already has a custom domain!` means you must remove the current domain first. `You cannot use a Modulify domain as a custom domain!` means the value you entered is on an address Modulify already owns.

## The records Modulify shows you

The table has four columns, **Name**, **Type**, **Value** and **Status**, and one row per record required for that hostname. Click a name or a value to copy it.

Above the table, a line names the zone the records belong in: `Add the following records at the DNS host that manages example.com (not any other domain).` That is whoever runs the nameservers for the domain today, which is often not the company you bought it from.

Names are shown relative to your domain, so your apex reads `@` rather than the full hostname. Below the table sits the reminder `DNS changes can take a few minutes to propagate.`

[DNS records](/docs/publish/dns-records) explains what each record is for, the Cloudflare proxy warning, and the one click setup button that some DNS providers support.

## All the records, or it stays Pending

This is the part worth reading twice. Modulify marks a hostname **Connected** only when **every** record in its table resolves to the expected value **and** the certificate for it has been issued. One record short and the hostname stays **Pending** forever. Nothing errors, nothing warns, and there is no partial success.

That has a consequence people trip over. Once the address records point at your site, the certificate can be issued and the site starts answering over HTTPS while the remaining records are still missing. So the domain can serve your pages perfectly and still read Pending. It is not a display bug, and it is not safe to leave, because those remaining records are the channel the certificate renews through.

Add every row in the table. Then check each row's own Status rather than glancing at the badge.

## While you wait

The panel re-checks each record on its own while you have it open, and the badge flips to **Connected** without a refresh. DNS usually propagates in minutes, though some providers take hours.

Your free `.modulify.website` address serves the whole time, so the site is never offline while a domain is pending.

If a row reads **Invalid**, a banner under it names the exact problem. [Troubleshoot a domain](/docs/publish/troubleshooting-a-domain) works through every cause in order.

## Replacing or removing a domain

A site holds one custom domain at a time. The panel says so under the section: `Only one custom domain can be connected at a time. Remove it to connect a different one.` To move to a different domain, remove the current one and connect the new one.

**Remove** asks first. The dialog is titled `Remove example.com?` and warns that your site will stop working at that address, and the confirm button reads **Remove domain**. If a www companion is attached, the description says it stays connected and has to be removed separately.

## Next

- [DNS records](/docs/publish/dns-records) lists the records and what each one does.
- [Troubleshoot a domain](/docs/publish/troubleshooting-a-domain) covers a domain stuck on Pending.
- [www and apex domains](/docs/publish/www-and-apex) covers the second hostname and picking one canonical address.
- [Publish a site](/docs/publish/publish-a-site) is what a connected domain needs before it serves anything.