πŸš€ Lesson 10.4: Build and Deployment

Take your React TypeScript applications from development to production. Learn how to build optimized production bundles, configure environment variables, deploy to popular platforms, and set up continuous integration and deployment pipelines.

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Create optimized production builds with Vite
  • Configure and use environment variables securely
  • Deploy React applications to Vercel, Netlify, and other platforms
  • Set up custom domains with SSL certificates
  • Implement CI/CD pipelines with GitHub Actions
  • Monitor application performance in production
  • Handle common deployment issues and troubleshooting

Estimated Time: 75-90 minutes

Project: Deploy your first React app to production

πŸ“‘ In This Lesson

🌟 Introduction to Production Deployment

Congratulations! You've built amazing React TypeScript applications throughout this course. Now it's time for the most exciting stepβ€”sharing your work with the world by deploying to production.

πŸ“– What is Deployment?

Deployment is the process of moving your application from your local development environment to a production server where real users can access it over the internet. This involves building optimized code, configuring servers, and ensuring everything works correctly in the production environment.

🎯 Development vs Production

Understanding the differences between development and production environments is crucial:

Aspect Development Production
Goal Fast feedback, easy debugging Performance, stability, security
Build Size Large (includes dev tools) Optimized (minified, tree-shaken)
Error Messages Detailed, helpful warnings User-friendly, minimal details
Source Maps Enabled for debugging Optional or disabled
Hot Reload Enabled for fast iteration Not needed
Environment Local machine (localhost) Remote server (public URL)

πŸ”„ The Deployment Pipeline

Modern deployment follows a structured pipeline:

graph LR A[Write Code] --> B[Git Commit] B --> C[Push to GitHub] C --> D[CI/CD Pipeline] D --> E[Run Tests] E --> F[Build Production] F --> G[Deploy to Hosting] G --> H[Live Website! πŸŽ‰] style A fill:#667eea,stroke:#764ba2,stroke-width:2px,color:#fff style B fill:#48bb78,stroke:#38a169,stroke-width:2px,color:#fff style C fill:#ed8936,stroke:#dd6b20,stroke-width:2px,color:#fff style D fill:#4299e1,stroke:#3182ce,stroke-width:2px,color:#fff style E fill:#9f7aea,stroke:#805ad5,stroke-width:2px,color:#fff style F fill:#f687b3,stroke:#ed64a6,stroke-width:2px,color:#fff style G fill:#38b2ac,stroke:#319795,stroke-width:2px,color:#fff style H fill:#48bb78,stroke:#38a169,stroke-width:3px,color:#fff

βœ… Why Use Modern Deployment Platforms?

Modern platforms like Vercel and Netlify make deployment incredibly easy:

  • Zero configuration: Connect your GitHub repo and deploy
  • Automatic builds: New commits trigger automatic deployments
  • Global CDN: Fast loading times worldwide
  • Free SSL: Automatic HTTPS for security
  • Preview deployments: Test changes before going live
  • Rollback support: Easy to revert to previous versions

πŸ“¦ Creating Production Builds

Before deploying, you need to create an optimized production build of your application. This process transforms your development code into highly optimized files ready for production.

πŸ“– What is a Production Build?

A production build is an optimized version of your application where code is minified, compressed, and stripped of development tools. This results in smaller file sizes and faster load times for your users.

πŸ”¨ Building with Vite

If you're using Vite (recommended for React TypeScript projects), building is straightforward:

# Build for production
npm run build

# Preview the production build locally
npm run preview

This creates a dist folder containing your optimized application:

dist/
β”œβ”€β”€ assets/
β”‚   β”œβ”€β”€ index-a1b2c3d4.js      # Your bundled JavaScript
β”‚   β”œβ”€β”€ index-e5f6g7h8.css     # Your bundled CSS
β”‚   └── logo-i9j0k1l2.svg      # Optimized assets
β”œβ”€β”€ index.html                   # Entry point
└── favicon.ico                  # Site icon

πŸ’‘ What Happens During Build?

  • Minification: Removes whitespace, shortens variable names
  • Tree shaking: Removes unused code from bundles
  • Code splitting: Creates separate chunks for better caching
  • Asset optimization: Compresses images and other assets
  • TypeScript compilation: Converts TS to optimized JS
  • CSS bundling: Combines and minifies stylesheets

βš™οΈ Vite Configuration

You can customize the build process in vite.config.ts:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  
  // Build options
  build: {
    // Output directory
    outDir: 'dist',
    
    // Generate source maps for debugging
    sourcemap: false, // Set to true for debugging production
    
    // Minification
    minify: 'esbuild', // Fast and efficient
    
    // Target browsers
    target: 'es2015',
    
    // Chunk size warnings
    chunkSizeWarningLimit: 1000,
    
    // Rollup options for advanced configuration
    rollupOptions: {
      output: {
        // Manual chunk splitting for better caching
        manualChunks: {
          'react-vendor': ['react', 'react-dom'],
          'router': ['react-router-dom'],
        },
      },
    },
  },
  
  // Base path for deployment
  base: '/', // Change if deploying to a subdirectory
  
  // Preview server configuration
  preview: {
    port: 3000,
    host: true,
  },
});

πŸ“Š Analyzing Bundle Size

Understanding what's in your bundle helps optimize it:

# Install bundle analyzer
npm install --save-dev rollup-plugin-visualizer

# Build and analyze
npm run build

Add to vite.config.ts:

import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
  plugins: [
    react(),
    visualizer({
      open: true,
      filename: 'dist/stats.html',
      gzipSize: true,
      brotliSize: true,
    }),
  ],
});

⚠️ Common Build Issues

  • TypeScript errors: Fix all type errors before building
  • Missing dependencies: Ensure all packages are in package.json
  • Path issues: Use relative imports, not absolute paths
  • Environment variables: Configure properly (next section)
  • Large bundle size: Use code splitting and lazy loading

🎯 Build Best Practices

// package.json scripts
{
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "lint": "eslint . --ext ts,tsx",
    "type-check": "tsc --noEmit"
  }
}

βœ… Pre-Deployment Checklist

  • βœ… Run npm run build successfully
  • βœ… Test with npm run preview
  • βœ… Check for TypeScript errors
  • βœ… Verify bundle size is reasonable
  • βœ… Test in different browsers
  • βœ… Confirm all environment variables are set
  • βœ… Review console for errors/warnings

πŸ” Environment Variables

Environment variables allow you to configure your application differently for development, staging, and production without changing code. They're essential for managing API keys, feature flags, and environment-specific settings.

πŸ“– What are Environment Variables?

Environment variables are key-value pairs that exist outside your codebase. They let you keep sensitive information (like API keys) out of version control and configure your app for different environments without code changes.

πŸ”‘ Using Environment Variables in Vite

Vite has built-in support for environment variables through .env files:

# .env.local (for local development - NOT committed to git)
VITE_API_URL=http://localhost:3001/api
VITE_API_KEY=dev_key_12345
VITE_ENABLE_ANALYTICS=false

# .env.production (for production - committed to git)
VITE_API_URL=https://api.myapp.com
VITE_ENABLE_ANALYTICS=true
# Note: Never put secret keys in .env.production!

⚠️ Important: VITE_ Prefix Required

In Vite, environment variables must start with VITE_ to be exposed to your app. This is a security feature to prevent accidentally exposing server-side secrets to the client.

πŸ“ Accessing Environment Variables

// src/config/env.ts
interface Config {
  apiUrl: string;
  apiKey: string;
  enableAnalytics: boolean;
  environment: 'development' | 'production';
}

export const config: Config = {
  apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:3001/api',
  apiKey: import.meta.env.VITE_API_KEY || '',
  enableAnalytics: import.meta.env.VITE_ENABLE_ANALYTICS === 'true',
  environment: import.meta.env.MODE as 'development' | 'production',
};

// Validate required variables
if (!config.apiUrl) {
  throw new Error('VITE_API_URL is required');
}

// Log config in development only
if (import.meta.env.DEV) {
  console.log('App Configuration:', config);
}

πŸ”’ Security Best Practices

βœ… DO's

  • βœ… Use .env.local for local secrets (add to .gitignore)
  • βœ… Use platform environment variables for production secrets
  • βœ… Document required variables in README
  • βœ… Validate environment variables on app startup
  • βœ… Use different API keys for dev/staging/production

❌ DON'Ts

  • ❌ Never commit .env.local to version control
  • ❌ Never put secret keys in .env.production
  • ❌ Don't expose server-side secrets to client code
  • ❌ Don't use production API keys in development
  • ❌ Never hardcode secrets in your source code

πŸ“„ .gitignore Configuration

# .gitignore
# Environment files with secrets
.env.local
.env.*.local

# Build output
dist
dist-ssr
*.local

# Dependencies
node_modules

# Logs
logs
*.log

# IDE
.vscode/*
.idea

🎯 TypeScript Support

Add type definitions for better autocomplete:

// src/vite-env.d.ts
/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_API_URL: string;
  readonly VITE_API_KEY: string;
  readonly VITE_ENABLE_ANALYTICS: string;
  // Add more env variables here
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

πŸ“– Example: API Client with Environment Variables

// src/lib/api-client.ts
import { config } from '@/config/env';

class ApiClient {
  private baseUrl: string;
  private apiKey: string;

  constructor() {
    this.baseUrl = config.apiUrl;
    this.apiKey = config.apiKey;
  }

  async fetch<T>(endpoint: string, options?: RequestInit): Promise<T> {
    const url = `${this.baseUrl}${endpoint}`;
    
    const response = await fetch(url, {
      ...options,
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.apiKey}`,
        ...options?.headers,
      },
    });

    if (!response.ok) {
      throw new Error(`API Error: ${response.statusText}`);
    }

    return response.json();
  }

  async get<T>(endpoint: string): Promise<T> {
    return this.fetch<T>(endpoint);
  }

  async post<T>(endpoint: string, data: unknown): Promise<T> {
    return this.fetch<T>(endpoint, {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }
}

export const apiClient = new ApiClient();

🌍 Different Environments

# Development
npm run dev
# Uses .env.local and .env.development

# Production build
npm run build
# Uses .env.production

# Custom environment
npm run build -- --mode staging
# Uses .env.staging

πŸ“‹ Environment Variables Documentation

Create a .env.example file to document required variables:

# .env.example
# Copy this to .env.local and fill in your values

# API Configuration
VITE_API_URL=http://localhost:3001/api
VITE_API_KEY=your_api_key_here

# Feature Flags
VITE_ENABLE_ANALYTICS=false
VITE_ENABLE_DARK_MODE=true

# Third-party Services
VITE_STRIPE_PUBLIC_KEY=pk_test_...
VITE_GOOGLE_ANALYTICS_ID=G-...

☁️ Deployment Platforms Overview

There are many platforms for deploying React applications. Let's compare the most popular options to help you choose the right one for your needs.

πŸ† Popular Deployment Platforms

Platform Best For Free Tier Key Features
Vercel Next.js, React SPAs Generous (100GB bandwidth) Zero config, preview deployments, edge functions
Netlify Static sites, JAMstack Good (100GB bandwidth) Forms, serverless functions, split testing
GitHub Pages Simple static sites Unlimited (public repos) Free, simple, direct from repo
Cloudflare Pages Global performance Unlimited bandwidth Fast CDN, Workers integration
AWS Amplify AWS ecosystem apps Limited (12 months) Full AWS integration, scalability
Render Full-stack apps Basic (free tier) Static sites + backends, databases

🎯 Choosing the Right Platform

πŸ’‘ Decision Factors

  • Use Vercel if: You want the best Next.js support or need edge functions
  • Use Netlify if: You need built-in forms or A/B testing features
  • Use GitHub Pages if: You want simple, free hosting from your repo
  • Use Cloudflare Pages if: You need global CDN performance
  • Use AWS Amplify if: You're already using AWS services
  • Use Render if: You need both frontend and backend hosting

✨ Common Features Across Platforms

graph TD A[Modern Deployment Platform] --> B[Git Integration] A --> C[Automatic Builds] A --> D[Free SSL/HTTPS] A --> E[Custom Domains] A --> F[Global CDN] A --> G[Preview Deployments] A --> H[Rollback Support] style A fill:#667eea,stroke:#764ba2,stroke-width:3px,color:#fff style B fill:#48bb78,stroke:#38a169,stroke-width:2px,color:#fff style C fill:#ed8936,stroke:#dd6b20,stroke-width:2px,color:#fff style D fill:#4299e1,stroke:#3182ce,stroke-width:2px,color:#fff style E fill:#9f7aea,stroke:#805ad5,stroke-width:2px,color:#fff style F fill:#f687b3,stroke:#ed64a6,stroke-width:2px,color:#fff style G fill:#38b2ac,stroke:#319795,stroke-width:2px,color:#fff style H fill:#fc8181,stroke:#f56565,stroke-width:2px,color:#fff

πŸ’° Pricing Comparison

Platform Free Tier Pro Tier (Monthly) Bandwidth Limit
Vercel Yes $20/member 100GB (free) / 1TB (pro)
Netlify Yes $19/member 100GB (free) / 1TB (pro)
GitHub Pages Yes (unlimited) N/A 100GB/month (soft limit)
Cloudflare Pages Yes $20/month Unlimited (free & paid)
Render Yes (limited) Starts at $7 100GB/month (free)

βœ… Recommendation for Beginners

Start with Vercel or Netlify. Both offer:

  • Excellent free tiers for learning and small projects
  • Simple deployment process (connect GitHub repo)
  • Automatic deployments on every git push
  • Great documentation and community support
  • Easy custom domain setup

β–² Deploying to Vercel

Vercel is one of the most popular platforms for deploying React applications. Created by the makers of Next.js, it offers an exceptional developer experience with zero-configuration deployments.

πŸ“– Why Vercel?

Vercel specializes in frontend frameworks and offers the fastest way to deploy React applications. It handles everything from building your app to serving it on a global CDN, all with automatic HTTPS and preview deployments.

πŸš€ Deploying Your First App to Vercel

Step 1: Prepare Your Repository

# Ensure your code is in a Git repository
git init
git add .
git commit -m "Initial commit"

# Push to GitHub (or GitLab/Bitbucket)
git remote add origin https://github.com/yourusername/your-repo.git
git push -u origin main

Step 2: Sign Up for Vercel

  1. Go to vercel.com
  2. Click "Sign Up"
  3. Choose "Continue with GitHub" (recommended)
  4. Authorize Vercel to access your repositories

Step 3: Import Your Project

  1. Click "Add New Project"
  2. Select your repository from the list
  3. Vercel auto-detects Vite and configures build settings
  4. Click "Deploy"

βœ… What Vercel Detects Automatically

  • Framework: Vite (from package.json)
  • Build Command: npm run build
  • Output Directory: dist
  • Node Version: Latest LTS

βš™οΈ Vercel Configuration

Create vercel.json for custom configuration:

{
  "buildCommand": "npm run build",
  "outputDirectory": "dist",
  "devCommand": "npm run dev",
  "installCommand": "npm install",
  
  "framework": "vite",
  
  "env": {
    "VITE_API_URL": "https://api.myapp.com"
  },
  
  "headers": [
    {
      "source": "/assets/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=31536000, immutable"
        }
      ]
    }
  ],
  
  "redirects": [
    {
      "source": "/old-page",
      "destination": "/new-page",
      "permanent": true
    }
  ],
  
  "rewrites": [
    {
      "source": "/api/:path*",
      "destination": "https://api.myapp.com/:path*"
    }
  ]
}

πŸ” Setting Environment Variables

  1. Go to your project settings on Vercel
  2. Navigate to "Environment Variables"
  3. Add your variables (one per environment)
# Production
VITE_API_URL=https://api.myapp.com
VITE_API_KEY=prod_key_xyz

# Preview (for PR deployments)
VITE_API_URL=https://staging-api.myapp.com
VITE_API_KEY=staging_key_abc

# Development (optional)
VITE_API_URL=http://localhost:3001
VITE_API_KEY=dev_key_123

πŸ”„ Automatic Deployments

Once connected, Vercel automatically deploys:

graph LR A[Push to main] --> B[Production Deploy] C[Create PR] --> D[Preview Deploy] E[Push to PR] --> D D --> F[Unique URL] B --> G[Live Site] style A fill:#667eea,stroke:#764ba2,stroke-width:2px,color:#fff style B fill:#48bb78,stroke:#38a169,stroke-width:2px,color:#fff style C fill:#ed8936,stroke:#dd6b20,stroke-width:2px,color:#fff style D fill:#4299e1,stroke:#3182ce,stroke-width:2px,color:#fff style E fill:#9f7aea,stroke:#805ad5,stroke-width:2px,color:#fff style F fill:#f687b3,stroke:#ed64a6,stroke-width:2px,color:#fff style G fill:#48bb78,stroke:#38a169,stroke-width:3px,color:#fff

πŸ’‘ Preview Deployments

Every pull request gets its own unique preview URL:

  • Test changes before merging
  • Share with team for review
  • Automatic comments on GitHub PRs with preview link
  • Isolated environment with its own database/API

πŸ“± Vercel CLI (Optional)

Deploy from the command line:

# Install Vercel CLI globally
npm install -g vercel

# Login to Vercel
vercel login

# Deploy to production
vercel --prod

# Deploy preview
vercel

🌐 Deploying to Netlify

Netlify is another excellent platform for deploying React applications, known for its powerful features like form handling, serverless functions, and split testing.

πŸ“– Why Netlify?

Netlify offers a complete platform for modern web projects. Beyond hosting, it provides built-in forms, serverless functions, and advanced features like split testingβ€”all with a generous free tier.

πŸš€ Deploying Your First App to Netlify

Method 1: Via Web UI (Easiest)

  1. Go to netlify.com and sign up
  2. Click "Add new site" β†’ "Import an existing project"
  3. Connect to GitHub and select your repository
  4. Configure build settings:
    • Build command: npm run build
    • Publish directory: dist
  5. Click "Deploy site"

Method 2: Drag and Drop

# Build locally
npm run build

# Drag the dist folder to netlify.com/drop

Method 3: Netlify CLI

# Install Netlify CLI
npm install -g netlify-cli

# Login
netlify login

# Initialize Netlify in your project
netlify init

# Deploy
netlify deploy --prod

βš™οΈ Netlify Configuration

Create netlify.toml in your project root:

# netlify.toml
[build]
  command = "npm run build"
  publish = "dist"
  
[build.environment]
  NODE_VERSION = "18"
  
# Redirect rules
[[redirects]]
  from = "/api/*"
  to = "https://api.myapp.com/:splat"
  status = 200
  
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200
  
# Headers
[[headers]]
  for = "/assets/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"
    
[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-Content-Type-Options = "nosniff"
    X-XSS-Protection = "1; mode=block"

πŸ” Environment Variables in Netlify

  1. Go to Site settings β†’ Environment variables
  2. Add your variables
  3. Choose scopes (Production, Deploy previews, Branch deploys)
# Via Netlify UI or CLI
VITE_API_URL=https://api.myapp.com
VITE_API_KEY=your_key_here

✨ Netlify Unique Features

1. Built-in Forms

<!-- Add netlify attribute to form -->
<form name="contact" method="POST" data-netlify="true">
  <input type="hidden" name="form-name" value="contact" />
  <input type="text" name="name" required />
  <input type="email" name="email" required />
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>

2. Serverless Functions

// netlify/functions/hello.ts
import { Handler } from '@netlify/functions';

export const handler: Handler = async (event, context) => {
  return {
    statusCode: 200,
    body: JSON.stringify({ message: 'Hello from Netlify!' }),
  };
};

// Access at: https://yoursite.netlify.app/.netlify/functions/hello

3. Split Testing

# netlify.toml
[[redirects]]
  from = "/*"
  to = "/branch-a/:splat"
  status = 200
  conditions = { Cookie = ["split-test=a"] }
  
[[redirects]]
  from = "/*"
  to = "/branch-b/:splat"
  status = 200
  conditions = { Cookie = ["split-test=b"] }

βœ… Netlify Best Practices

  • Use netlify.toml for configuration (version controlled)
  • Enable "Build plugins" for optimization (image optimization, etc.)
  • Use deploy contexts for different environments
  • Set up deploy notifications (Slack, email)
  • Use Netlify Analytics for privacy-friendly analytics

🌍 Custom Domains and SSL

Your deployed app gets a free subdomain (like myapp.vercel.app), but you'll want a custom domain for a professional look. Both Vercel and Netlify make this easy with automatic SSL certificates.

πŸ“– What is a Custom Domain?

A custom domain is your own web address (like myapp.com) instead of using a platform's subdomain. SSL/TLS certificates enable HTTPS encryption, making your site secure and trusted by browsers.

πŸ›’ Buying a Domain

Popular domain registrars:

Registrar Price Range Features
Namecheap $8-15/year Good prices, free WHOIS protection
Google Domains $12/year Simple, reliable, good support
Cloudflare At-cost (cheapest) No markup, requires account
Porkbun $5-10/year Budget-friendly, good features

πŸ”— Connecting Domain to Vercel

Step 1: Add Domain in Vercel

  1. Go to Project Settings β†’ Domains
  2. Enter your domain (e.g., myapp.com)
  3. Vercel provides DNS records to add

Step 2: Configure DNS

Add these records at your domain registrar:

Type Name Value
A @ 76.76.21.21
CNAME www cname.vercel-dns.com

πŸ’‘ DNS Propagation

DNS changes can take 24-48 hours to propagate globally, but often complete within minutes. Use whatsmydns.net to check propagation status.

πŸ”— Connecting Domain to Netlify

Option 1: Use Netlify DNS (Recommended)

  1. Go to Site settings β†’ Domain management
  2. Click "Add custom domain"
  3. Choose "Use Netlify DNS"
  4. Update nameservers at your registrar:
    • dns1.p0x.netlify.com
    • dns2.p0x.netlify.com
    • dns3.p0x.netlify.com
    • dns4.p0x.netlify.com

Option 2: External DNS

Add these records at your DNS provider:

Type Name Value
A @ 75.2.60.5
CNAME www your-site.netlify.app

πŸ”’ SSL Certificates

Both platforms provide free, automatic SSL certificates:

βœ… SSL is Automatic!

  • Vercel: SSL cert issued automatically within minutes
  • Netlify: SSL cert issued via Let's Encrypt automatically
  • Auto-renewal: Certificates renew automatically before expiring
  • HTTPS redirect: HTTP automatically redirects to HTTPS
  • No cost: Completely free, no manual configuration needed

🎯 Subdomain and Apex Domain

# Apex domain (root domain)
myapp.com

# www subdomain
www.myapp.com

# Custom subdomains
api.myapp.com
blog.myapp.com
docs.myapp.com

⚠️ Best Practice: Support Both

Configure both myapp.com and www.myapp.com, then set one as primary with automatic redirect from the other. Most platforms handle this automatically.

πŸ“‹ Domain Configuration Checklist

Click to expand checklist
  • ☐ Domain purchased from registrar
  • ☐ DNS records configured correctly
  • ☐ DNS propagation completed (check whatsmydns.net)
  • ☐ SSL certificate issued
  • ☐ HTTPS working (look for padlock in browser)
  • ☐ HTTP redirects to HTTPS
  • ☐ www subdomain configured
  • ☐ Primary domain selected
  • ☐ Test site loads correctly on custom domain

βš™οΈ CI/CD with GitHub Actions

Continuous Integration and Continuous Deployment (CI/CD) automate testing and deployment. Every time you push code, your tests run automatically, and if they pass, your app deploys to production.

πŸ“– What is CI/CD?

CI/CD is the practice of automating your development workflow. Continuous Integration (CI) runs tests on every commit. Continuous Deployment (CD) automatically deploys passing code to production.

🎯 Why Use CI/CD?

βœ… Benefits

  • Catch bugs early: Tests run automatically on every commit
  • Consistent builds: Same process every time
  • Faster releases: Deploy with confidence, no manual steps
  • Team coordination: Everyone follows the same workflow
  • Rollback capability: Easy to revert if something goes wrong

πŸ”§ GitHub Actions Basics

GitHub Actions is a CI/CD platform built into GitHub. It runs workflows defined in YAML files:

# .github/workflows/deploy.yml
name: Deploy to Production

# Trigger on push to main branch
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    
    steps:
      # Checkout code
      - uses: actions/checkout@v3
      
      # Setup Node.js
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'
      
      # Install dependencies
      - name: Install dependencies
        run: npm ci
      
      # Run type check
      - name: Type check
        run: npm run type-check
      
      # Run linter
      - name: Lint
        run: npm run lint
      
      # Run tests
      - name: Run tests
        run: npm test
      
      # Build for production
      - name: Build
        run: npm run build
        env:
          VITE_API_URL: ${{ secrets.VITE_API_URL }}
          VITE_API_KEY: ${{ secrets.VITE_API_KEY }}

πŸš€ Advanced Workflow Example

# .github/workflows/ci-cd.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

# Allow manual trigger
  workflow_dispatch:

jobs:
  # Job 1: Test
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [16, 18, 20]
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run tests with coverage
        run: npm run test:coverage
      
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/coverage-final.json
  
  # Job 2: Build and Deploy
  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build
        run: npm run build
        env:
          VITE_API_URL: ${{ secrets.VITE_API_URL }}
          VITE_API_KEY: ${{ secrets.VITE_API_KEY }}
      
      # Deploy to Vercel
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v20
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod'

πŸ” Managing Secrets

Store sensitive information in GitHub Secrets:

  1. Go to your repository on GitHub
  2. Settings β†’ Secrets and variables β†’ Actions
  3. Click "New repository secret"
  4. Add your secrets:
    • VITE_API_URL
    • VITE_API_KEY
    • VERCEL_TOKEN
    • etc.

πŸ’‘ Using Secrets in Workflows

env:
  VITE_API_URL: ${{ secrets.VITE_API_URL }}
  VITE_API_KEY: ${{ secrets.VITE_API_KEY }}

πŸ“Š Workflow Status Badges

Add a badge to your README to show workflow status:

![CI/CD](https://github.com/username/repo/workflows/CI-CD/badge.svg)

🎯 Common Workflow Patterns

1. Preview Deployments for PRs

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Deploy Preview
        # Deploy to preview environment
        run: vercel --env=preview

2. Scheduled Workflows

on:
  schedule:
    # Run every day at midnight
    - cron: '0 0 * * *'

jobs:
  nightly-build:
    runs-on: ubuntu-latest
    steps:
      # Build and test

3. Multi-Environment Deployment

jobs:
  deploy-staging:
    if: github.ref == 'refs/heads/develop'
    # Deploy to staging
    
  deploy-production:
    if: github.ref == 'refs/heads/main'
    # Deploy to production

βœ… CI/CD Best Practices

  • Run tests before deploying
  • Use caching to speed up workflows
  • Keep secrets in GitHub Secrets, never in code
  • Use matrix builds to test multiple Node versions
  • Add status checks to protect main branch
  • Use workflow approvals for production deploys
  • Monitor workflow run times and optimize

πŸ“ˆ Performance Monitoring

After deployment, it's crucial to monitor your application's performance in production. Real users experience different conditions than your local development environment.

πŸ“– Why Monitor Production?

Performance monitoring helps you understand how your app performs for real users. It tracks metrics like load time, errors, and user interactions, allowing you to identify and fix issues quickly.

πŸ“Š Key Metrics to Monitor

Metric What It Measures Good Target
LCP (Largest Contentful Paint) Loading performance < 2.5s
FID (First Input Delay) Interactivity < 100ms
CLS (Cumulative Layout Shift) Visual stability < 0.1
TTFB (Time to First Byte) Server response < 600ms
FCP (First Contentful Paint) Perceived load speed < 1.8s

πŸ› οΈ Monitoring Tools

1. Built-in Platform Analytics

// Vercel Analytics
import { Analytics } from '@vercel/analytics/react';

function App() {
  return (
    <>
      <YourApp />
      <Analytics />
    </>
  );
}
// Netlify Analytics
// Automatically enabled, no code needed
// View in Netlify dashboard β†’ Analytics

2. Google Lighthouse

Test your site's performance:

  1. Open Chrome DevTools (F12)
  2. Go to "Lighthouse" tab
  3. Select categories (Performance, Accessibility, Best Practices, SEO)
  4. Click "Analyze page load"

πŸ’‘ Lighthouse Scoring

  • 90-100: Good (green)
  • 50-89: Needs improvement (orange)
  • 0-49: Poor (red)

3. Web Vitals Library

# Install web-vitals
npm install web-vitals
// src/lib/vitals.ts
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

function sendToAnalytics(metric: any) {
  // Send to your analytics service
  console.log(metric);
  
  // Example: Send to Google Analytics
  if (window.gtag) {
    window.gtag('event', metric.name, {
      value: Math.round(metric.value),
      event_category: 'Web Vitals',
      event_label: metric.id,
      non_interaction: true,
    });
  }
}

// Measure all Web Vitals
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);
// src/main.tsx
import { reportWebVitals } from './lib/vitals';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// Report web vitals
reportWebVitals();

4. Error Monitoring with Sentry

npm install @sentry/react
// src/main.tsx
import * as Sentry from '@sentry/react';

Sentry.init({
  dsn: import.meta.env.VITE_SENTRY_DSN,
  environment: import.meta.env.MODE,
  integrations: [
    new Sentry.BrowserTracing(),
    new Sentry.Replay(),
  ],
  
  // Performance Monitoring
  tracesSampleRate: 1.0,
  
  // Session Replay
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
});

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

πŸ“± Real User Monitoring (RUM)

Track real user experiences:

// Custom RUM implementation
class RUM {
  private metrics: Map<string, number> = new Map();

  trackPageView(path: string) {
    // Track page views
    this.sendEvent('pageview', { path });
  }

  trackError(error: Error) {
    // Track JavaScript errors
    this.sendEvent('error', {
      message: error.message,
      stack: error.stack,
    });
  }

  trackPerformance() {
    // Track performance metrics
    const navigation = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;
    
    this.metrics.set('dns', navigation.domainLookupEnd - navigation.domainLookupStart);
    this.metrics.set('tcp', navigation.connectEnd - navigation.connectStart);
    this.metrics.set('ttfb', navigation.responseStart - navigation.requestStart);
    this.metrics.set('download', navigation.responseEnd - navigation.responseStart);
    this.metrics.set('domInteractive', navigation.domInteractive - navigation.fetchStart);
    this.metrics.set('domComplete', navigation.domComplete - navigation.fetchStart);
    
    this.sendMetrics();
  }

  private sendEvent(name: string, data: any) {
    // Send to your analytics backend
    fetch('/api/analytics', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ event: name, data }),
    });
  }

  private sendMetrics() {
    // Send collected metrics
    fetch('/api/metrics', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(Object.fromEntries(this.metrics)),
    });
  }
}

export const rum = new RUM();

// Usage
rum.trackPageView(window.location.pathname);
rum.trackPerformance();

🎯 Monitoring Best Practices

βœ… What to Monitor

  • Performance metrics: Core Web Vitals, load times
  • Error rates: JavaScript errors, API failures
  • User behavior: Page views, interactions, conversions
  • Resource loading: Image, script, and stylesheet performance
  • API performance: Request/response times, error rates
  • Browser/device distribution: What users are using

⚠️ Privacy Considerations

  • Respect user privacy (GDPR, CCPA compliance)
  • Anonymize IP addresses
  • Provide opt-out mechanisms
  • Don't track PII without consent
  • Use privacy-friendly analytics when possible

πŸ“Š Setting Up Alerts

// Example: Monitor and alert on poor performance
function checkPerformance() {
  getLCP((metric) => {
    if (metric.value > 2500) {
      // Alert: Poor LCP
      sendAlert({
        metric: 'LCP',
        value: metric.value,
        threshold: 2500,
        severity: 'warning',
      });
    }
  });
  
  getCLS((metric) => {
    if (metric.value > 0.1) {
      // Alert: Poor CLS
      sendAlert({
        metric: 'CLS',
        value: metric.value,
        threshold: 0.1,
        severity: 'warning',
      });
    }
  });
}

πŸ‹οΈ Hands-on Exercises

Let's practice deploying React applications! These exercises will help you gain real-world deployment experience.

🎯 Exercise 1: Deploy Your First App

Deploy one of your React TypeScript projects to production.

Requirements
  1. Choose a project from this course (Todo app, Weather dashboard, etc.)
  2. Create a GitHub repository
  3. Push your code to GitHub
  4. Deploy to Vercel or Netlify
  5. Verify the deployment works
  6. Share the URL!
Step-by-Step Guide
# 1. Initialize git if not already done
git init

# 2. Add .gitignore
echo "node_modules
dist
.env.local
*.log" > .gitignore

# 3. Commit your code
git add .
git commit -m "Initial commit"

# 4. Create GitHub repo and push
git remote add origin https://github.com/yourusername/your-repo.git
git push -u origin main

# 5. Go to Vercel.com or Netlify.com
# 6. Import your repository
# 7. Deploy!
Success Criteria
  • βœ… App deployed and accessible via public URL
  • βœ… HTTPS enabled (padlock in browser)
  • βœ… All pages/routes work correctly
  • βœ… No console errors in production
  • βœ… Assets (images, fonts) load properly

🎯 Exercise 2: Configure Environment Variables

Set up environment variables for development and production.

Tasks
  1. Create .env.local for local development
  2. Create .env.example as documentation
  3. Add at least 3 environment variables
  4. Configure them in your deployment platform
  5. Use them in your application code
  6. Verify different values work in dev vs production
Example Implementation
# .env.local (don't commit!)
VITE_APP_NAME=My Awesome App
VITE_API_URL=http://localhost:3001/api
VITE_ENABLE_DEBUG=true

# .env.example (commit this)
VITE_APP_NAME=Your App Name
VITE_API_URL=https://api.example.com
VITE_ENABLE_DEBUG=false
// src/config/env.ts
export const config = {
  appName: import.meta.env.VITE_APP_NAME,
  apiUrl: import.meta.env.VITE_API_URL,
  enableDebug: import.meta.env.VITE_ENABLE_DEBUG === 'true',
};

// Usage in component
function App() {
  return (
    <div>
      <h1>{config.appName}</h1>
      {config.enableDebug && <DebugPanel />}
    </div>
  );
}

🎯 Exercise 3: Set Up a Custom Domain

Connect a custom domain to your deployed application.

Steps

Option A: Use a free subdomain service

  • Use services like FreeDNS or NoIP
  • Get a free subdomain (e.g., myapp.mooo.com)
  • Configure DNS to point to your deployment

Option B: Buy a domain (recommended)

  • Purchase domain from Namecheap, Porkbun, or Google Domains
  • Configure DNS records as shown in lesson
  • Wait for DNS propagation (usually 5-30 minutes)
  • Verify SSL certificate is issued
Verification Checklist
  • ☐ Domain accessible via browser
  • ☐ HTTPS working (green padlock)
  • ☐ Both apex and www subdomains work
  • ☐ HTTP redirects to HTTPS
  • ☐ Check on whatsmydns.net

🎯 Exercise 4: Implement CI/CD

Set up automated testing and deployment with GitHub Actions.

Requirements
  1. Create a GitHub Actions workflow file
  2. Run TypeScript type checking on every push
  3. Run tests on every pull request
  4. Automatically deploy on push to main
  5. Add a status badge to your README
Starter Workflow
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Type check
        run: npm run type-check
      
      - name: Lint
        run: npm run lint
      
      - name: Build
        run: npm run build
Bonus Challenges
  • Add test coverage reporting
  • Run tests in multiple Node.js versions
  • Create preview deployments for PRs
  • Add Slack notifications on deployment
  • Implement blue-green deployments

🎯 Exercise 5: Monitor Your App

Add performance monitoring to your production application.

Tasks
  1. Install and configure web-vitals
  2. Track Core Web Vitals (LCP, FID, CLS)
  3. Run Lighthouse audit on deployed site
  4. Identify and fix at least 3 performance issues
  5. Compare before/after Lighthouse scores
Implementation Guide
# Install web-vitals
npm install web-vitals
// src/reportWebVitals.ts
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

export function reportWebVitals() {
  getCLS(console.log);
  getFID(console.log);
  getFCP(console.log);
  getLCP(console.log);
  getTTFB(console.log);
}

// src/main.tsx
import { reportWebVitals } from './reportWebVitals';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

reportWebVitals();
Success Metrics

Target Lighthouse Scores:

  • Performance: > 90
  • Accessibility: > 90
  • Best Practices: > 90
  • SEO: > 90

Core Web Vitals:

  • LCP: < 2.5s
  • FID: < 100ms
  • CLS: < 0.1

πŸ”§ Troubleshooting Common Issues

Deployment doesn't always go smoothly. Here are solutions to common problems you might encounter.

❌ Problem: Build Fails

Error Message

Error: Command "npm run build" exited with 1

Common Causes & Solutions

  • TypeScript errors: Run npm run type-check locally and fix all errors
  • Missing dependencies: Ensure all packages are in package.json, not just devDependencies
  • Different Node versions: Specify Node version in deployment config
  • Environment variables missing: Check that all required env vars are set

❌ Problem: 404 on Refresh

Issue

App works fine when navigating from home, but refreshing on a route (e.g., /about) gives 404 error.

Solution: Configure Redirects

For Vercel:

// vercel.json
{
  "rewrites": [
    { "source": "/(.*)", "destination": "/" }
  ]
}

For Netlify:

# netlify.toml
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

Or create public/_redirects:

/*    /index.html   200

❌ Problem: Environment Variables Not Working

Common Issues

  • Missing VITE_ prefix: All client-side env vars must start with VITE_
  • Not set on platform: Environment variables must be configured in deployment platform UI
  • Quotes in values: Don't use quotes around values in platform UI
  • Not rebuilding: Changes to env vars require a new deployment

Debug Steps

// Add this temporarily to check
console.log('Environment:', import.meta.env);
console.log('API URL:', import.meta.env.VITE_API_URL);

❌ Problem: Slow Build Times

Optimization Strategies

  • Cache dependencies: Most platforms cache node_modules by default
  • Reduce bundle size: Use code splitting and tree shaking
  • Skip unnecessary steps: Don't run tests in production builds
  • Use faster package manager: Try pnpm instead of npm
// Speed up npm ci
{
  "scripts": {
    "build": "npm ci --prefer-offline && vite build"
  }
}

❌ Problem: Images Not Loading

Common Causes

  • Wrong path: Use relative paths or import statements
  • Case sensitivity: Linux servers are case-sensitive (Image.png β‰  image.png)
  • Not in public folder: Static assets should be in public/
  • Base path issue: Check base config in vite.config.ts

Correct Approaches

// βœ… Import the image
import logo from './assets/logo.png';
<img src={logo} alt="Logo" />

// βœ… Use public folder
<img src="/images/logo.png" alt="Logo" />

// ❌ Don't use absolute paths
<img src="C:/Users/me/project/logo.png" alt="Logo" />

❌ Problem: API Requests Failing

CORS Issues

If API requests work locally but fail in production:

  • Backend CORS: Configure your API to allow requests from your domain
  • Use proxy: Configure Vite proxy for development
  • Use serverless functions: Netlify/Vercel functions can act as proxy
// vite.config.ts - Development proxy
export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3001',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
    },
  },
});

❌ Problem: Large Bundle Size

Reduction Strategies

# Analyze bundle
npm install --save-dev rollup-plugin-visualizer
npm run build
  • Lazy load routes: Use React.lazy() for route components
  • Remove unused dependencies: Check with depcheck
  • Use lighter alternatives: Replace heavy libraries (e.g., moment.js β†’ date-fns)
  • Tree shake properly: Import specific functions, not entire libraries
// ❌ Bad - imports entire library
import _ from 'lodash';

// βœ… Good - imports specific function
import debounce from 'lodash/debounce';

// βœ… Even better - use native methods when possible
const debounce = (fn: Function, ms: number) => {
  let timeout: NodeJS.Timeout;
  return (...args: any[]) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), ms);
  };
};

πŸ› οΈ General Debugging Tips

βœ… Debugging Checklist

  1. Check build logs: Read the entire error message carefully
  2. Build locally first: Run npm run build and npm run preview
  3. Clear cache: Try clearing platform's build cache
  4. Check environment: Verify all required env vars are set
  5. Verify dependencies: Make sure package.json is correct
  6. Test in production mode: Some issues only appear in production builds
  7. Check browser console: Look for JavaScript errors
  8. Verify routes: Test all routes and page refreshes
  9. Check network tab: See if assets are loading correctly
  10. Compare with working version: Look at what changed since last successful deploy

πŸ“š Summary

Congratulations! You've learned how to deploy React TypeScript applications to production. Let's recap the essential concepts:

🎯 Key Takeaways

βœ… What You've Learned

  • Production builds: Creating optimized builds with Vite
  • Environment variables: Managing configuration securely
  • Deployment platforms: Using Vercel, Netlify, and others
  • Custom domains: Connecting your own domain with SSL
  • CI/CD: Automating testing and deployment
  • Monitoring: Tracking performance and errors in production
  • Troubleshooting: Fixing common deployment issues

πŸ”„ The Deployment Workflow

graph TD A[Write Code] --> B[Test Locally] B --> C[Commit to Git] C --> D[Push to GitHub] D --> E[CI/CD Runs Tests] E --> F{Tests Pass?} F -->|Yes| G[Build Production] F -->|No| H[Fix Issues] H --> A G --> I[Deploy to Platform] I --> J[Monitor Performance] J --> K[Iterate & Improve] K --> A style A fill:#667eea,stroke:#764ba2,stroke-width:2px,color:#fff style B fill:#48bb78,stroke:#38a169,stroke-width:2px,color:#fff style C fill:#ed8936,stroke:#dd6b20,stroke-width:2px,color:#fff style D fill:#4299e1,stroke:#3182ce,stroke-width:2px,color:#fff style E fill:#9f7aea,stroke:#805ad5,stroke-width:2px,color:#fff style F fill:#f687b3,stroke:#ed64a6,stroke-width:2px,color:#fff style G fill:#38b2ac,stroke:#319795,stroke-width:2px,color:#fff style H fill:#fc8181,stroke:#f56565,stroke-width:2px,color:#fff style I fill:#48bb78,stroke:#38a169,stroke-width:2px,color:#fff style J fill:#ed8936,stroke:#dd6b20,stroke-width:2px,color:#fff style K fill:#4299e1,stroke:#3182ce,stroke-width:2px,color:#fff

πŸ“‹ Pre-Deployment Checklist

Complete Deployment Checklist

Before Deployment

  • ☐ Code works locally without errors
  • ☐ All tests passing
  • ☐ TypeScript compiles without errors
  • ☐ Production build succeeds (npm run build)
  • ☐ Preview build works (npm run preview)
  • ☐ Environment variables documented
  • ☐ .env.local in .gitignore
  • ☐ All secrets removed from code

During Deployment

  • ☐ Repository connected to platform
  • ☐ Build settings configured correctly
  • ☐ Environment variables set on platform
  • ☐ Custom domain configured (if applicable)
  • ☐ SSL certificate active
  • ☐ Redirects configured for SPA routing

After Deployment

  • ☐ Site loads correctly
  • ☐ All routes work (test page refresh)
  • ☐ Images and assets load
  • ☐ API calls work
  • ☐ Forms submit successfully
  • ☐ No console errors
  • ☐ HTTPS working (green padlock)
  • ☐ Mobile responsive
  • ☐ Performance acceptable (Lighthouse > 80)
  • ☐ Monitoring configured

πŸ› οΈ Essential Tools Reference

Tool/Platform Purpose Link
Vercel Deployment platform vercel.com
Netlify Deployment platform netlify.com
GitHub Actions CI/CD automation github.com/features/actions
Lighthouse Performance auditing Built into Chrome DevTools
Sentry Error monitoring sentry.io
whatsmydns.net DNS propagation checker whatsmydns.net

πŸ“– Quick Command Reference

Essential Commands
# Build for production
npm run build

# Preview production build locally
npm run preview

# Type check
npm run type-check

# Deploy with Vercel CLI
vercel --prod

# Deploy with Netlify CLI
netlify deploy --prod

# Initialize Vercel project
vercel

# Initialize Netlify project
netlify init

# Check bundle size
npm run build -- --stats

πŸ’‘ Final Thoughts

Deployment is not a one-time taskβ€”it's an ongoing process. As you add features, fix bugs, and improve performance, you'll deploy many times. The key is to make this process smooth, automated, and reliable. With the tools and techniques you've learned, you can deploy with confidence!

πŸš€ What's Next?

You've mastered deployment! Here's how to continue your journey:

πŸ“š Continue Learning

  • Next Lesson: Lesson 10.5 - Next Steps and Advanced Topics
  • Practice: Deploy all your course projects to production
  • Explore: Try different deployment platforms and compare them
  • Learn: Dive deeper into DevOps, Docker, and Kubernetes

🎯 Immediate Next Steps

πŸ’‘ This Week's Challenge

  1. Deploy at least one project from this course
  2. Set up a custom domain (even a free subdomain)
  3. Implement CI/CD with GitHub Actions
  4. Monitor your app's performance with Lighthouse
  5. Share your deployed app on social media or with friends!

🌟 Advanced Topics to Explore

βœ… Take It Further

  • Server-Side Rendering: Learn Next.js for SSR and SSG
  • Edge Functions: Deploy serverless functions at the edge
  • Monorepo Management: Use Turborepo or Nx
  • Advanced CI/CD: Blue-green deployments, canary releases
  • Infrastructure as Code: Terraform, Pulumi
  • Container Orchestration: Docker, Kubernetes
  • Observability: Logs, metrics, traces with OpenTelemetry

πŸ“± Build Your Portfolio

Now that you know how to deploy, showcase your work:

  1. Portfolio Website: Create a personal site with all your projects
  2. GitHub Profile: Pin your best repositories
  3. Blog: Write about what you learned (great for SEO and networking)
  4. LinkedIn: Share your deployed projects
  5. Dev.to / Medium: Publish technical articles

πŸŽ“ Course Completion

You're almost at the end of the React TypeScript course! After the final lesson, you'll have:

  • βœ… Built multiple production-ready React applications
  • βœ… Mastered TypeScript for type-safe development
  • βœ… Learned modern React patterns and best practices
  • βœ… Deployed applications to production
  • βœ… Gained real-world development experience

πŸŽ‰ You're Ready!

With deployment mastered, you now have the complete skill set to build and ship professional React TypeScript applications. You're not just learningβ€”you're building real products that real people can use. Keep building, keep shipping, and keep learning!