Move the apex to yellowpine.com and make .dev the redirect - #1
Conversation
yellowpine.com is finally in the Porkbun account, so the site takes the name people actually guess. yellowpine.dev becomes the redirect domain. This also closes a live defect. The page has advertised hello@yellowpine.com since 2026-09-08, but .com was not ours then, and when it arrived it came with the previous owner's Mailgun MX records and none of our forwards. Every message sent to the address on the homepage went to servers we do not control. No test related the contact address to the domain the site is served from, so nothing caught it. tests/site.test.mjs now asserts that relationship. It was written against the live page first, where it failed with "contact address is not on yellowpine.dev: hello@yellowpine.com", and only then was the domain flipped. The Deploying section is rewritten rather than retitled: its reasoning rested on .dev being HSTS-preloaded, which made HTTPS free. .com is not, so Enforce HTTPS is now something to set rather than assume. The ordering footgun that cost a morning last time -- DNS must point at GitHub before the domain lands in CNAME, or validation fails and GitHub never retries -- is written down there too. The 2026-09-08 spec is left as written; the new one supersedes it rather than editing what was true then. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q5nJ8eKEb1wm5tCzxipXHS
There was a problem hiding this comment.
🟡 Changes recommended
Four moderate findings remain in the migration documentation, metadata checks, and contact-address validation.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Moves the GitHub Pages site apex from yellowpine.dev to yellowpine.com and documents .dev as the redirect domain.
Changes:
- Updates CNAME, metadata, README, and package description.
- Adds contact-domain validation tests.
- Adds DNS migration and deployment documentation.
File summaries
| File | Summary | Final review comments |
|---|---|---|
tests/site.test.mjs |
Updates domain assertions and validates mailto: links. |
Moderate (1 vote): Strip query parameters before validating mailto: addresses. Moderate (1 vote): Reject malformed addresses containing multiple @ characters. |
README.md |
Documents the new domain topology and deployment process. | No final comments. |
package.json |
Updates the project description. | No final comments. |
index.html |
Updates canonical and Open Graph metadata. | Moderate (3 votes): Assert og:url and og:site_name against DOMAIN, rather than only checking tag existence. |
docs/superpowers/specs/2026-09-10-yellowpine-com-apex-design.md |
Records migration sequencing and DNS decisions. | Moderate (2 votes): Resolve the conflict between deleting .dev mail records and preserving the hosted inbox. |
CNAME |
Sets yellowpine.com as the custom domain. |
No final comments. |
Review details
Suppressed comments (2)
tests/site.test.mjs:96
- RFC 6068 permits query parameters on a
mailto:URI, such asmailto:hello@yellowpine.com?subject=Hello. Including that query inaddressmakes this assertion reject an otherwise valid contact link because the parsed domain becomesyellowpine.com?subject=Hello; strip the query before validating the address.
const address = href.slice('mailto:'.length);
tests/site.test.mjs:98
- The new invariant does not actually reject every off-domain address:
address.split('@')[1]is stillyellowpine.comfor a malformed value such ashello@yellowpine.com@attacker.example, so that link would pass despite not being a valid address on this domain. Validate that there is exactly one@(and compare the part after it) before asserting the domain.
address.split('@')[1],
- Files reviewed: 6/6 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| domain whose DNS still points elsewhere fails validation, and GitHub never retries. | ||
| 5. Merge -> Pages re-registers on `.com`. Verify the certificate reaches `approved`, then | ||
| enable `https_enforced` in its own call. | ||
| 6. Immediately after: `.dev` A records, `www`, MX, SPF and forwards deleted; URL forward added. |
| <meta property="og:site_name" content="yellowpine.com"> | ||
| <meta property="og:url" content="https://yellowpine.com/"> |
mailto: hrefs may carry ?subject= or ?body=, and splitting on @ alone folds that tail into the host: "yellowpine.com?subject=Hello" never equals DOMAIN, so the invariant would fail on a link that is perfectly correct. Found reviewing the diff, not in the wild -- neither address on the page carries a query today. Fixing it now keeps the next person from hitting a false failure and "fixing" it by loosening the assertion. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q5nJ8eKEb1wm5tCzxipXHS
Five findings, all real: The domain guard missed og:url and og:site_name entirely. hrefsIn() matches only href=/src=, so the og:* tags never reached the mailto or canonical checks, and the metadata test asserted those tags EXIST without ever reading what they say. A future move could update CNAME and canonical, miss og:*, and go green while every shared link advertised the old domain. Proven by reverting og:url alone: CNAME and canonical both still passed, and only the new guard failed. The address is also visible anchor text, not just an href. Editing one without the other left the suite green while anyone copying the address by eye got the dead domain. Also proven by mutation. README documented `-f cname=""` as the certificate recovery. The Pages API removes a custom domain only on a JSON null, and gh's -f sends raw strings, so the one command written down for the emergency would fail at the moment it was needed. Now `-F cname=null`, with the reason next to it. The spec claimed `npm test` was the gate for four things it cannot check: the apex is excluded from the liveness test by isSelf, and nothing fetches .dev or tests mail. A certificate that never issued would have kept CI green forever. The verification section now says plainly that those checks are manual. The spec's non-goal about the .dev trial inbox contradicted step 6, which deletes the MX and SPF that inbox would need. Reworded: it is neither set up nor cancelled, it lapses on 2026-09-22, and nothing reaches it meanwhile -- which is what redirect-only means. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q5nJ8eKEb1wm5tCzxipXHS
Review findings — all five addressedReviewed at
1 — the guard had a hole exactly where the PR claimed to close one
5 — same class, second instanceThe address is a link target and visible text. Reverting only the text: 3 — the emergency command didn't workThe Pages API removes a custom domain only on a JSON 2 — the spec overstated its own gateThe apex is excluded from the liveness test by 4 — self-contradiction in the specThe non-goal said the
|
yellowpine.comis finally in the Porkbun account. This moves the site onto it and turnsyellowpine.devinto the redirect domain, reversing the topology chosen on 2026-09-08 (which parked the site on.devprecisely because.comwas not ours to point anywhere).The defect this closes
The page has advertised
hello@yellowpine.comsince 2026-09-08, in the masthead and again under Get in touch..comwas not ours then, and when it arrived it came carrying the previous owner's Mailgun MX records and zero forwards of ours.Every message sent to the address on the homepage went to servers we do not control. Nothing in the suite caught it, because no test related the contact address to the domain the site is served from.
tests/site.test.mjsnow asserts that relationship. It was written against the live page first, where it failed:and only then was the domain flipped.
What changed
CNAMEyellowpine.dev→yellowpine.comindex.htmlcanonical,og:url,og:site_name. The twomailto:links already said.comand are untouched.tests/site.test.mjsDOMAINflipped; new invariant tying everymailto:toDOMAIN; header renumbered.README.mdpackage.jsondocs/.../2026-09-10-yellowpine-com-apex-design.mdDeploying is rewritten rather than retitled: its reasoning rested on
.devbeing HSTS-preloaded, which made HTTPS free..comis not, so Enforce HTTPS is now something to set rather than assume. The ordering footgun is written down there too — DNS must point at GitHub before the domain lands inCNAME, or validation fails and GitHub never retries.Merge order
DNS for
yellowpine.comis being pointed at GitHub Pages before this merges, so Pages does not register a custom domain whose DNS still resolves elsewhere..devstays fully live until the moment this lands.Known transitional risk, accepted: Pages serves exactly one custom domain, so between this merge and Porkbun issuing a certificate for
yellowpine.dev,.devis dark — and being HSTS-preloaded at the TLD level it hard-fails rather than degrading. The sequence puts that gap on the domain being retired, never on the live one.Tests
npm test— 20/20 with network checks enabled.🤖 Generated with Claude Code
https://claude.ai/code/session_01Q5nJ8eKEb1wm5tCzxipXHS