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:
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:
- Go to netlify.com and create a free account
- Navigate to “Sites” section
- 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:
npm install -g vercelcd my-static-sitevercelVercel asked me a few 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] NAfter 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:
ssh root@my-server-ipapt updateapt install python3 python3-pip nginxpip3 install flask gunicornThen 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:
my-todo-app/├── api/│ └── todos.py├── static/│ ├── index.html│ └── script.js└── vercel.jsonThe api/todos.py file:
from flask import Flask, jsonify, requestimport 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:
{ "version": 2, "builds": [ { "src": "api/**/*.py", "use": "@vercel/python" } ], "routes": [ { "src": "/api/(.*)", "dest": "/api/$1" }, { "src": "/(.*)", "dest": "/static/$1" } ]}Deployed with:
vercel --prodVercel 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:
my-todo-app/├── app.py├── requirements.txt├── static/│ ├── index.html│ └── script.js└── templates/I created a requirements.txt:
flask==3.0.0gunicorn==21.2.0Then a Procfile (tells Railway how to start the app):
web: gunicorn app:appDeployment via Railway CLI:
npm install -g @railway/clirailway loginrailway initrailway upRailway 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:
- Serverless functions (Vercel) can’t persist files between runs
- 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:
railway add --plugin postgresqlRailway gave me a DATABASE_URL environment variable. I updated my code:
import osfrom flask import Flaskimport 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:
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:
railway variables set API_KEY=sk-proj-xxxxxIn my code:
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
- Go to project settings in Vercel dashboard
- Click “Domains”
- Add your domain (e.g.,
myapp.com) - Vercel provides DNS records to add
In Namecheap, I added the records:
Type: AHost: @Value: 76.76.21.21TTL: Automatic
Type: CNAMEHost: wwwValue: cname.vercel-dns.comTTL: AutomaticAfter DNS propagation (took about 30 minutes), my app was accessible at myapp.com.
Common Deployment Errors I Encountered
Error 1: Build Fails - Missing Dependencies
ModuleNotFoundError: No module named 'flask-cors'I forgot to add flask-cors to requirements.txt. Fixed by:
flask==3.0.0flask-cors==4.3.0gunicorn==21.2.0Error 2: Port Binding Issues
OSError: [Errno 98] Address already in useLocal issue, not deployment. The platform assigns the port dynamically. I changed my code to use the PORT environment variable:
if __name__ == '__main__': port = int(os.environ.get('PORT', 5000)) app.run(host='0.0.0.0', port=port)Error 3: Database Connection Timeout
psycopg2.OperationalError: connection timeoutRailway’s free tier sometimes had cold starts. I added connection pooling:
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:
| Service | Free Tier | Paid Tier |
|---|---|---|
| Vercel | 100GB bandwidth, unlimited deploys | $20/month for team features |
| Netlify | 100GB 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 |
| Render | 750 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
-
Start with static sites. Deploying a folder of HTML files to Netlify takes 30 seconds. This builds confidence.
-
Use PaaS, not VPS. Platforms like Vercel and Railway handle server management. Focus on your app, not infrastructure.
-
Environment variables for secrets. Never commit API keys. Use platform environment variable features.
-
Managed databases for persistence. SQLite works locally but causes problems in production. Use the database services provided by hosting platforms.
-
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) orpackage.json(Node) - Environment variables used for secrets
- Database connection uses environment variable for URL
- Port binding uses
PORTenvironment variable -
Procfileorvercel.jsonconfiguration correct -
.gitignoreexcludes 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
Related Resources
- 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