Skip to content

How to Deploy Claude-Coded Web Apps: Hosting Options for Beginners

The Problem: My App Only Works on My Laptop

I built a todo app with Claude. It worked great locally. I typed python app.py and opened localhost:5000 in my browser. Everything functioned perfectly.

Then I wanted to share it with my friend.

I sent him the GitHub link. He cloned it, ran python app.py, and got:

Error message
ModuleNotFoundError: No module named 'flask'

Then he asked: “Why do I need to run commands? Can’t I just open it like a normal website?”

That’s when I realized the fundamental gap. Claude helped me write code that runs on my machine. But making it accessible to others? That’s a completely different problem.

What Deployment Actually Means

When you build a web app locally, it lives on your computer. Only you can access it through localhost. Deployment means putting your app on a server that’s connected to the internet 24/7, so anyone can visit it through a URL.

The confusion I had: I thought GitHub was deployment. I pushed my code to GitHub and assumed people could now “use” my app. But GitHub only stores your code. It doesn’t run it.

To make your app accessible, you need a hosting platform.

Choosing the Right Hosting Platform

Not all apps are the same. Your hosting choice depends on what you built:

Static Sites (HTML, CSS, JavaScript files only):

  • Vercel
  • Netlify
  • GitHub Pages
  • Cloudflare Pages

Full-Stack Apps (Frontend + Backend):

  • Vercel (serverless functions)
  • Railway
  • Render
  • Fly.io

Backend-Heavy Apps (APIs, databases):

  • Supabase
  • Railway
  • Render
  • AWS (overkill for beginners)

I started with a simple static site to understand the basics.

Static Site Deployment: The Easy Path

My first deployable app was a simple landing page. Three files: index.html, styles.css, and script.js. No server, no database, just files.

Option 1: Netlify Drag-and-Drop

The simplest method I found:

  1. Go to netlify.com and create a free account
  2. Navigate to “Sites” section
  3. Drag your project folder onto the page

That’s it. Netlify gave me a URL like random-name-12345.netlify.app.

The entire process took 30 seconds. No configuration files, no commands, no Git required.

Option 2: Vercel CLI

I wanted to try Vercel because I heard it integrates well with React and Next.js. Here’s what I did:

Install Vercel CLI
npm install -g vercel
Deploy to Vercel
cd my-static-site
vercel

Vercel asked me a few questions:

Vercel deployment questions
? Set up and deploy "~/my-static-site"? [Y/n] Y
? Which scope do you want to deploy to? my-username
? Link to existing project? [y/N] N
? What's your project's name? my-static-site
? In which directory is your code located? ./
? Want to modify these settings? [y/N] N

After answering, Vercel deployed my site to my-static-site.vercel.app.

Why These Platforms Work for Static Sites

Static sites are just files. When someone visits your URL, the server sends these files to their browser. The browser does all the work. No server processing needed.

This makes deployment straightforward: upload files, get URL.

Full-Stack App Deployment: Adding Complexity

My todo app was different. It had:

  • A Python Flask backend
  • A SQLite database
  • API endpoints for CRUD operations

Static hosting wouldn’t work here. I needed a platform that could run Python code.

The Problem with Traditional Hosting

I first tried a traditional VPS (Virtual Private Server). I rented a $5/month Droplet from DigitalOcean.

The setup process involved:

Initial server setup
ssh root@my-server-ip
apt update
apt install python3 python3-pip nginx
pip3 install flask gunicorn

Then I needed to:

  • Configure Nginx as a reverse proxy
  • Set up a systemd service to keep the app running
  • Configure the firewall
  • Set up SSL certificates with Let’s Encrypt
  • Manage environment variables

This was overwhelming. Each step introduced new problems. I spent an entire weekend on this and still had issues.

Platform-as-a-Service: The Better Option

PaaS platforms handle all the server management. You just push code, they handle the rest.

Vercel with Serverless Functions

Vercel supports serverless functions. These are functions that run only when called, then shut down. Perfect for small backends.

I converted my Flask app to a Vercel-compatible structure:

Project structure for Vercel
my-todo-app/
├── api/
│ └── todos.py
├── static/
│ ├── index.html
│ └── script.js
└── vercel.json

The api/todos.py file:

api/todos.py - Vercel serverless function
from flask import Flask, jsonify, request
import sqlite3
app = Flask(__name__)
def get_db():
conn = sqlite3.connect('todos.db')
conn.row_factory = sqlite3.Row
return conn
@app.route('/api/todos', methods=['GET'])
def get_todos():
db = get_db()
todos = db.execute('SELECT * FROM todos').fetchall()
return jsonify([dict(todo) for todo in todos])
@app.route('/api/todos', methods=['POST'])
def add_todo():
data = request.json
db = get_db()
db.execute('INSERT INTO todos (text) VALUES (?)', (data['text'],))
db.commit()
return jsonify({'status': 'success'})

The vercel.json configuration:

vercel.json - Vercel configuration
{
"version": 2,
"builds": [
{
"src": "api/**/*.py",
"use": "@vercel/python"
}
],
"routes": [
{
"src": "/api/(.*)",
"dest": "/api/$1"
},
{
"src": "/(.*)",
"dest": "/static/$1"
}
]
}

Deployed with:

Deploy full-stack app to Vercel
vercel --prod

Vercel automatically detected the Python files and set up the serverless environment.

Railway: Simpler Alternative

Railway felt more intuitive for Python apps. I didn’t need to restructure my project.

My original structure worked:

Original Flask project structure
my-todo-app/
├── app.py
├── requirements.txt
├── static/
│ ├── index.html
│ └── script.js
└── templates/

I created a requirements.txt:

requirements.txt
flask==3.0.0
gunicorn==21.2.0

Then a Procfile (tells Railway how to start the app):

Procfile
web: gunicorn app:app

Deployment via Railway CLI:

Deploy to Railway
npm install -g @railway/cli
railway login
railway init
railway up

Railway detected the Flask app, installed dependencies, and deployed. It even set up a PostgreSQL database when I needed to upgrade from SQLite.

The Database Problem

SQLite worked locally but caused issues in deployment:

  1. Serverless functions (Vercel) can’t persist files between runs
  2. Container-based hosting (Railway, Render) resets the filesystem on each deploy

I needed a separate database service.

Solution: Managed Databases

For Railway, I added PostgreSQL directly:

Add PostgreSQL to Railway project
railway add --plugin postgresql

Railway gave me a DATABASE_URL environment variable. I updated my code:

Using PostgreSQL in Flask
import os
from flask import Flask
import psycopg2
app = Flask(__name__)
def get_db():
database_url = os.environ.get('DATABASE_URL')
return psycopg2.connect(database_url)
@app.route('/api/todos', methods=['GET'])
def get_todos():
conn = get_db()
cur = conn.cursor()
cur.execute('SELECT * FROM todos')
todos = cur.fetchall()
conn.close()
return jsonify(todos)

This change solved the persistence problem. The database lived separately from the app, so redeployments didn’t lose data.

Environment Variables: Handling Secrets

My app needed an API key for a third-party service. I initially hardcoded it:

DON'T DO THIS
api_key = "sk-proj-xxxxx" # Never commit this!

This worked, but when I pushed to GitHub, my API key was public. Anyone could use it.

The fix: environment variables.

On Railway:

Set environment variable in Railway
railway variables set API_KEY=sk-proj-xxxxx

In my code:

Access environment variable
import os
api_key = os.environ.get('API_KEY')
if not api_key:
raise ValueError('API_KEY environment variable not set')

This keeps secrets out of the codebase.

Domain Names: The Final Touch

Free hosting platforms give you URLs like my-app-xyz123.vercel.app. These work, but they’re not memorable.

I bought a domain for $12/year from Namecheap.

Connecting Custom Domain to Vercel

  1. Go to project settings in Vercel dashboard
  2. Click “Domains”
  3. Add your domain (e.g., myapp.com)
  4. Vercel provides DNS records to add

In Namecheap, I added the records:

DNS configuration
Type: A
Host: @
Value: 76.76.21.21
TTL: Automatic
Type: CNAME
Host: www
Value: cname.vercel-dns.com
TTL: Automatic

After DNS propagation (took about 30 minutes), my app was accessible at myapp.com.

Common Deployment Errors I Encountered

Error 1: Build Fails - Missing Dependencies

Build error
ModuleNotFoundError: No module named 'flask-cors'

I forgot to add flask-cors to requirements.txt. Fixed by:

Updated requirements.txt
flask==3.0.0
flask-cors==4.3.0
gunicorn==21.2.0

Error 2: Port Binding Issues

Port error
OSError: [Errno 98] Address already in use

Local issue, not deployment. The platform assigns the port dynamically. I changed my code to use the PORT environment variable:

Correct port binding
if __name__ == '__main__':
port = int(os.environ.get('PORT', 5000))
app.run(host='0.0.0.0', port=port)

Error 3: Database Connection Timeout

Database timeout
psycopg2.OperationalError: connection timeout

Railway’s free tier sometimes had cold starts. I added connection pooling:

Connection pooling with psycopg2
from psycopg2 import pool
connection_pool = pool.SimpleConnectionPool(
1, 10,
os.environ.get('DATABASE_URL')
)
def get_db():
return connection_pool.getconn()
def release_db(conn):
connection_pool.putconn(conn)

Cost Reality Check

After deploying several apps, here’s what I actually paid:

ServiceFree TierPaid Tier
Vercel100GB bandwidth, unlimited deploys$20/month for team features
Netlify100GB bandwidth, 300 build minutes/month$19/month for team features
Railway$5 credit/month (usually enough for small apps)Pay-as-you-go after credit
Render750 free hours/month for web services$7/month for starter plan
Domain-$10-15/year

For a beginner with 2-3 small apps, the free tiers are sufficient. I paid $12/year for a custom domain, nothing else.

What I Learned

  1. Start with static sites. Deploying a folder of HTML files to Netlify takes 30 seconds. This builds confidence.

  2. Use PaaS, not VPS. Platforms like Vercel and Railway handle server management. Focus on your app, not infrastructure.

  3. Environment variables for secrets. Never commit API keys. Use platform environment variable features.

  4. Managed databases for persistence. SQLite works locally but causes problems in production. Use the database services provided by hosting platforms.

  5. Read the logs. When deployment fails, platforms show build logs. The error message usually points to the exact problem.

Deployment Checklist

Before deploying:

  • All dependencies listed in requirements.txt (Python) or package.json (Node)
  • Environment variables used for secrets
  • Database connection uses environment variable for URL
  • Port binding uses PORT environment variable
  • Procfile or vercel.json configuration correct
  • .gitignore excludes sensitive files

After deploying:

  • Test all endpoints
  • Check logs for errors
  • Verify environment variables are set
  • Confirm database connections work
  • Set up custom domain if needed
  • Vercel Documentation: Comprehensive guides for Next.js and serverless functions
  • Netlify Documentation: Excellent tutorials for static sites and edge functions
  • Railway Documentation: Clear guides for deploying full-stack apps with databases
  • Reddit Discussion: Real users sharing deployment experiences and solutions

Deployment used to intimidate me. Now I see it as just another step in the development process. The tools have improved significantly. What required a sysadmin ten years ago now takes a CLI command.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments