Merge pull request 'docs(whp): rework DNS page for new Domains & DNS UI' (#1) from docs/dns-page-rework into main
Build and deploy / deploy (push) Successful in 23s

Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2026-06-11 21:52:34 +00:00
12 changed files with 267 additions and 12 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

After

Width:  |  Height:  |  Size: 89 KiB

+10 -8
View File
@@ -27,24 +27,25 @@ import Support from '~/content/partials/support-link.mdx';
<Steps>
1. In the sidebar, click **Domains**.
![WHP Domains page](~/assets/screenshots/whp/whp-domains.png)
1. In the sidebar, click **Domains & DNS**. You'll see a searchable list of the domains on your account.
![WHP Domains & DNS page](~/assets/screenshots/whp/whp-domains.png)
2. Under **Add New Domain** on the left, type your domain (for example, `example.com`). Don't include `http://` or `www.` — just the bare domain.
2. Click **Add Domain** in the top right. In the dialog, type your domain (for example, `example.com`) — just the bare domain, with no `http://` or `www.`
![Add Domain dialog](~/assets/screenshots/whp/whp-dns-add-domain.png)
3. Click **Add Domain**.
3. Click **Add Domain** to confirm. The domain appears in the list with a green **Active** status.
</Steps>
WHP creates the standard set of DNS records automatically for the new domain:
WHP creates a DNS zone with the standard set of records automatically for the new domain:
- **A record** for the apex domain → your server's IP
- **CNAME** for `www` → the apex
- **NS records** for the nameservers
- **MX record** → the mail server
- **TXT record** for SPF
- **TXT records** for SPF and DKIM
You can review and tweak any of these from the **DNS Management** panel on the right side of the Domains page (select the domain from the dropdown).
You can review and tweak any of these — click **Manage DNS** next to the domain to open the records editor. See [Manage DNS records](/whp/how-to/manage-dns-records/) for the full walkthrough.
## Point your DNS at us
@@ -54,7 +55,7 @@ There are two paths depending on where the domain is registered:
**Registered elsewhere.** At your registrar, do one of the following:
- Set the **nameservers** to the values shown on the Domains page (recommended gives us full DNS control, easier to support), **or**
- Set the **nameservers** to the values shown in **Manage DNS** (the **NS** records) — recommended, as it gives us full DNS control and is easier to support **or**
- Keep your existing nameservers and add an **A record** pointing the domain to the IP shown on the **Dashboard** page under Server Information.
## Verify it worked
@@ -76,6 +77,7 @@ Once DNS resolves, visiting your domain in a browser will reach WHP — though y
## Related
- [Manage DNS records](/whp/how-to/manage-dns-records/)
- [Create a site](/whp/how-to/create-a-site/)
## Still stuck?
+1 -1
View File
@@ -2,7 +2,7 @@
title: Backups
description: Run on-demand and scheduled backups of your sites and databases, and confirm they're succeeding.
sidebar:
order: 4
order: 5
---
import { Steps, Aside } from '@astrojs/starlight/components';
@@ -2,7 +2,7 @@
title: Create a site
description: Spin up a containerized site on a domain you've added to WHP.
sidebar:
order: 2
order: 3
---
import { Steps, Aside } from '@astrojs/starlight/components';
@@ -2,7 +2,7 @@
title: Create an email account
description: Add a mailbox on one of your domains and connect your email client.
sidebar:
order: 3
order: 4
---
import { Steps, Aside } from '@astrojs/starlight/components';
@@ -0,0 +1,113 @@
---
title: Manage DNS records
description: View, add, edit, and delete DNS records for your domains using the Domains & DNS records editor in WHP.
sidebar:
order: 2
---
import { Steps, Aside } from '@astrojs/starlight/components';
import SignIn from '~/content/partials/signing-in.mdx';
import Support from '~/content/partials/support-link.mdx';
When we host your DNS, WHP gives you a full records editor — add, edit, or remove **A**, **CNAME**, **MX**, **TXT**, and other records yourself, no support ticket needed.
## Before you start
- A domain already added to your account. If you haven't done that yet, [add a domain](/whp/how-to/add-a-domain/) first.
- We must be running DNS for the domain (its nameservers point at us). If your DNS lives at another provider, make these changes there instead.
- A couple of minutes. Record changes apply quickly on our side, but can take up to 24 hours to propagate worldwide.
## Sign in to WHP
<SignIn />
## Open the records editor
<Steps>
1. In the sidebar, click **Domains & DNS**.
![WHP Domains & DNS page](~/assets/screenshots/whp/whp-domains.png)
2. Find your domain in the list and click **Manage DNS**.
![DNS records editor for a domain](~/assets/screenshots/whp/whp-dns-records.png)
</Steps>
Each domain starts with a standard zone created automatically when the domain was added:
| Type | What it's for |
| --- | --- |
| **A** | Points the apex domain at your server's IP. |
| **CNAME** | Aliases like `www` and `autoconfig` to the right host. |
| **MX** | Routes mail for the domain to our mail server. |
| **TXT** | SPF and DKIM records that help your mail pass authentication. |
| **NS** | The nameservers that are authoritative for the domain. |
| **SRV** | Service records such as mail autodiscovery. |
<Aside type="caution">
Editing **MX**, **NS**, or the SPF/DKIM **TXT** records can break email delivery or hand DNS control away from us. Only change these if you know exactly what you're doing.
</Aside>
## Add a record
<Steps>
1. Click **Add Record**. A new, editable row appears at the top of the table.
![Inline Add Record row](~/assets/screenshots/whp/whp-dns-add-record.png)
2. Fill in the row:
- **Type** — choose the record type (A, AAAA, CNAME, MX, TXT, NS, PTR, SRV, CAA, SSHFP, or TLSA).
- **Name** — the host the record applies to. Use `@` for the domain itself, or a subdomain like `blog` for `blog.example.com`.
- **Content** — the value: an IP for an A record, a hostname for a CNAME, and so on.
- **Prio** — only used by record types that need a priority (like MX). Leave it blank otherwise.
- **TTL** — how long resolvers may cache the record, in seconds. The default of `300` (5 minutes) is fine for most records.
3. Click **Save**. The record joins the list immediately. (Click **Cancel** to discard the row without saving.)
</Steps>
## Edit or delete a record
In the **Actions** column on the right of each row:
- The **pencil** icon opens the record for editing in place. Change any field, then save.
- The **trash** icon deletes the record. Deletions take effect right away, so double-check before you remove anything.
## Find a record quickly
If a domain has a lot of records, use the **All types** dropdown above the table to filter by a single record type — for example, show only **MX** records while you sort out mail.
## Work with several records at once
Tick the checkboxes on the left of one or more rows to reveal the bulk-action bar:
![Bulk actions on selected DNS records](~/assets/screenshots/whp/whp-dns-bulk-actions.png)
- **Change TTL** — set the same TTL on every selected record.
- **Enable/Disable** — toggle records on or off without deleting them (handy for temporarily parking a record).
- **Delete** — remove all selected records at once.
- **Clear** — clear your selection (this does *not* delete anything).
## Verify it worked
DNS changes apply on our side within moments, but resolvers elsewhere may keep serving the old answer until the record's TTL expires (up to 24 hours for unfamiliar records).
- Run `dig example.com +short` (or `dig blog.example.com A +short`) from a terminal and confirm you see the value you just set.
- Or use a web tool like [whatsmydns.net](https://www.whatsmydns.net/) to watch propagation across regions.
## Troubleshooting
**My change isn't showing up yet.** Resolvers cache records for the length of their TTL. Wait for the TTL to pass, then clear your local DNS cache and check again with `dig`.
**There's no Manage DNS button for my domain.** We're not running DNS for it — its nameservers point somewhere else. Make the change at your current DNS provider, or [point the domain's nameservers at us](/whp/how-to/add-a-domain/#point-your-dns-at-us) first.
**Email stopped working after I edited records.** Restore the original **MX** and SPF/DKIM **TXT** records. If you're not sure what they should be, open a support ticket (see below) and we'll put them back.
## Related
- [Add a domain](/whp/how-to/add-a-domain/)
- [Create an email account](/whp/how-to/create-an-email-account/)
## Still stuck?
<Support />
@@ -2,7 +2,7 @@
title: Switching your site's backend
description: Change the web engine (container type) running a site — standard PHP/FPM or the premium LiteSpeed/OpenLiteSpeed tier.
sidebar:
order: 5
order: 6
---
import { Steps, Aside } from '@astrojs/starlight/components';
+140
View File
@@ -0,0 +1,140 @@
/**
* DNS capture — the reworked "Domains & DNS" area.
*
* Captures, as the demo customer (so the demo domain's real zone shows):
* - whp-domains.png the Domains & DNS list (searchable table)
* - whp-dns-add-domain.png the Add Domain modal
* - whp-dns-records.png the per-domain DNS Records editor
* - whp-dns-add-record.png the inline "Add Record" editor row
* - whp-dns-bulk-actions.png the bulk-select toolbar
*
* Viewport-only (1440x900), redacted for our multi-server fleet: server /
* mail / nameserver hostnames and IPs become neutral placeholders, while the
* brand demo domain (whp-demo.anhh.co) is kept visible on purpose.
*
* Read-only: opens modals and ticks checkboxes for the screenshot, never
* saves, deletes, or submits anything.
*/
import { chromium, type Page } from 'playwright';
import { mkdir } from 'node:fs/promises';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const OUT_DIR = resolve(__dirname, '../../src/assets/screenshots/whp');
function need(name: string): string {
const v = process.env[name];
if (!v) throw new Error(`missing env: ${name}`);
return v;
}
const BASE = need('WHP_BASE');
const USER = need('WHP_USER');
const PASS = need('WHP_PASS');
const DOMAIN = process.env.WHP_DEMO_DOMAIN ?? 'whp-demo.anhh.co';
const HIDE_CSS = `.navbar-text, .brand-full { visibility: hidden !important; }`;
async function login(page: Page) {
await page.goto(`${BASE}/login.php`, { waitUntil: 'domcontentloaded' });
await page.fill('input[name="user"]', USER);
await page.fill('input[name="password"]', PASS);
await page.click('button[type="submit"]');
await page.waitForLoadState('networkidle');
}
/**
* Neutralise fleet-identifying text before the screenshot. The brand demo
* domain (anhh.co) is intentionally preserved; everything that names a
* specific server, mail host, nameserver, or IP is swapped for a placeholder.
*/
async function redact(page: Page) {
await page.addStyleTag({ content: HIDE_CSS });
await page.evaluate(() => {
const swaps: [RegExp, string][] = [
[/ns[12]\.whp\d+(-[a-z0-9]+)?\.cloud-hosting\.io/gi, 'ns<n>.<your-server>.cloud-hosting.io'],
[/whp\d+(-[a-z0-9]+)?\.cloud-hosting\.io/gi, '<your-server>.cloud-hosting.io'],
[/mail\d+\.cloud-hosting\.io/gi, '<mail-server>.cloud-hosting.io'],
[/WHP\d+(-[A-Z0-9]+)?\b/g, '<YOUR-SERVER>'],
[/whp\d+(-[a-z0-9]+)?\b/gi, '<your-server>'],
// Public IPv4 (skip RFC1918 — those read fine as generic examples)
[/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g, '<server-IP>'],
[/demo-user/g, 'your-username'],
];
// Text nodes
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
const nodes: Text[] = [];
let n: Node | null = walker.nextNode();
while (n) { nodes.push(n as Text); n = walker.nextNode(); }
for (const node of nodes) {
let v = node.nodeValue ?? '';
for (const [re, rep] of swaps) v = v.replace(re, rep);
if (v !== node.nodeValue) node.nodeValue = v;
}
// Input values (the inline Add Record / TTL fields)
document.querySelectorAll<HTMLInputElement>('input').forEach((el) => {
if (el.type === 'password' || !el.value) return;
let v = el.value;
for (const [re, rep] of swaps) v = v.replace(re, rep);
if (v !== el.value) el.value = v;
});
});
}
async function shot(page: Page, id: string) {
await page.waitForTimeout(400);
await redact(page);
const path = resolve(OUT_DIR, `${id}.png`);
await page.screenshot({ path, fullPage: false });
console.log(`captured ${id} -> ${path}`);
}
async function main() {
await mkdir(OUT_DIR, { recursive: true });
const browser = await chromium.launch({ headless: true });
const ctx = await browser.newContext({
ignoreHTTPSErrors: true,
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 2,
});
const page = await ctx.newPage();
try {
await login(page);
// 1. Domains & DNS list
await page.goto(`${BASE}/index.php?page=domains`, { waitUntil: 'networkidle' });
await shot(page, 'whp-domains');
// 2. Add Domain modal
await page.locator('button:has-text("Add Domain"), a:has-text("Add Domain")').first().click();
await page.waitForTimeout(600);
await shot(page, 'whp-dns-add-domain');
await page.keyboard.press('Escape').catch(() => {});
await page.waitForTimeout(300);
// 3. DNS Records editor for the demo domain
await page.goto(`${BASE}/index.php?page=domains&domain=${DOMAIN}`, { waitUntil: 'networkidle' });
await shot(page, 'whp-dns-records');
// 4. Inline Add Record row
await page.locator('button:has-text("Add Record"), a:has-text("Add Record")').first().click();
await page.waitForTimeout(500);
await shot(page, 'whp-dns-add-record');
// Cancel the inline add row so the next shot is clean
await page.locator('button:has-text("Cancel")').first().click().catch(() => {});
await page.waitForTimeout(400);
// 5. Bulk-select toolbar (tick two record rows)
const rowChecks = page.locator('table tbody input[type=checkbox]');
const n = await rowChecks.count();
if (n >= 2) { await rowChecks.nth(0).check(); await rowChecks.nth(1).check(); }
else if (n === 1) { await rowChecks.nth(0).check(); }
await page.waitForTimeout(500);
await shot(page, 'whp-dns-bulk-actions');
} finally {
await browser.close();
}
}
main().catch((err) => { console.error(err); process.exit(1); });