Hands-On: Deploy to Production
Duration: 90 minutes Difficulty: 🟡 Intermediate
Overview
In this hands-on session, you'll deploy three types of projects to production:
- A React application to Vercel
- A Node.js API to Railway
- A documentation site with MkDocs Material
By the end, you'll have live URLs for all three projects with automated CI/CD pipelines.
Exercise 1: Deploy React App to Vercel (30 minutes)
Step 1: Prepare Your React Application
Create a simple React app or use an existing one:
# Create new React app with Vite
npm create vite@latest my-app -- --template react
cd my-app
npm install
Add a production build script to package.json:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}
Test the build locally:
npm run build
npm run preview
Step 2: Push to GitHub
# Initialize Git
git init
git add .
git commit -m "Initial commit"
# Create GitHub repository and push
gh repo create my-app --public --source=. --remote=origin --push
# Or manually create on GitHub and:
git remote add origin https://github.com/YOUR_USERNAME/my-app.git
git push -u origin main
Step 3: Deploy to Vercel
Option A: Using Vercel Dashboard (Recommended for beginners)
- Visit vercel.com
- Sign up/log in with GitHub
- Click "Add New... → Project"
- Import your GitHub repository
- Configure build settings:
- Framework Preset: Vite
- Root Directory:
./ - Build Command:
npm run build - Output Directory:
dist
- Click "Deploy"
Option B: Using Vercel CLI (Faster for repeat deployments)
# Install Vercel CLI
npm i -g vercel
# Deploy
vercel
# Follow prompts:
# Set up and deploy? Yes
# Which scope? (select your account)
# Link to existing project? No
# Project name? (accept default)
# Directory? (press Enter for current)
# Want to override settings? No
# Production deployment
vercel --prod
Step 4: Verify Deployment
Your app is now live! You'll get two URLs:
- Preview URL:
my-app-abc123.vercel.app(for this specific deployment) - Production URL:
my-app.vercel.app(always points to latest production)
Visit the URL and verify your app works.
Step 5: Add Custom Domain (Optional)
In Vercel Dashboard:
- Project Settings → Domains
- Add your domain (e.g.,
myapp.com) - Configure DNS records as instructed
- Vercel automatically provisions SSL certificate
Exercise 2: Deploy Node.js API to Railway (30 minutes)
Step 1: Create Express API
mkdir my-api
cd my-api
npm init -y
npm install express cors dotenv
Create server.js:
// server.js
import express from 'express';
import cors from 'cors';
import 'dotenv/config';
const app = express();
const PORT = process.env.PORT || 3000;
app.use(cors());
app.use(express.json());
// Health check endpoint
app.get('/health', (req, res) => {
res.json({ status: 'healthy', timestamp: new Date().toISOString() });
});
// Sample API endpoint
app.get('/api/tasks', (req, res) => {
res.json([
{ id: 1, title: 'Deploy to Railway', completed: true },
{ id: 2, title: 'Configure environment variables', completed: false }
]);
});
app.post('/api/tasks', (req, res) => {
const { title } = req.body;
res.status(201).json({ id: Date.now(), title, completed: false });
});
app.listen(PORT, () => {
console.log(`API running on port ${PORT}`);
});
Update package.json:
{
"type": "module",
"scripts": {
"start": "node server.js",
"dev": "node --watch server.js"
}
}
Test locally:
npm run dev
# Visit http://localhost:3000/health
Step 2: Push to GitHub
git init
echo "node_modules\n.env" > .gitignore
git add .
git commit -m "Initial API commit"
gh repo create my-api --public --source=. --remote=origin --push
Step 3: Deploy to Railway
Option A: Using Railway Dashboard
- Visit railway.app
- Sign up with GitHub
- Click "New Project"
- Select "Deploy from GitHub repo"
- Choose your
my-apirepository - Railway auto-detects Node.js and deploys
Option B: Using Railway CLI
# Install Railway CLI
npm i -g @railway/cli
# Login
railway login
# Initialize project
railway init
# Link to GitHub repo (optional)
railway link
# Deploy
railway up
Step 4: Configure Environment Variables
In Railway Dashboard:
- Select your service
- Go to "Variables" tab
- Add variables:
NODE_ENV:productionAPI_KEY:your-secret-key
Or via CLI:
railway variables set NODE_ENV=production
railway variables set API_KEY=your-secret-key
Step 5: Get Your API URL
Railway generates a URL like:
https://my-api-production.up.railway.app
Test your API:
curl https://my-api-production.up.railway.app/health
Step 6: Add PostgreSQL Database (Optional)
In Railway Dashboard:
- Click "New" → "Database" → "PostgreSQL"
- Railway automatically sets
DATABASE_URLenvironment variable - Access in your code:
import pg from 'pg';
const pool = new pg.Pool({
connectionString: process.env.DATABASE_URL,
ssl: { rejectUnauthorized: false }
});
app.get('/api/tasks', async (req, res) => {
const result = await pool.query('SELECT * FROM tasks');
res.json(result.rows);
});
Exercise 3: Deploy Documentation with MkDocs Material (30 minutes)
Step 1: Install MkDocs Material
pip install mkdocs-material
# Or with pipx for isolation
pipx install mkdocs-material
Step 2: Create Documentation Site
mkdir my-docs
cd my-docs
mkdocs new .
This creates:
my-docs/
├── mkdocs.yml # Configuration
└── docs/
└── index.md # Homepage
Step 3: Configure Material Theme
Edit mkdocs.yml:
site_name: My Project Documentation
site_url: https://my-docs.example.com
repo_url: https://github.com/username/my-docs
theme:
name: material
palette:
# Light mode
- scheme: default
primary: indigo
accent: indigo
toggle:
icon: material/brightness-7
name: Switch to dark mode
# Dark mode
- scheme: slate
primary: indigo
accent: indigo
toggle:
icon: material/brightness-4
name: Switch to light mode
features:
- navigation.tabs
- navigation.sections
- navigation.expand
- navigation.top
- search.suggest
- search.highlight
- content.code.copy
- content.code.annotate
plugins:
- search
markdown_extensions:
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tabbed:
alternate_style: true
- admonition
- pymdownx.details
- attr_list
- md_in_html
nav:
- Home: index.md
- Getting Started:
- Installation: getting-started/installation.md
- Quick Start: getting-started/quickstart.md
- API Reference:
- Overview: api/overview.md
- Endpoints: api/endpoints.md
Step 4: Add Documentation Pages
Create docs/getting-started/installation.md:
# Installation
## Prerequisites
- Node.js 20 or higher
- npm or yarn package manager
## Install via npm
\`\`\`bash
npm install my-package
\`\`\`
## Install via yarn
\`\`\`bash
yarn add my-package
\`\`\`
!!! warning "Python 3.10+"
This package requires Python 3.10 or higher for CLI tools.
Test locally:
mkdocs serve
# Visit http://localhost:8000
Step 5: Deploy to GitHub Pages
# Push to GitHub first
git init
git add .
git commit -m "Initial docs"
gh repo create my-docs --public --source=. --remote=origin --push
# Deploy to GitHub Pages
mkdocs gh-deploy
Your docs are now live at:
https://username.github.io/my-docs/
Step 6: Alternative - Deploy to Vercel
# Build static site
mkdocs build
# Deploy to Vercel
vercel deploy
In Vercel, configure:
- Build Command:
pip install mkdocs-material && mkdocs build - Output Directory:
site
Bonus Exercise: GitHub Actions Automation (20 minutes)
Set up automatic deployments on every push.
For Vercel (React App)
Create .github/workflows/deploy.yml:
name: Deploy to Vercel
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
For Railway (API)
Create .github/workflows/deploy-api.yml:
name: Deploy API to Railway
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Railway CLI
run: npm i -g @railway/cli
- name: Deploy to Railway
run: railway up --service=my-api
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
For MkDocs (Documentation)
Create .github/workflows/docs.yml:
name: Deploy Documentation
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Install MkDocs
run: pip install mkdocs-material
- name: Deploy to GitHub Pages
run: mkdocs gh-deploy --force
Troubleshooting Common Issues
Vercel Build Fails
Problem: Error: Command "npm run build" exited with 1
Solutions:
- Check
package.jsonhas correct build script - Verify all dependencies are in
dependencies(notdevDependencies) - Set Node.js version: Create
vercel.json:{ "buildCommand": "npm run build", "devCommand": "npm run dev", "framework": "vite", "installCommand": "npm install", "outputDirectory": "dist" }
Railway Port Issues
Problem: Service starts but shows "Application failed to respond"
Solution: Railway provides PORT environment variable. Use it:
const PORT = process.env.PORT || 3000;
MkDocs GitHub Pages 404
Problem: Documentation deploys but shows 404
Solutions:
- Check GitHub Pages is enabled: Settings → Pages → Source:
gh-pagesbranch - Verify
site_urlinmkdocs.ymlmatches GitHub Pages URL - Wait 2-3 minutes for DNS propagation
Environment Variables Not Working
Problem: Secrets not accessible in application
Solutions:
- Restart service after adding variables
- Check variable names match exactly (case-sensitive)
- For preview deployments, ensure variables are set for "Preview" environment
Verification Checklist
After completing all exercises, verify:
- React app accessible at Vercel URL
- API health check endpoint responds
- Documentation site loads with correct theme
- All sites use HTTPS automatically
- Environment variables configured correctly
- GitHub Actions workflows (if configured) passing
Next Steps
Now that you have live deployments, you'll learn to:
- Set up preview deployments for PRs
- Configure custom domains
- Add monitoring and error tracking
- Implement zero-downtime deployments
Next: 03_exercises.md - Advanced Deployment Patterns
Quick Reference Commands
# Vercel
vercel # Deploy preview
vercel --prod # Deploy production
vercel logs # View logs
vercel env ls # List environment variables
# Railway
railway up # Deploy
railway logs # View logs
railway open # Open in browser
railway variables # Manage environment variables
# MkDocs
mkdocs serve # Local preview
mkdocs build # Build static site
mkdocs gh-deploy # Deploy to GitHub Pages