Building · Building this site

Buy a domain. Keep moving.

Why I started with a deliberately temporary domain, then avoided tying the site to it so I could move to karlconjecture.com without rebuilding.

TL;DR I did not want naming the site to become a project before the project existed. I bought the site's original domain quickly, got the first version moving, and treated the name as replaceable. When Karl Conjecture became the name, I registered karlconjecture.com and moved the public site without rebuilding it. The useful decision was not picking the perfect name early. It was avoiding the coupling that would make changing it painful later.

Names can eat a surprising amount of time.

I wanted to get something registered and start building. I had not settled on the final name, so I bought the site’s original domain at INWX and kept going. It was a purposely quick purchase: good enough to put a real address on the work, without pretending I had made a permanent branding decision.

That gave me something concrete to connect, deploy, test, and look at from my phone. It also moved the naming question out of the way until I had a better answer.

When Karl Conjecture became the name for the platform, I registered karlconjecture.com and moved the public site there. The first domain did not become a mistake just because it was no longer the main address. It had already done its job: it let me begin.

The trick was to delay the final decision without delaying the work. A temporary choice stays temporary only when it is not copied into every file, service, test, and assumption around it.

What actually happened

This is the sequence:

When What I did Result
Before the first repository Registered the site’s original domain at INWX I had a usable address without waiting for the final name
July 18, 2026 Changed its nameservers to the pair assigned by Cloudflare Cloudflare reported the zone active; INWX remained the registrar
July 19, 2026 Corrected the DNSSEC submission The signed delegation chain validated publicly
August 2, 2026 Registered karlconjecture.com through Cloudflare Registrar The long-term name existed without disturbing the running site
After registration Added the karlconjecture domain to the existing Worker The same deployment answered on the new address while the first domain stayed registered

Connect the first domain

Registration and DNS were separate steps even though provider dashboards make them feel like one thing.

I first secured the provider accounts with unique passwords, strong multifactor authentication, an independent recovery email, transfer lock, automatic renewal, and recovery codes stored privately.

Then I connected the original domain to Cloudflare:

  1. Add the domain to Cloudflare.
  2. Review the DNS records instead of assuming the automatic scan found everything.
  3. Copy the two nameservers Cloudflare assigned.
  4. Replace the nameservers at INWX.
  5. Wait for the public delegation to change.
  6. Check the result with tools outside both dashboards.

That matches Cloudflare’s documented full-zone onboarding sequence. Changing the nameservers changed who answered DNS. It did not transfer the registration away from INWX.

DNSSEC was the one snag

The first DNSSEC attempt failed because I supplied the kind of record I expected the INWX form to want, not the kind it actually wanted.

I tried to submit Cloudflare’s DS data directly. INWX rejected it with a DNSKEY validation error. The fix was to give INWX the DNSKEY and let it calculate the digest. Then I checked the signed chain publicly rather than treating either dashboard as proof.

The failed attempt is worth including because the form makes the wrong path easy to choose. The reproducible steps are in the technical section below.

Add the karlconjecture domain without rebuilding

The final-name migration was deliberately boring.

I registered karlconjecture.com through Cloudflare Registrar, opened the existing Worker, and used Settings → Domains & Routes → Add → Custom Domain. Cloudflare’s Workers Custom Domains documentation describes the same flow and confirms that one Worker can have multiple custom domains.

I left the first domain alone while the karlconjecture domain received managed DNS and TLS. The www hostname was handled separately with a proxied placeholder record and a permanent redirect that preserves both the path and query string. The application did not need a second build.

Give the public address one home in the repository

The first implementation had the production URL repeated in configuration, tests, health checks, and workflows. That would turn every future domain change into a search-and-hope exercise.

The repository now keeps the production origin in site.config.mjs. That module derives the HTTP and www variants plus the environment values consumed by Astro, Playwright, build verification, health checks, and deployment jobs. A repository test rejects another copy of the production-origin literal.

That is the kind of coupling worth removing. Internal Worker names, repository names, and other hidden provider identifiers do not need to mirror the public brand. Code should remain name-agnostic unless a provider genuinely requires a concrete value.

Relative internal links and path-preserving redirects complete the move. A visitor following an old deep link should arrive at the corresponding new page, not be dumped at the homepage.

The first domain was not forever. It did not need to be. It got the site moving, and the rest of the system was built so I could make the better decision later.

The nitty-gritty (robots welcome)

Make a temporary domain safely replaceable

Area Practical rule
Registration Record the registrar, renewal state, lock state, recovery route, and domain expiry privately
Accounts Use independent recovery, strong MFA, and recovery material that does not depend on the domain itself
DNS Treat nameserver delegation as a separate change and inventory web, mail, and verification records first
Hosting Attach domains to the deployment rather than baking one hostname into the artifact
Source Keep the public origin in one configuration module and test against duplicate literals
Links Prefer relative internal links and preserve paths and queries through redirects
Migration Run the old and new domains together until DNS, TLS, redirects, and representative routes have been checked

Configure DNSSEC at INWX

  1. In Cloudflare, copy the key-signing DNSKEY value for the zone.
  2. In INWX, choose the DNSKEY form rather than the DS-only form.
  3. Paste the DNSKEY RR value.
  4. Leave the DS field empty.
  5. Leave Auto calculate digest enabled.
  6. Let INWX derive the DS record and submit it to the parent registry.
  7. Verify the signed chain publicly before treating the dashboard status as proof.

INWX describes that preference in its DNSSEC instructions: when the supported type is uncertain, use DNSKEY and let it calculate the digest.

Verify outside the dashboards

After delegation, check that the parent and child agree:

DOMAIN=example.com

dig +short NS "$DOMAIN"
dig +trace "$DOMAIN"
dig +dnssec "$DOMAIN" A

Then test every public entry form with a representative path and query:

DOMAIN=example.com
CHECK_PATH='/example-path?source=check'

curl -I "http://$DOMAIN$CHECK_PATH"
curl -I "https://www.$DOMAIN$CHECK_PATH"
curl -I "https://$DOMAIN$CHECK_PATH"

The evidence should show the intended nameservers, an intact DNSSEC chain when enabled, valid HTTPS, the correct destination, and preservation of the path and query.

If something fails, change one layer at a time: registration, nameserver delegation, authoritative DNS, edge delivery, then the application. Changing several together removes the evidence that tells you which one was wrong.