Custom Domain and HTTPS After the Agent Deploys to a Default URL
Devon Walsh
September 30, 2026
I launched a side project on a URL that looked like a Wi-Fi password. Something like shelfie-k3x9q.platform.app. The agent had deployed it, the app worked, and I was impatient, so I posted that link in two communities and a newsletter. A few hundred people signed up in the first week. Then I bought shelfie.club for eleven dollars and spent a Saturday learning that “add a custom domain” is one button and about fourteen follow-up tasks.
Shelfie is a tiny app for tracking which board games your friends own so you stop buying duplicates. It has login, a Stripe checkout for a small annual plan, email invites, and a public profile page per shelf. None of that is complicated. All of it, it turned out, knew the old URL.
If you are about to move an agent-built app from its default platform URL to a real domain, here is what I wish I had on a checklist, in the order it bit me.
The button part, which is genuinely easy
Every modern host makes the first step simple. You add the domain in the dashboard, and it tells you which DNS records to create. For a subdomain like www or app, that is usually a CNAME pointing at the platform. For the bare domain, the apex, you typically get either an A record with an IP address, or instructions to use your DNS provider’s ALIAS, ANAME, or CNAME flattening feature, because the DNS standard does not allow a plain CNAME at the apex.
Once DNS resolves, the platform requests a certificate, usually from Let’s Encrypt, and within a few minutes https://shelfie.club loads. I refreshed it, saw the padlock, and thought I was done.
I was not done. I had moved the front door. I had not told anything inside the house.

Everything the agent had hard-coded
I asked the agent to search the codebase for the old hostname. It found it in nine places. Some were in environment variables, which was fine. Others were written directly into the code, because during development the agent had needed an absolute URL and used the only one that existed.
Login callbacks. “Sign in with Google” failed immediately on the new domain with a redirect URI mismatch. The OAuth app in Google’s console only had the old URL registered, and the auth library’s base URL was set to the old hostname. Both needed updating, and I needed to keep the old callback registered temporarily so that people mid-login did not get stranded.
Session cookies. The cookie domain was not set explicitly, so cookies from the old URL simply did not exist on the new one. Everybody was logged out. That is expected when changing domains, but I had not warned anyone, and three people emailed to say their account had been deleted.
Email links. Invite emails and password resets were built with a hard-coded base URL. For two days after the switch, invites sent people to the old domain. Those still worked, which is the only reason it did not become a crisis, but it meant new users were signing up on the old URL and getting a cookie there instead of on the new one.
The Stripe webhook. Stripe sends payment events to an endpoint you register. Mine was the old URL. The old URL still worked, so webhooks still arrived, which was fine until I added a redirect from the old domain to the new one. Stripe does not follow redirects for webhooks. The next subscription payment was charged, but my app never heard about it. I found it the next morning in the Stripe dashboard as a string of failed deliveries.
CORS. A small public API used by an embed widget had an allowlist of origins. The agent had written the old hostname into it. The widget broke on every site that embedded it the moment the page loaded from the new domain.
Canonical tags, the sitemap, and Open Graph images. All pointed at the old hostname. Search engines were being told the new domain’s pages were duplicates of the old one, and link previews on social media showed the old URL.
None of these were bugs in the usual sense. The agent had done exactly what I asked during development. It just had no concept of “this URL is temporary.” Neither, apparently, did I.
The HTTPS part that is not a button
Two separate HTTPS problems cost me about three hours.
The redirect loop. My domain’s DNS was on Cloudflare, and I had left the orange-cloud proxy turned on, with Cloudflare’s SSL mode set to “Flexible.” In that mode, Cloudflare talks to the visitor over HTTPS but to the origin over plain HTTP. The platform, correctly, redirects HTTP to HTTPS. So Cloudflare requested HTTP, got redirected to HTTPS, passed that redirect to the browser, and the browser asked Cloudflare again. Infinite loop. The fix was to set the SSL mode to “Full (strict)”, or to turn off the proxy for that record and let the platform handle TLS directly. I chose the second, because I did not need two layers of proxy for a board game app.
The certificate that would not issue. The www subdomain worked, but the apex sat at “certificate pending” for an hour. The cause was a CAA record I had forgotten about, left over from a previous project on the same registrar, which only allowed a different certificate authority to issue certificates for the domain. The platform uses Let’s Encrypt, and the CAA record said no. Deleting it, or adding Let’s Encrypt to it, fixed things within minutes.
Neither of these was the agent’s fault. But I mention them because when you ask an agent to “set up the custom domain,” it can only change what it can reach, which is usually the code and maybe the platform config. It cannot see your DNS provider’s proxy mode or a CAA record from 2023. Those are yours to check.

Keeping the old URL alive, on purpose
My first instinct was to kill the default URL immediately so there would be one canonical address. That broke the webhook and would have broken every link I had posted during launch week.
What I do now is treat the default URL like an old postal address. Keep it working, redirect it, and update senders one at a time.
- Redirect page views from the old domain to the new one with a permanent 301, preserving the path, so every shared link still lands in the right place.
- Do not redirect webhooks or API calls. Update every external service to the new URL first. Only then add the redirect, or exclude
/api/and webhook paths from it. - Keep old OAuth callbacks registered for a couple of weeks after the switch.
- Tell users they will be logged out once. A one-line banner the week before would have saved three worried emails.
The checklist I use now
For every project since Shelfie, I ask the agent to do the code half and I do the account half. It takes about an hour when done in order.
- One variable for the public URL. Before launch, ask the agent to replace every hard-coded hostname with a single
PUBLIC_URLenvironment variable, and to search the whole codebase, including email templates, config files, and tests, to confirm none remain. Do this before you even have a domain. - List external services that know the URL. OAuth providers, payment webhooks, email provider domain settings, analytics, error tracking, uptime monitors, and any embed or API allowlists. Write them down.
- Check DNS for surprises. Existing CAA records, proxy settings, old records pointing somewhere else.
- Add the domain and wait for the certificate on both the apex and
www, and decide which one is canonical. - Update the variable and redeploy. Now canonical tags, sitemaps, emails, and cookies all use the new domain.
- Update every external service from the list in step two. Test one webhook delivery by hand.
- Only then, redirect the old URL, excluding API and webhook paths until you are sure nothing still calls them.
- Set up email authentication for the new domain (SPF, DKIM, and DMARC) if the app sends email from it. Otherwise your invites go to spam.
Step one is the one that matters most, and it is the one you can do today even if you have not bought a domain. The agent is very good at “replace every instance of this string with a variable.” It is not good at knowing, on its own, that a string is temporary.
Was it worth it?
For Shelfie, absolutely. Signups from word of mouth went up noticeably once people could say the name out loud without spelling a random suffix. The Stripe payment that went missing was recovered by replaying the webhook from the dashboard. The three people who thought their accounts had been deleted are still subscribers.
But I would not launch on the default URL again. Not because it is bad, since it is a perfectly good address for testing, but because every day you run on it, more things learn it. Every shared link, every registered callback, every email in someone’s inbox. Moving later is not hard. It is just long, and most of the length comes from everything the agent and I wrote down in the meantime without realising it would need to change.