name: mj-cf-dns
description: "Maintain Cloudflare DNS and domain bindings safely. Use when a user asks to add, update, delete, verify, or audit Cloudflare DNS records; point a domain or subdomain at a Cloudflare Pages *.pages.dev site; bind a custom domain to a Pages project; configure a Worker custom domain through Wrangler custom_domain: true; fix DNS conflicts; or verify Cloudflare nameserver propagation."
Cloudflare DNS
Overview
Use this skill to make Cloudflare DNS changes deliberately: identify the real product path, inspect existing records first, apply idempotent changes, and verify against Cloudflare or authoritative DNS instead of guessing.
Hard Rules
- Do not overwrite or delete DNS records until you have listed the existing records for the exact hostname and type.
- Default to dry-run planning unless the user explicitly asks you to apply the change.
- Preserve user-provided record values literally: type, name, content, priority, TTL, proxied state, and comments.
- Treat Cloudflare Pages, Workers Custom Domains, Workers Routes, and ordinary DNS as different workflows.
- For production domains, verify after write with the Cloudflare API and DNS queries. Prefer authoritative nameservers when available.
- Never print full API tokens. Report only whether
CLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_IDare present.
Choose The Path
- If the user says "point this domain to
*.pages.dev" or "bind a custom domain to Cloudflare Pages", use the Pages custom-domain workflow. - If the user says "bind this domain to a Worker" or the repo has
wrangler.jsoncwithroutes, use the Workers Custom Domains workflow. - If the user gives a DNS table, MX/TXT verification values, A/AAAA/CNAME records, or says "change DNS", use the ordinary DNS workflow.
- If the user only asks whether permissions or config are needed, answer directly and do not touch live DNS.
Credentials
Check:
echo "CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN:+set}"
echo "CLOUDFLARE_ACCOUNT_ID=${CLOUDFLARE_ACCOUNT_ID:+set}"
Minimum token permissions by task:
- DNS read/write:
Zone Read,DNS Read,DNS Writescoped to the target zone. - Pages custom domains:
Pages Read,Pages Write, plus DNS permissions if you also need to create or repair records in a Cloudflare zone. - Workers Custom Domains through Wrangler: Worker script/route permissions such as
Workers Scripts WriteandWorkers Routes Write; DNS Write is not the main path forcustom_domain: true, but existing DNS conflicts may still need DNS access to inspect or delete.
If credentials are missing, explain the exact missing variable and stop before live operations. You may still produce an offline dry-run plan.
Ordinary DNS Workflow
Use for direct DNS record maintenance.
- Resolve the zone from the hostname, usually the registrable domain such as
example.com. - List current records for the exact
nameandtype. - Decide create vs update vs no-op by comparing
content,ttl,proxied,priority, and other relevant fields. - Apply only the minimal change.
- Verify with Cloudflare API and
dig.
Helper script examples:
# Offline dry-run CNAME upsert. No live write without --apply.
node /path/to/mj-cf-dns/scripts/mj-cf-dns.mjs upsert \
--zone example.com \
--name app.example.com \
--type CNAME \
--content my-site.pages.dev \
--proxied true \
--ttl 1
# Dry-run with live read of existing records.
node /path/to/mj-cf-dns/scripts/mj-cf-dns.mjs upsert ... --inspect
# Apply after checking the plan.
node /path/to/mj-cf-dns/scripts/mj-cf-dns.mjs upsert ... --apply
# Verify DNS.
node /path/to/mj-cf-dns/scripts/mj-cf-dns.mjs verify \
--domain app.example.com \
--type CNAME \
--expected my-site.pages.dev
Read references/mj-cf-dns-runbook.md for API payloads and edge cases.
Pages Custom Domain Workflow
Use when binding www.example.com, app.example.com, or example.com to a Cloudflare Pages project.
- Confirm the Pages project name and account ID.
- Add the domain to the Pages project through the Pages project domains API or dashboard.
- For subdomains in a Cloudflare-managed zone, Cloudflare may add the CNAME after confirmation. If it does not, create or update a CNAME from the custom hostname to
<project>.pages.dev. - For external DNS providers, provide the CNAME instruction to the user instead of editing Cloudflare.
- For apex domains, make sure the apex zone is active on Cloudflare; do not blindly create a normal CNAME at the apex unless you have verified Cloudflare's CNAME flattening behavior and existing records.
- Re-check the Pages domain status until it is
activeor report the pending validation details.
Dry-run example:
node /path/to/mj-cf-dns/scripts/mj-cf-dns.mjs bind-pages-domain \
--account "$CLOUDFLARE_ACCOUNT_ID" \
--project my-site \
--domain app.example.com \
--zone example.com \
--pages-target my-site.pages.dev
Apply example:
node /path/to/mj-cf-dns/scripts/mj-cf-dns.mjs bind-pages-domain \
--account "$CLOUDFLARE_ACCOUNT_ID" \
--project my-site \
--domain app.example.com \
--zone example.com \
--pages-target my-site.pages.dev \
--apply
Read references/examples.md for common Pages scenarios.
Workers Custom Domain Workflow
Use this for a Worker that should own a hostname such as api.example.com.
- Check for existing CNAME/A/AAAA conflicts on the hostname.
- Prefer Wrangler config:
{
"routes": [
{ "pattern": "api.example.com", "custom_domain": true }
]
}
- Run
npx wrangler deployfrom the Worker project. - Verify the domain under Workers & Pages > Worker > Settings > Domains & Routes and with
curl -I https://api.example.com.
Do not create a CNAME to workers.dev for this workflow. Cloudflare creates the DNS record and certificate for a Worker Custom Domain.
References
references/mj-cf-dns-runbook.md: detailed API workflow, payloads, verification commands, and failure handling.references/examples.md: concrete examples for Pages, Workers, MX/TXT verification, redirects, and deletion.scripts/mj-cf-dns.mjs: small API helper for dry-run planning, DNS upsert/delete, Pages domain binding, and DNS verification.