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

# Serve a page on your own domain

> Publish your booking page, store, membership page, contact form or AI assistant on a web address you own, with a certificate issued for you.

export const StillStuck = ({topic}) => <div className="ck-callout ck-callout--note" role="note">
    <p className="ck-callout__body">
      <strong>Still stuck{topic ? ` with ${topic}` : ''}?</strong>{' '}
      Check <a href="/platform/help/troubleshooting">Troubleshooting</a> first —
      it covers the failures we see most often. If that does not resolve it,{' '}
      <a href="/platform/help/contact-support">contact support</a> and include
      your workspace name and the time the problem happened, so we can find the
      matching entry in your audit log.
    </p>
  </div>;

export const TaskHeader = ({before, time, after}) => <div className="ck-task">
    {before ? <div className="ck-task__cell">
        <div className="ck-task__title">Before you start</div>
        <p className="ck-task__body">{before}</p>
      </div> : null}

    {time ? <div className="ck-task__cell">
        <div className="ck-task__title">Takes about</div>
        <p className="ck-task__body">{time}</p>
      </div> : null}

    {after ? <div className="ck-task__cell">
        <div className="ck-task__title">When you're done</div>
        <p className="ck-task__body">{after}</p>
      </div> : null}
  </div>;

export const Path = ({steps = []}) => <span className="ck-path">
    {steps.map((s, i) => <span key={i} className="ck-path__step">
        {i > 0 ? <span className="ck-path__sep" aria-hidden="true">
            ›
          </span> : null}
        {s}
      </span>)}
  </span>;

export const Availability = ({editions = ['all'], plans, roles, note}) => {
  const list = editions.includes('all') ? ['clinic', 'pharmacy', 'lims'] : editions;
  return <div className="ck-avail" role="note" aria-label="Feature availability">
      <span className="ck-avail__label">Available in</span>

      {list.map(e => <span key={e} className={`ck-pill ck-pill--${e}`}>
          {EDITION_LABELS[e] || e}
        </span>)}

      {plans ? <span className="ck-avail__label">Plan</span> : null}
      {plans ? <span className="ck-pill ck-pill--plan">{plans}</span> : null}

      {roles ? <span className="ck-avail__label">Who</span> : null}
      {roles ? <span className="ck-pill ck-pill--role">{roles}</span> : null}

      {note ? <span className="ck-avail__note">{note}</span> : null}
    </div>;
};

<Availability editions={['clinic']} plans="Team and above" roles="Owner, Manager" />

Five of your public pages can be served on a domain you own, so a patient books at `book.yourclinic.com` rather than at a ClinikEHR address. You add two DNS records, and the security certificate is issued for you.

## What can have a domain

| Surface                | Example                     | Set it up on                                                     |
| ---------------------- | --------------------------- | ---------------------------------------------------------------- |
| Booking page           | `book.yourclinic.com`       | <Path steps={['Settings', 'Booking Page Designer', 'Design']} /> |
| Store                  | `shop.yourclinic.com`       | <Path steps={['Settings', 'Store Page']} />                      |
| Membership page        | `membership.yourclinic.com` | <Path steps={['Settings', 'Membership Page']} />                 |
| Contact form           | `inquire.yourclinic.com`    | <Path steps={['Settings', 'Contact Form']} />                    |
| Published AI assistant | `assistant.yourclinic.com`  | <Path steps={['Agents', 'Public UIs']} />                        |

One domain per surface, and each surface has its own **Custom domain** card. Four separate subdomains for four pages is normal and expected.

<Note>
  **The patient portal does not support custom domains.** It is always served on the ClinikEHR portal address, and there is no setting to change that — so there is nothing to hunt for on the **Client Portal** tab. Everything else about the portal, including its branding, is yours to set: see [Portal branding](/portal/setup/branding).
</Note>

<TaskHeader before="A domain you control the DNS for, and the Team plan or above" time="10 minutes of work, then up to a few hours of waiting" after="Your page live on your own address, with a valid certificate" />

## Connect a domain

<Steps>
  <Step title="Decide the subdomain">
    Use a subdomain — `book.yourclinic.com`, not `yourclinic.com`. Most registrars cannot point a bare domain at anything but their own hosting, and the card says as much.
  </Step>

  <Step title="Open the surface's settings tab and find Custom domain">
    The card is headed **Custom domain** — "Serve this page on a domain you own". Enter your hostname and select **Connect domain**.
  </Step>

  <Step title="Add the ownership record at your DNS provider">
    The card now shows two records. Add the first, **1. Ownership (TXT)** — use **Copy value** so nothing is mistyped. This proves the domain is yours.
  </Step>

  <Step title="Select Verify now, and wait">
    The badge moves from **Waiting for TXT record** to **Waiting for CNAME** once the record is visible. Verification is also checked automatically, so **Verify now** just saves you waiting.
  </Step>

  <Step title="Add the routing record">
    Add **2. Routing (CNAME)**, again with **Copy value**. This is what actually points visitors at your page.
  </Step>

  <Step title="Wait for the certificate">
    The badge moves to **Issuing certificate**. Nothing is required from you — the certificate is requested and installed automatically.
  </Step>

  <Step title="Confirm it reads Live">
    When the badge says **Live**, an **Open** button appears beside the hostname. Select it, and your page loads on your own address over HTTPS.
  </Step>
</Steps>

## The status ladder

The badge on the card tells you exactly where you are.

| Badge                      | Means                                                  | What to do                                                              |
| -------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------- |
| **Waiting for TXT record** | The ownership record is not visible yet                | Add the TXT record, then **Verify now**                                 |
| **Waiting for CNAME**      | Ownership is proved; routing is not in place           | Add the CNAME record, then **Verify now**                               |
| **Issuing certificate**    | Both records are good; the certificate is being issued | Wait. Usually minutes                                                   |
| **Live**                   | Your page is being served on your domain               | Nothing                                                                 |
| **Needs attention**        | Setup failed. The reason is shown under the badge      | Read the reason, fix the record, **Verify now**                         |
| **Suspended**              | The domain has been taken out of service               | Read the reason, then [contact support](/platform/help/contact-support) |

**Nothing is served on your domain until the badge reads Live.** Until then your ClinikEHR address is the working link, and it keeps working afterwards too.

## Disconnecting

**Disconnect** on the card removes the domain. The confirmation is explicit about the consequences: the domain stops serving the page immediately, your ClinikEHR link keeps working, and for 30 days no other account can claim that hostname.

## Check it worked

* The badge on the **Custom domain** card reads **Live**.
* **Open** loads your page on your own address, with a padlock in the browser.
* The page looks like your ClinikEHR page — same branding, same content.
* Your original ClinikEHR link still works. It always does.

## If something goes wrong

<AccordionGroup>
  <Accordion title="I added the records and it still says Waiting">
    DNS changes take time to spread — usually minutes, occasionally a few hours, and up to 48 in the worst case. Select **Verify now** occasionally rather than deleting and re-adding the domain, which restarts the clock.
  </Accordion>

  <Accordion title="Verify now keeps failing after several hours">
    Almost always a typo or a duplicated hostname. Check three things at your DNS provider: the record **name** matches what the card shows exactly; the **value** was pasted with **Copy value** and not retyped; and your provider has not silently appended your domain to a name that already contained it — `book.yourclinic.com.yourclinic.com` is the classic version of this.
  </Accordion>

  <Accordion title="There is no Custom domain card on the tab">
    Custom domains are part of the **Team** plan and above. On a lower plan the card shows an upgrade prompt instead of the form. See [Change your plan](/platform/plans/change-plan).
  </Accordion>

  <Accordion title="I want to use my bare domain, without a subdomain">
    Use a subdomain. Most registrars cannot point a bare domain at an external service, and doing it usually breaks your main website's mail records as a side effect.
  </Accordion>

  <Accordion title="The browser warns the connection is not private">
    The certificate is not issued yet — the badge will still read **Issuing certificate**. Wait for **Live** before sharing the address with anyone.
  </Accordion>

  <Accordion title="It says Needs attention">
    The reason is printed under the badge in red. Fix the record it names and select **Verify now**. If the reason is not something you can act on, [contact support](/platform/help/contact-support) with the hostname.
  </Accordion>

  <Accordion title="Can I point two surfaces at the same hostname?">
    No — one domain per surface, and a hostname is claimed once. Give each page its own subdomain.
  </Accordion>
</AccordionGroup>

## Related

<Columns cols={2}>
  <Card title="Brand your public pages" icon="https://mintcdn.com/clinikehr/nLyvBRumcl1Yk8z3/images/icons/palette.svg?fit=max&auto=format&n=nLyvBRumcl1Yk8z3&q=85&s=3b2a5d7b762442ba8faf36251771633c" href="/platform/settings/branding" width="24" height="24" data-path="images/icons/palette.svg">
    Logos, colours and copy on each public surface.
  </Card>

  <Card title="Embed on your website" icon="https://mintcdn.com/clinikehr/gjlpJWWKqjyYNRzM/images/icons/code.svg?fit=max&auto=format&n=gjlpJWWKqjyYNRzM&q=85&s=3d6bc617a8ceba1aac8fb7795e0d73b3" href="/platform/integrations/embeds" width="24" height="24" data-path="images/icons/code.svg">
    Putting a page inside your own site instead of linking to it.
  </Card>
</Columns>

<StillStuck topic="a domain that will not go live" />
