Skip to main content
MindStudio
Pricing
Blog About
My Workspace

How to Deploy a Web App: A Beginner's Guide to Going Live

A step-by-step guide to deploying a web app — covering hosting options, environment variables, custom domains, and what to check before launch.

MindStudio Team RSS
How to Deploy a Web App: A Beginner's Guide to Going Live

Getting Your App Off Your Machine and Into the World

You’ve built a web app. It runs locally. You’re happy with it. And now you’re staring at the question that stops a lot of first-timers cold: how do I actually deploy this thing?

Deployment is the process of taking your application from your local machine and putting it somewhere that anyone on the internet can access. It sounds simple, but it involves more moving parts than most tutorials cover — hosting, environment variables, databases, domains, and a checklist of things that will silently break if you don’t handle them before launch.

This guide covers all of it. Step by step, from choosing a hosting platform to going live with a custom domain. Whether you’re deploying a full-stack app with a backend and database, or a simpler frontend project, you’ll find what you need here.


What “Deploying a Web App” Actually Means

When you run your app locally, your computer is the server. The app is only accessible at localhost:3000 (or wherever your dev server runs), which means only you can see it.

Deployment moves that process to a remote server — a computer somewhere in the cloud that’s always on and accessible via a public URL. When someone types your domain into a browser, their request hits that server, which runs your app and sends back a response.

There are different deployment models depending on what kind of app you have:

  • Static sites — Only HTML, CSS, and JavaScript. No server-side logic. Can be hosted almost anywhere for free.
  • Server-rendered apps — The server processes requests and generates HTML dynamically (e.g., Next.js, Express, Django). Needs a platform that runs a Node/Python/other process.
  • Full-stack apps — A frontend, a backend API, and a database, all working together. Requires more planning around how each layer gets deployed and how they connect.

Most modern web apps fall somewhere between the second and third category. That’s what this guide focuses on.


Step 1: Choose a Hosting Platform

This is the first real decision. Your choice here affects everything else — pricing, configuration, and how much you need to manage yourself.

PaaS platforms handle the server infrastructure for you. You push code; they run it.

Vercel is the most popular choice for frontend and full-stack JavaScript apps. It integrates directly with GitHub, auto-deploys on every push, and handles edge functions and serverless backends. It’s free to start. If you’re using Next.js, Vercel is the obvious default.

Railway is a good option for apps that need a persistent backend process. It supports any language, includes managed databases, and has a clean deployment experience with minimal config.

Render is similar to Railway — supports web services, cron jobs, and managed databases. Slightly more generous on free tier limits.

Fly.io lets you deploy Docker containers close to your users. More control than Vercel or Railway, but a steeper learning curve.

Infrastructure-as-a-Service (IaaS) — For Later

AWS, Google Cloud, and Azure give you raw VMs and services. They’re powerful but overkill when you’re just getting started. You’ll spend more time configuring than building. Come back to these when you have specific needs PaaS can’t meet.

What to Pick

If you’re deploying a Next.js or React app: Vercel.
If you need a real backend process (Express, FastAPI, Rails): Railway or Render.
If you want full control and are comfortable with containers: Fly.io.

The right platform also depends on what tools you used to build your app. If you built with a full-stack AI builder — the kind compared in this breakdown of Bolt, Lovable, Replit, and more — some of them have built-in deployment. Replit deploys to its own infrastructure. Lovable deploys to Netlify. Bolt exports code you can deploy wherever you want.


Step 2: Prepare Your App for Deployment

This is where most first-timers hit problems. Running locally is forgiving. Production is not.

Set Up Environment Variables

Never hardcode API keys, database credentials, or secrets into your code. Instead, use environment variables — values that live outside your codebase and get injected at runtime.

Locally, these live in a .env file:

DATABASE_URL=postgresql://user:password@localhost:5432/mydb
API_KEY=sk_live_abc123

Your .env file should be in .gitignore. It never gets committed to version control.

In production, you set these variables through your hosting platform’s dashboard or CLI. Every platform (Vercel, Railway, Render) has a section for environment variables in your project settings. You’ll paste in each key-value pair manually.

Common environment variables to set:

  • DATABASE_URL — connection string for your database
  • NODE_ENV=production — tells your app to run in production mode
  • SECRET_KEY or JWT_SECRET — used for auth and session signing
  • Any third-party API keys (Stripe, SendGrid, etc.)

Run a Production Build

Most frontend frameworks need to be built before deployment. Development servers serve code in a way that’s readable but slow. Production builds minify and optimize everything.

For a Vite + React app:

npm run build

This generates a dist/ folder with your static assets. That’s what gets served in production.

For Next.js:

npm run build

For a Node.js backend, you may not need a build step — just make sure your start command points to the right file (node server.js or similar).

Check Your Start Command

Your hosting platform needs to know how to start your app. This is usually defined in your package.json:

"scripts": {
  "start": "node server.js",
  "build": "vite build"
}

Make sure this is correct and actually works when you run it locally.

Make Sure Your Database Is Production-Ready

A local SQLite file or local Postgres instance won’t work in production. You need a managed database that your deployed app can connect to over the network.

Options include:

  • Supabase — managed Postgres with a generous free tier. See our guide on what Supabase is and how it works if you’re not familiar with it.
  • PlanetScale — serverless MySQL, scales well
  • Railway’s managed Postgres — easiest if you’re already using Railway
  • Neon — serverless Postgres with branching

If you’re starting from scratch, our guide on how to set up a managed database for your web app walks through the full setup process. Once your database is live, copy the connection string and add it as your DATABASE_URL environment variable.

Run Any Migrations

If your app uses a schema-based database with migrations (Prisma, Drizzle, Alembic, etc.), you need to run those migrations against your production database before your app can start.

Most platforms let you define a release command that runs before deployment completes:

npx prisma migrate deploy

Don’t forget this step. If your app starts before migrations run, it will crash or behave unpredictably.


Step 3: Connect Your Code Repository

Almost every PaaS platform works by connecting to your GitHub (or GitLab/Bitbucket) repository. Once connected, every push to your main branch triggers a new deployment automatically.

Here’s the basic flow for Vercel as an example:

  1. Go to vercel.com and sign in with GitHub.
  2. Click “Add New Project” and import your repository.
  3. Vercel detects your framework automatically and sets the build command.
  4. Add your environment variables.
  5. Click Deploy.

That’s it for the initial deployment. After that, every git push origin main redeploys automatically.

For Railway:

  1. Create a new project and choose “Deploy from GitHub repo.”
  2. Select your repository.
  3. Set environment variables.
  4. Railway detects your start command and builds.

The pattern is the same across platforms. The main variation is how you set environment variables and what commands you need to configure.


Step 4: Add Authentication (If Your App Needs It)

If your app has user accounts, you need auth set up before going live. Auth is one of those things that’s easy to get wrong, and the consequences of getting it wrong (exposed user data, broken sessions) are serious.

Popular options:

  • Clerk — managed auth with React/Next.js SDKs, easiest to drop in
  • Auth.js (NextAuth) — free, open source, good for Next.js
  • Supabase Auth — if you’re already using Supabase for your database, auth is built in
  • Firebase Auth — solid if you’re on the Firebase stack

Our guide on how to add authentication to your web app covers the setup in detail for several of these options.

The key thing for deployment: make sure your auth callbacks and redirect URLs are updated to point to your production domain, not localhost. This is a very common launch-day mistake.


Step 5: Set Up a Custom Domain

Your app is probably live at something like my-app.vercel.app or my-app.up.railway.app. That’s fine for testing, but you’ll want a custom domain for anything real.

Buy a Domain

Buy a domain from a registrar. Common ones: Namecheap, Cloudflare Registrar (cheapest renewal prices), Google Domains (now Squarespace Domains), or GoDaddy. .com domains run $10–15/year. .io domains are $40–60/year.

Point Your DNS

Once you have a domain, you need to point its DNS records to your hosting platform. Your platform will give you specific instructions, but the general pattern is:

  1. Add your custom domain in your platform’s dashboard.
  2. The platform gives you either an IP address (A record) or a hostname (CNAME record).
  3. Go to your registrar’s DNS settings and add that record.
  4. DNS changes take a few minutes to a few hours to propagate.

For Vercel: add the domain in your project settings, and Vercel walks you through the exact DNS records to add.

HTTPS Is Automatic

All major platforms provision SSL certificates automatically via Let’s Encrypt. You don’t need to buy or configure a certificate manually. Once your DNS is pointed correctly, HTTPS just works.


Step 6: Pre-Launch Checklist

Before you share your app with anyone, go through this list. These are the things that commonly break in production but work fine locally.

Environment variables

  • All required env vars are set in your platform’s dashboard
  • No keys are hardcoded in the codebase
  • NODE_ENV is set to production

Database

  • Connected to a production database, not localhost
  • Migrations have been run
  • Seeding (if needed) is done

Auth

  • Redirect URLs updated to production domain
  • Callback URLs updated in your auth provider’s dashboard
  • OAuth apps (Google, GitHub login, etc.) have production URLs added

API and external services

  • Third-party API keys are production keys (not test/sandbox)
  • Webhooks point to your production URL
  • CORS settings allow your production domain

Frontend

  • Production build completes without errors
  • No localhost hardcoded anywhere in frontend code (use environment variables for API base URL)
  • Favicon and meta tags are set

Performance and errors

  • Error tracking set up (Sentry is free to start)
  • Basic logging in place on the backend
  • Test the app end-to-end on the live URL before announcing

Step 7: Monitor After Launch

Deployment isn’t a one-time event. Once your app is live, you need to know when it breaks.

Error monitoring — Sentry is the standard here. It catches unhandled exceptions, groups them, and alerts you. Free tier is sufficient for most indie projects.

Uptime monitoring — Services like Better Uptime or UptimeRobot ping your app every few minutes and notify you if it goes down. Both have free plans.

Logs — Check your platform’s log viewer after deployment. If something is broken, the error will be there.

Database metrics — If you’re using Supabase or PlanetScale, their dashboards show query performance and connection counts. Keep an eye on these as traffic grows.


How Remy Handles Deployment

If you’re building with Remy, the deployment step is already handled. Apps deploy on every push to the main branch and are immediately live on a real URL. There’s no separate “configure your build command” step, no “add environment variables to the dashboard” dance, no provider account to set up.

Remy generates a full-stack app — backend, database, auth, frontend — and the infrastructure that runs it is managed for you. Your database is a real SQL database (SQLite with WAL journaling and automatic schema migrations). Auth is real auth with verification codes and sessions. The backend is real TypeScript running in Node.

The spec you write is the source of truth. If you need to change something, you update the spec and recompile — you don’t manually edit build configs or restart servers. It’s a different starting point than the traditional deploy flow entirely. You can try Remy at mindstudio.ai/remy to see how it compares to the manual process described in this guide.

If you’ve been using one of the AI-assisted builders to get to this point — something like Bolt or Lovable — and you’re now trying to figure out where to host the exported code, the steps above apply to you directly.


Frequently Asked Questions

What is the easiest way to deploy a web app?

For a frontend-only or Next.js app, Vercel is the easiest option. Connect your GitHub repo, add environment variables, and click deploy. For full-stack apps with a separate backend, Railway or Render are similarly beginner-friendly. If you want everything handled including database and auth, Remy handles deployment as part of the build process.

How much does it cost to deploy a web app?

Most platforms have free tiers that work for small projects and MVPs. Vercel’s Hobby plan is free. Railway and Render both offer free tiers with usage limits. Managed databases like Supabase have free plans up to 500MB. As traffic grows, costs typically range from $5–20/month for a small production app. At scale, the numbers depend heavily on usage.

What should I do with my .env file when deploying?

Never commit your .env file to version control. Add it to .gitignore. Instead, enter each environment variable manually in your hosting platform’s dashboard (Vercel, Railway, Render all have a settings section for this). If you’re using a team, a secrets manager like Doppler or 1Password Secrets can help keep things in sync.

Why does my app work locally but break in production?

The most common causes are:

  • Missing environment variables in the production config
  • Hardcoded localhost URLs in the frontend
  • Auth redirect URLs pointing to localhost instead of the production domain
  • Database migrations not run against the production database
  • Using a local database file instead of a managed database

Go through the pre-launch checklist above systematically. The error logs in your hosting platform’s dashboard will usually point to the exact problem.

Do I need a custom domain?

Not to get started. Your platform gives you a free subdomain (yourapp.vercel.app) that works fine for testing and early users. A custom domain makes your app feel more professional and is worth the $10–15/year if you’re sharing it publicly or pitching to anyone.

How do I deploy a database with my app?

Your local database doesn’t move to production with your code. You need a separate managed database in the cloud. Supabase and Firebase are two popular options, each with different tradeoffs. Once your managed database is running, copy the connection string and add it as an environment variable in your hosting platform. Then run your migrations before the app starts.


Key Takeaways

  • Deployment is the process of running your app on a remote server that’s publicly accessible. It’s more than uploading files.
  • Choose your hosting platform based on what your app needs: Vercel for frontend/Next.js, Railway or Render for full-stack backends.
  • Environment variables are the most common source of production bugs. Set them correctly in your platform’s dashboard — never hardcode them.
  • Your production database needs to be a managed cloud database, not a local file or localhost instance.
  • Update auth redirect URLs and OAuth app settings to use your production domain before launch.
  • Custom domains are cheap and worth doing for any app you’re sharing publicly.
  • Set up error tracking and uptime monitoring after launch — not as an afterthought.

If you want to skip most of this setup, try Remy. It handles the full stack — including deployment — from a spec you write in plain English. For those curious about how that approach compares to traditional full-stack development, spec-driven development is worth understanding. And if you’re weighing what backend platform to build on before you deploy, the best backend platforms for indie hackers is a useful comparison.

Presented by MindStudio

No spam. Unsubscribe anytime.