# Connect a custom domain

> Serve your landing pages, booking pages and clients' portal on a subdomain of your own, such as coaching.example.com, with the two DNS records it needs.

## Goal

Your clients open your landing pages, your booking pages and their portal on your own address, such as `https://coaching.example.com`, instead of `https://coaching-toolkit.com`. Coaching Toolkit issues and renews the HTTPS certificate; you create two DNS records once.

## Prerequisites

- **Admin** of the practice. One domain per practice.
- **A subdomain you control**, such as `coaching.example.com` or `book.example.co.uk`: at least three labels. A bare domain (`example.com`) is not supported, nor anything under `coaching-toolkit.com`.
- Access to the DNS settings where the domain is registered or hosted (your registrar, or a DNS host such as Cloudflare, Route 53 or your web host).

## 1. Add the hostname

In the app (Admin, web): **Settings**, **Brand and domain**, **Custom domain**, enter the hostname, **Add**. Optionally pick which published landing page answers at `/`; without one, the default page of the practice's first Coach who has one answers there.

The app then shows the two DNS records to create (a `CNAME` and a `TXT`) and the domain's status, `PendingVerification`.

## 2. Create the two DNS records

At your DNS provider, for the hostname you added:

| Type | Name | Value | Why |
| --- | --- | --- | --- |
| `CNAME` | `coaching` (the hostname without your domain; some providers want the full `coaching.example.com`) | `pages.coaching-toolkit.com` | sends visitors to Coaching Toolkit |
| `TXT` | `_coaching-toolkit.coaching` (or the full `_coaching-toolkit.coaching.example.com`) | the TXT value the app shows for your domain | proves you own the domain |

- Leave the TTL at the default.
- If your DNS is at Cloudflare, set the CNAME to **DNS only** (grey cloud), not proxied.
- A hostname that already has other records (an `A` record, for example) cannot also be a CNAME: remove them first.

Records usually resolve within minutes; some providers take up to a few hours.

## 3. Verify

In the app: **Verify**. It looks both records up; when both resolve, Coaching Toolkit starts issuing the certificate and the domain is `Verifying`.

If a record is not found yet, the app names which ones (CNAME, TXT); fix them and verify again.

## 4. Wait for the certificate

The certificate is usually issued within a few minutes. **Check status** in the app. When the domain shows `Active` with an active certificate, the domain serves your pages. Coaching Toolkit also checks every hour by itself.

## What the domain serves

| On `https://coaching.example.com` | What |
| --- | --- |
| `/` | the landing page you picked, else the practice's default page |
| `/{slug}` | your practice's landing pages (without the practice slug that leads them on `https://coaching-toolkit.com`) |
| `/book/{slug}`, `/pay/{slug}/{offerId}` | your practice's booking and pay-only pages (served on the same host) |
| `/book/manage/{token}` | the cancel and reschedule link in booking mails |
| `/portal/...` | your clients' portal |
| `/sitemap.xml` | your home page and landing pages |

Not served there: the coach app, the coach API, the documentation, other practices' pages; each answers `404`. Coaches keep signing in at `https://coaching-toolkit.com/login`.

Once the domain is Active, every link Coaching Toolkit sends your clients uses it: portal links, booking confirmations and their manage links, "add to calendar" downloads, and the booking and landing page URLs shown in the app and in your embed snippets. A client signed in to the portal on `https://coaching-toolkit.com` needs a new portal link to sign in on your domain.

## Change the home page or remove the domain

In **Settings**, **Brand and domain**, **Custom domain**, pick another published landing page for `/`, or none to go back to the default page. **Remove** deletes the domain at once; links already sent on it stop working, so remove the DNS records afterwards, not before.

## Verify it worked

```sh
curl -sI https://coaching.example.com/
curl -sI https://coaching.example.com/docs
```

The first answers `200` with your page; the second answers `404`. In the app the domain shows **Active**, and your booking pages show their links on your domain.

## Failure cases

| What you see | Why |
| --- | --- |
| Hostname invalid | not a subdomain of at least three labels (letters, digits, hyphens), or an IP address |
| Hostname reserved | a Coaching Toolkit domain, or a development domain such as `localhost` |
| Hostname taken | another practice (or this one) already connected it |
| Domain limit reached | the practice already has a domain; remove it first |
| Landing page invalid | the chosen page is not a published landing page of the practice |
| DNS not ready | the app names the records not found yet |
| Domain not verified | checking status before a successful verify |
| Certificate service rejected the hostname | for example because it is connected to another service using the same provider |
| Certificate service unavailable | it did not answer; try again in a few minutes |
| Custom domains not set up | custom domains are not set up on this Coaching Toolkit installation |

The domain turns **Failed** when its records disappear later (the practice's Admins get a mail, and your pages answer on `https://coaching-toolkit.com` meanwhile) or when no certificate was issued within 7 days. Fix the records and press **Verify** again.
