> ## Documentation Index
> Fetch the complete documentation index at: https://help.the-meridian.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom domain

You can serve your hosted app on your own domain instead of the [default domain](/default-domain). Meridian provisions the certificate and verifies the connection.

## Connecting a domain

Add your domain on the app's **Settings > Domains** page. Meridian gives you three DNS records to create at your DNS provider:

| Record | Name | Value | What it does |
| - | - | - | - |
| `TXT` | `_meridian-verify.` followed by your domain | `meridian-verify=` and a token, shown on the screen | Proves the domain is yours |
| `CNAME` | your domain, for example `shop` for `shop.example.com` | `edge.the-meridian.app` | Points the domain at Meridian |
| `CNAME` | `_acme-challenge.` followed by your domain | a value unique to your domain, shown on the screen | Lets Google issue the HTTPS certificate |

A bare domain such as `example.com` can't carry a `CNAME` at most DNS providers, so for one of those Meridian shows an `A` record with Meridian's address instead of the `CNAME` that points the domain at Meridian.

The ownership token is new every time you add the domain, so a `TXT` record left from an earlier connection doesn't count: replace its value with the one on the screen. Meridian checks the record once. After the domain is connected you can remove it, and the domain stays live. Domains connected before the ownership record existed don't need one.

The domain then moves through three states:

* **Pending DNS**: Meridian is waiting for the `_acme-challenge` record to resolve, or for the ownership record.
* **Issuing certificate**: the record resolved, and Google is issuing the certificate, usually within minutes.
* **Active**: the certificate is issued, ownership is proven, and your app is reachable on the domain over HTTPS.

Meridian's own domains, `the-meridian.ai`, `the-meridian.app` and every name under them, can't be added as custom domains, and neither can a domain another app on Meridian already holds.

Meridian checks every few minutes, and **Re-verify** checks straight away. Each record shows a check mark once public DNS returns it. Meridian keeps the certificate renewed through the same `_acme-challenge` record, so leave it in place.

### Moving a domain without downtime

The certificate depends only on the `_acme-challenge` record, not on where the domain points. To move a domain that is live somewhere else, add the `TXT` and `_acme-challenge` records first and wait for **Active**, then change the domain's own record to Meridian. HTTPS works from the first request that reaches Meridian.

### Cloudflare and other proxies

A proxy such as Cloudflare in front of the domain works. The certificate is issued through the `_acme-challenge` record, which the proxy doesn't touch. Point the proxied record at `edge.the-meridian.app`. The screen may then show the record that points the domain at Meridian as not detected, because public DNS returns the proxy's addresses, which is expected. Use Cloudflare's **Full (strict)** SSL mode so the proxy talks to Meridian over HTTPS.

### If the certificate fails

If Google can't issue the certificate, usually because the `_acme-challenge` record was missing or wrong for too long, the domain shows *failed* with Google's reason. Fix the record, then select **Re-verify** to start issuance again.

With the [CDN](/cdn) add-on, your custom domains are cached like the default domain.

Form actions work on the custom domain without any change to your app. The edge router accepts a `POST` from whichever of your hostnames served the page and still refuses one from anywhere else. See [React Router apps: form actions through the edge router](/deployment#react-router-apps-form-actions-through-the-edge-router).

## Removing a domain

Removing a custom domain stops serving your app on it and frees the hostname, so you can add it back later. If Meridian can't release the domain on its side, the domain stays in the list as *failed*: remove it again to retry.

## External domains

An external domain is the `https://` origin of your app when it runs outside Meridian, on Heroku, Fly or your own server. Meridian does not serve it, so there is no DNS record to add and no certificate to provision. It tells Meridian where to forward your Shopify webhooks.

Add one on the app's **Settings > Domains** page, under **External domains**. Unlike custom domains, they don't depend on your plan, so every app can add them, up to 10 per app. The origin is `https://` with no path, and a hostname can't be both a custom domain and an external domain of the same app.

A new external domain is *pending* until you click **Verify** in its detail panel. Meridian then sends a signed challenge to `/webhooks/shopify` on that origin, and your app answers it with the SDK. See [The host verification challenge](/sdk-webhooks#the-host-verification-challenge). The domain becomes *verified*, or *failed* with a short reason such as `HTTP 401`, which usually means the app holds a different signing secret. Verified means your app answers at that origin and holds the signing secret. It does not prove you own the domain.

To receive forwarded webhooks there, select the domain as the forward host on the **Pub/Sub > Webhooks** page. If a later verification of the selected domain fails, it stays selected but forwards fall back until it passes again: to your Meridian deployment when there is one, otherwise they don't reach your app.

Removing the external domain that is your forward host asks for confirmation first, and says where forwards go once it is gone: your Meridian deployment when the app is deployed, otherwise nowhere your app can see. Removing any other external domain changes nothing about delivery.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.