> This page is for Developer.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.bigcommerce.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.bigcommerce.com/_mcp/server.

# Custom Domains

> Add a custom domain to a Storefront Hosting project with the Catalyst CLI, including setup for stores that already serve their domain through Cloudflare.

By default, a Storefront Hosting deployment is served from a BigCommerce-provided hostname in the form `<your-project>.catalyst-sandbox.store` — your **worker URL**. This page covers attaching your own domain to a project with the Catalyst CLI, in two setup flows: the standard flow for any DNS provider, and the Orange-to-Orange (O2O) flow for stores that already serve their domain through their own Cloudflare account.

> **Warning**
>
> The Catalyst CLI is generally available, but Storefront Hosting is currently
> in closed beta. There may be breaking changes to the Storefront Hosting APIs as we
> finalize them. To express interest in gaining access, fill out the [Storefront Hosting Closed Beta Interest Form](https://docs.google.com/forms/d/e/1FAIpQLSfDepq3qRtEtavb1wQvSvdK21pwr_kNsYQbH2B7JjWYyptUSA/viewform?usp=header).

## Prerequisites

* A linked Storefront Hosting project. Run `pnpm catalyst projects create` or `pnpm catalyst projects link`, as described in [Getting Started](/developer/docs/storefront/catalyst/deployment/storefront-hosting/getting-started).
* At least one successful `pnpm catalyst deploy`, so the project has a worker URL to route traffic to.
* Store credentials available to the CLI, either from `pnpm catalyst auth login` or through `--store-hash` and `--access-token`. See [Authentication](/developer/docs/storefront/catalyst/deployment/storefront-hosting/overview#authentication).
* Access to the DNS zone for the domain you're attaching.

## Choose a setup flow

Both flows use the same command, `catalyst domains add`. They differ only in the DNS record you publish.

| Your DNS setup                                                                | Flow                                                         | Record to publish                                   |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------ | --------------------------------------------------- |
| Any DNS provider, or Cloudflare with DNS-only (grey-clouded) records          | [Standard setup](#standard-setup)                            | `CNAME` to your worker URL, or `A` to your store IP |
| Cloudflare, with the domain proxied (orange-clouded) through your own account | [Cloudflare (O2O) setup](#cloudflare-orange-to-orange-setup) | `CNAME` to `shops.mybigcommerce.com`, proxied       |

O2O stands for "Orange-to-Orange": your zone is proxied by Cloudflare (orange cloud) and so is BigCommerce's, so traffic passes through two Cloudflare zones. Use it when you want your own Cloudflare rules — WAF, page rules, caching, bot management — to keep applying to storefront traffic. If you are on Cloudflare but don't need those rules to apply, the standard setup works: set the record to DNS-only.

## Standard setup

Use this flow for any DNS provider — a registrar's own DNS, Route 53, or Cloudflare with a DNS-only record.

### Add the domain to your project

Run `domains add` from your project directory. The command registers the domain and prints the DNS records that point it at this project.

```shell showLineNumbers={false}
pnpm catalyst domains add example.com
```

The output includes the domain's verification status and the records to publish:

```text
✅ Domain example.com added.
example.com pending
ℹ️ Point example.com at this project with one of these DNS records:
  A      <your-store-ip>
  CNAME  <your-project>.catalyst-sandbox.store
```

> **Warning**
>
> `catalyst domains add` is the only command that returns the pointing records —
> `domains status` and `domains list` won't print them again, so copy them
> before you move on. If you do lose them, you can look both values up: see
> [Troubleshooting](#troubleshooting).

### Publish the DNS record

For a subdomain such as `shop.example.com`, publish the `CNAME` record:

```text showLineNumbers={false}
Type:   CNAME
Host:   shop
Value:  <your-project>.catalyst-sandbox.store
```

For an apex domain such as `example.com`, publish the `A` record. Most DNS providers do not allow a `CNAME` on an apex domain. You can also find your store IP in the store control panel under **Settings → Email & DNS Records**.

```text showLineNumbers={false}
Type:   A
Host:   @
Value:  <your-store-ip>
```

### Wait for verification

A new domain starts in a `pending` verification state and becomes `active` once DNS has propagated and BigCommerce verifies the record. See [Check domain status](#check-domain-status).

## Cloudflare (Orange-to-Orange) setup

Use this flow when your domain's zone lives in your own Cloudflare account and you want to keep it proxied so your Cloudflare configuration continues to apply. Instead of pointing at the worker URL, you point at BigCommerce's fallback origin and leave the record proxied.

This is the same setup Cloudflare documents in its [BigCommerce provider guide](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/bigcommerce/#enable), and it applies to both Stencil storefronts and Catalyst storefronts on Storefront Hosting.

### Set the zone SSL/TLS mode

In your Cloudflare dashboard, open **SSL/TLS → Overview** for the zone and set the encryption mode to **Full** or **Full (strict)**. Flexible mode is not supported, because BigCommerce terminates TLS at its own edge.

### Publish a proxied CNAME record

Create a `CNAME` record pointing at `shops.mybigcommerce.com` and leave the proxy status set to **Proxied** (orange cloud). For a subdomain such as `shop.example.com`:

```text showLineNumbers={false}
Type:   CNAME
Name:   shop
Target: shops.mybigcommerce.com
Proxy:  Proxied
```

This applies to apex domains as well. Most registrars reject a `CNAME` on an apex record, but Cloudflare supports it through CNAME flattening — so an apex domain on Cloudflare uses the same proxied `CNAME` to `shops.mybigcommerce.com`, not an `A` record.

```text showLineNumbers={false}
Type:   CNAME
Name:   @
Target: shops.mybigcommerce.com
Proxy:  Proxied
```

### Add the domain to your project

Register the domain with the CLI. Because the O2O record target is always `shops.mybigcommerce.com`, you can ignore the pointing records this command prints — they describe the standard flow.

```shell showLineNumbers={false}
pnpm catalyst domains add example.com
```

### Wait for verification

As in the standard flow, the domain starts as `pending` and becomes `active` once BigCommerce verifies it. See [Check domain status](#check-domain-status).

### Cloudflare product compatibility

O2O routes traffic through two Cloudflare zones, and not every Cloudflare product applies on both sides. None of the following prevents O2O from working, but plan around it so you don't expect a feature to take effect where it can't. Cloudflare publishes the authoritative [product compatibility table](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/).

| Product                                            | Where it applies to O2O traffic                                       |
| -------------------------------------------------- | --------------------------------------------------------------------- |
| WebSockets, Rocket Loader, China Network, Spectrum | Unsupported on both zones                                             |
| Load Balancing, Origin Rules, Argo Smart Routing   | BigCommerce's zone only — your own configuration does not take effect |
| API Shield, Zaraz                                  | Your zone only                                                        |

### Cloudflare (O2O) limitations

* **Apex domains must use a proxied `CNAME`**, not an `A` record. Although most registrars do not allow pointing an apex domain with a CNAME, Cloudflare does allow this via CNAME flattening.
* **Enterprise zone holds block activation.** If your zone has a hold applied, release it temporarily so the custom hostname can activate.

## SSL/TLS certificates

The two flows terminate TLS in different places, so which certificate a visitor sees — and whether you can supply your own — depends on the flow you chose.

### Standard setup

BigCommerce's Cloudflare for SaaS instance provisions and renews the certificate for the custom hostname.

> **Warning**
>
> Custom SSL/TLS certificates are not yet supported in this flow. Your domain
> serves the certificate BigCommerce assigns to it, and a certificate you supply
> is not applied. If your domain requires a specific certificate or issuing CA,
> use the [Cloudflare (O2O) setup](#cloudflare-orange-to-orange-setup) instead.

### Cloudflare (O2O) setup

Your own Cloudflare zone terminates TLS for visitor traffic, so the certificate the visitor sees is the one on your zone — which means custom certificates are supported. Configure the certificate you want in your Cloudflare account. When more than one certificate could match the hostname, Cloudflare's [certificate and hostname priority](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/) rules determine which it serves.

BigCommerce still provisions a certificate for the custom hostname on its own zone, since that zone is the origin your zone connects to. That connection is why the zone's encryption mode has to be **Full** or **Full (strict)**.

## Check domain status

DNS propagation can take anywhere from a few minutes to a day, so check the status periodically rather than waiting on a single command.

```shell showLineNumbers={false}
pnpm catalyst domains status example.com
```

Add `--wait` to poll until the domain leaves `pending`. The command polls every five seconds and times out after five minutes, which is shorter than propagation often takes — a timeout is not a failure.

```shell showLineNumbers={false}
pnpm catalyst domains status example.com --wait
```

To see every domain on the project and its status, or to filter to the ones still verifying:

```shell showLineNumbers={false}
pnpm catalyst domains list
pnpm catalyst domains list --status pending
```

### Verify domain ownership

If the domain is already in use on another store, `catalyst domains add` refuses the request and prints an ownership-verification `TXT` record instead:

```text
⚠️ example.com is already in use on another store.
Add this DNS record to verify ownership:
  Type:  TXT
  Name:  _commerce-verify.example.com
  Value: <verification-value>
ℹ️ Once the record is live, claim it with:
  catalyst domains claim example.com
```

Publish the `_commerce-verify` `TXT` record in the zone for the domain — in your Cloudflare DNS if you're on Cloudflare, or with your DNS provider otherwise. Ownership verification works the same way in both flows. Once the record resolves, claim the domain:

```shell showLineNumbers={false}
pnpm catalyst domains claim example.com
```

If ownership still can't be verified, the command reprints the record so you can confirm it and retry.

## Move a domain between projects

If the domain is already bound to a different project in the same store, `domains add` tells you to transfer it rather than claim it. Run `domains transfer` from the project that currently owns the domain:

```shell showLineNumbers={false}
pnpm catalyst domains transfer example.com --to-project-uuid <PROJECT_UUID>
```

Omit `--to-project-uuid` to pick the destination project from a list. Transferring does not change DNS — the record keeps pointing at the same store, and BigCommerce routes it to the new project.

## Remove a domain

```shell showLineNumbers={false}
pnpm catalyst domains remove example.com
```

Removing an active domain prompts for confirmation, since traffic stops routing to the project. Pass `--force` to skip the prompt in a script or CI job.

```shell showLineNumbers={false}
pnpm catalyst domains remove example.com --force
```

## Troubleshooting

| Symptom                                                          | What to try                                                                                                                                                                                                                                                                                                                                              |
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **"Infrastructure Domains API not enabled"**                     | The Domains API is gated during the closed beta. If you're in the beta, contact [support@bigcommerce.com](mailto:support@bigcommerce.com) to enable it.                                                                                                                                                                                                  |
| **Domain stays `pending`**                                       | Confirm the published record matches what `domains add` returned, then re-check with `domains status`. Propagation can take up to a day.                                                                                                                                                                                                                 |
| **You lost the pointing records**                                | Look both values up directly: the `A` record value is your store IP, in the control panel under **Settings → Email & DNS Records**, and the `CNAME` value is your worker URL (`<your-project>.catalyst-sandbox.store`), from `pnpm catalyst projects list`. As a last resort, remove the domain with `domains remove` and add it again for a fresh copy. |
| **"already in use on another store"**                            | Publish the `_commerce-verify` `TXT` record, then run `domains claim`. See [Verify domain ownership](#verify-domain-ownership).                                                                                                                                                                                                                          |
| **"already bound to another project"**                           | Use `domains transfer`. See [Move a domain between projects](#move-a-domain-between-projects).                                                                                                                                                                                                                                                           |
| **Cloudflare returns a redirect loop or a 5xx on an O2O domain** | Check the zone's SSL/TLS mode. Flexible mode causes this — set it to **Full** or **Full (strict)**.                                                                                                                                                                                                                                                      |
| **Your Cloudflare WAF or page rules don't apply**                | The record is likely DNS-only. Set it to **Proxied** and point it at `shops.mybigcommerce.com`.                                                                                                                                                                                                                                                          |

For the full set of flags on every `domains` subcommand, see the [CLI Reference](/developer/docs/storefront/catalyst/reference/cli#domains-add).