Skip to content
Vibe Coders

Deploying a Bolt-Generated App to Your Own Domain With Proper DNS

Step by step from Bolt export to live domain. GitHub, Vercel or Netlify, DNS records, SSL, and environment variables, with the stuck points named.

By WitsCode10 min read

You built something in Bolt. It works in the preview window. Your friends saw the StackBlitz URL and said "ship it." The distance between a working Bolt preview and a live app at yourcompany.com is roughly seven stages, and most of those stages have at least one quiet failure mode that will eat an afternoon. This is the map we walk clients through.

The seven stages are export, Git, deploy, DNS, SSL, environment variables, and go-live verification. They run in that order because each one depends on the one before it resolving correctly. You cannot configure DNS before you have a deploy target, cannot provision SSL before DNS resolves, and cannot debug a blank page before environment variables are in place. Skipping ahead is where most people lose a weekend.

Stage one, getting the code out of Bolt cleanly

Bolt runs your project inside a StackBlitz WebContainer, which is a fully functional Node environment running in the browser. That is wonderful for iteration and it is slightly awkward for export. You have two paths. The first is to click the Download button in the top right and get a zip. The second is to use the Connect to GitHub integration inside Bolt, which pushes directly to a new repo on your account.

Prefer GitHub connect when available, because it preserves commit structure and you skip the manual unzip. The stuck point at this stage is that Bolt projects sometimes carry WebContainer-specific artifacts that do not belong in a real repo. Look inside the project before you push. If you see a populated node_modules folder, a .env file at the root with real secret values, or a lockfile from a package manager you did not intend to use, clean those up first. Create a .gitignore that excludes node_modules, .env, .env.local, .DS_Store, dist, .next, and build. Bolt does not always generate a complete gitignore, and the first time you realise it missed one is usually the moment GitHub warns you that you committed an API key to a public repo.

One more check before leaving this stage. Open your env files and look for values auto-filled for the WebContainer sandbox. Bolt sometimes writes VITE_API_URL pointing at a stackblitz.io preview domain. Replace those before deploy, because they get baked into your client bundle.

Stage two, a clean Git push to your own account

If you used GitHub connect in Bolt, you are mostly done with this stage, but verify a few things. Check that the default branch is main, not master, because Vercel and Netlify default to main and a mismatch shows up later as a confusing "no deployments detected" error. Run git status and make sure nothing is staged you did not mean to commit, particularly generated PDFs, sample images, or database dumps that would blow past Git large file limits.

If you zipped and are importing manually, this is where git init, git add, git commit, git remote add origin, and git push -u origin main happen. The stuck point is large binaries. If Bolt generated placeholder assets in the megabyte range, Git will accept the push and Vercel will pull it, but your repo is now permanently bloated. Prune before you push.

Stage three, importing into Vercel or Netlify

Pick one. Vercel tends to be the smoother default for Next.js, Remix, Astro, and Vite apps. Netlify is strong for SvelteKit and static sites and has a slightly more generous free tier for bandwidth. The import flow is similar in both. You authorize the platform to read your GitHub account, you pick the repo, and the dashboard tries to auto-detect your framework.

This is where a real stuck point lives. Vercel's framework detector is good, but it is not perfect, and it has a bias toward assuming Next.js. If you built a Vite app in Bolt, sometimes Vercel detects it correctly and sometimes it does not. When it does not, your build succeeds, the deploy reports green, and you visit the URL and get a 404 on the root path. The reason is that the output directory in the project settings is wrong. Vite writes to dist. Next writes to .next, which Vercel handles specially. Remix writes to build. If the publish directory does not match what the framework actually produces, Vercel serves nothing from the right place and you see nothing. Open project settings, go to Build and Output Settings, and manually set the output directory to match your framework.

Node version is the second pitfall at this stage. WebContainer runs Node 20 under the hood, and Vercel now defaults to Node 22 for new projects. Most apps are fine either way, but some packages pinned to specific Node minor versions will error out during install. If your build fails with a peer dependency warning about Node, pin your engine version in package.json under the engines field, and set the same version in your platform's project settings.

Stage four, the DNS stage where most people actually get stuck

Your app is now live at something like yourapp.vercel.app or yourapp.netlify.app. You want it at yourapp.com. This is the stage where people who are fluent in JavaScript suddenly feel like they are reading a different language, because DNS has its own vocabulary and its own historical quirks, and one of those quirks will get you if you do not know about it.

You need to point two hostnames at your deploy. The apex, which is yourapp.com with nothing in front, and the www subdomain, which is www.yourapp.com. The subdomain is easy. You add a CNAME record on www that points to your Vercel or Netlify target, which will be something like cname.vercel-dns.com or yourapp.netlify.app. The apex is where it gets awkward.

The DNS specification forbids CNAME records at the apex of a zone. You cannot write a CNAME for yourapp.com itself. You can only write an A record, which needs a literal IP address. The problem is that platforms like Vercel do not want to give you a literal IP address, because they reserve the right to move their load balancers around. The industry workaround is a record type called ALIAS, sometimes called ANAME or CNAME flattening, which behaves like a CNAME but is legal at the apex because the DNS server resolves it to an A record before answering the query.

Not every registrar supports ALIAS. Cloudflare does, through its CNAME flattening feature. DNSimple does. Netlify DNS does. Vercel's own nameservers do. GoDaddy's default DNS does not. Namecheap's basic DNS does not. Google Domains, which has been migrated to Squarespace Domains, has inconsistent support. If your registrar supports ALIAS, use it. Write an ALIAS record on the apex pointing to cname.vercel-dns.com or your Netlify target, write a CNAME on www pointing to the same target, and you are done.

If your registrar does not support ALIAS, you have two options. The cleaner option is to transfer DNS to a provider that does, most commonly by changing your nameservers to Cloudflare, which is free and takes about ten minutes to set up. The faster option is to use a plain A record on the apex pointing to your platform's documented IP address. Vercel publishes 76.76.21.21 for this purpose. Netlify has its own documented load balancer IP. This works, but if the platform ever changes that IP, your site goes down until you update the record, and you will not get a warning.

One more stuck point on DNS. Check for lingering A records from whoever was hosting this domain before. If you previously parked the domain on GoDaddy's builder, or if a predecessor had it pointed at a WordPress host, there is probably an old A record still there. DNS does not override records by type silently. You must delete the stale ones. And keep your TTL low, 300 seconds or less, while you are actively changing things. A 24 hour TTL means you will spend a whole day thinking your fix did not work.

Stage five, SSL certificates and the propagation delay that feels like a bug

Once your DNS resolves correctly, Vercel and Netlify both attempt to provision a Let's Encrypt certificate automatically. You do not need to do anything for this step in the normal case. The platform asks Let's Encrypt for a cert, Let's Encrypt runs a challenge against your domain, the challenge passes because DNS points at the platform, and a cert appears within a few minutes.

The first stuck point is CAA records. A CAA record is a DNS record that restricts which certificate authorities are allowed to issue certs for your domain. If a previous host set a CAA record pinning Sectigo or DigiCert, Let's Encrypt cannot issue a cert and your SSL will silently fail to provision. The error message on the dashboard is usually cryptic. Check your DNS zone for CAA records, and either remove them or add an entry for letsencrypt.org.

The second stuck point is propagation timing, which is less of a real problem and more of a psychological one. DNS propagation is sometimes described in hours, and SSL provisioning can take anywhere from thirty seconds to a couple of hours on top of that. The platform will tell you it is working on it. Most people refresh every ninety seconds, conclude something is broken after five minutes, start changing settings, and end up in a state where they cannot tell whether the problem is real or whether they just interrupted the process. Set a timer for thirty minutes. Do not touch anything until the timer goes off. If it is still broken after thirty minutes, then start debugging. Nine times out of ten, waiting alone resolves it.

The third stuck point is mixed content. Your cert is fine, your domain is live over HTTPS, and then your app loads and half the images are broken. Open the browser console. If you see mixed content warnings, it is because your Bolt code has hardcoded http:// URLs somewhere, usually in an API base URL or an image CDN reference. Change them to https:// or to protocol-relative URLs.

If you are staring at DNS entries and an SSL dashboard and wishing someone else would do this, that is the moment to book a WitsCode deployment setup. We do this every working day. Book here --> https://witscode.com/book

Stage six, environment variables, where leaks happen

Your app needs secrets. API keys, database URLs, OAuth client secrets. Bolt let you store these in an env file and read them with a VITE_ or NEXT_PUBLIC_ prefix, because that is what makes them work in the browser during development. The production problem is that the same prefix convention determines what is safe to ship.

Any variable that starts with VITE_, NEXT_PUBLIC_, PUBLIC_, or REACT_APP_ is bundled into the JavaScript that runs in the user's browser. Anyone who loads your app can read those values from the network tab. That is fine for things like a Supabase anon key, a Stripe publishable key, a PostHog project key, or a public Google Maps API key with a domain restriction. It is a disaster for anything labeled secret. If Bolt helpfully renamed your STRIPE_SECRET_KEY to NEXT_PUBLIC_STRIPE_SECRET_KEY so it would work in the preview, and you copy that straight into your Vercel dashboard, you have just published your Stripe secret to the public internet. Every Bolt-to-production migration should include an audit of your env var names. Strip the public prefix off anything that should never leave the server.

Server-side secrets go in without a prefix and are only available in API routes, server components, middleware, and build scripts. Set them at the project level in your platform's dashboard. Vercel and Netlify both let you scope variables to production, preview, and development environments. Set them on all three, or accept that preview deploys will crash.

Two more real stuck points. First, Vercel aggressively caches build output. If you update an environment variable and click Redeploy, Vercel will happily reuse cached build artifacts that were compiled with the old values, which means the new variable appears to not take effect. Use the Redeploy without cache option, or push a trivial commit to force a fresh build. Netlify has a similar cache, with a similar solution in Deploys, Options, Clear cache and deploy site. Second, multiline environment variables, typically private keys for Firebase admin or signing certs, need either escaped newline sequences or base64 encoding to survive the form field. If you paste a PEM into the dashboard and the newlines vanish, your app will error out at runtime trying to parse it.

Stage seven, verifying you are actually live

Open an incognito window. Load your domain over HTTPS. Open the console. Check for red errors. Open the network tab. Check that your API calls are hitting the right host and returning two hundreds. If you have OAuth, try the full login flow, because the most common post-deploy bug is that your Google or GitHub OAuth app still has the StackBlitz preview URL in its allowed redirect URIs list. Update those to your real domain on both the provider side and anywhere your code references them.

Check CORS. If your backend is Supabase, Firebase, or a separate API, add your production domain to the allowlist. Localhost was probably in there from development, and your new custom domain is probably not.

Run Lighthouse. Not for the score as such, but because it will flag any mixed content, any missing meta tags, and any obvious accessibility regressions that slipped through. Set up at least a basic uptime check, either through Vercel and Netlify's built-in analytics or through something like UptimeRobot, so you find out your site is down before your users do.

Where WitsCode fits

If you read all of this and thought "that is more operations than I signed up for when I opened Bolt," you are not alone, and that is precisely the gap we work in. We are the last mile developer for vibe coders. You prototype in Bolt, Lovable, or v0, and we take over at stage one and deliver you a live app at your own domain with DNS, SSL, environment variables, CI, and monitoring wired up correctly the first time.

A typical Bolt-to-production engagement is two to five working days. You keep ownership of the repo, the domain, and every account involved. Book a deployment setup here --> https://witscode.com/book

Get weekly field notes.

Practical writing on shipping products, straight to your inbox. No spam.

Need help with this?

MVP Development

We design and build web apps, MVPs, and SaaS products. Talk to us about what you are working on.

Talk to us

Want to discuss vibe coders for your business?

Start a project and we'll talk through where you are, what's working, and the highest-leverage moves for the next 90 days.