CI/CD Pipeline for React App on S3 + CloudFront using GitHub Actions πŸš€



This content originally appeared on DEV Community and was authored by Yash Sonawane

“What if every time you push to GitHub, your website updated itself within minutes?”

Welcome to the world of automated deployments! In this post, we’ll build a CI/CD pipeline that deploys a React app to Amazon S3 and serves it globally via CloudFront, all powered by GitHub Actions.

Perfect for developers who want to move fast, stay lean, and look like pros. 😎

🎯 What We’ll Cover

  • Build and host a React app on S3
  • Connect CloudFront for global delivery
  • Use GitHub Actions to auto-deploy on every push
  • Add cache invalidation so users always get the latest version

Think of this like a pizza shop that bakes, boxes, and delivers your app every time you update the ingredients (code)!

🧰 Prerequisites

  • AWS account with access to S3, CloudFront, and IAM
  • React project (Create with npx create-react-app my-app)
  • GitHub repo with your React app
  • Basic familiarity with GitHub Actions and AWS CLI

🏗 Step 1: Create an S3 Bucket for Static Hosting

  1. Go to the AWS S3 Console
  2. Create a new bucket: my-react-app-bucket
  3. Uncheck “Block all public access” (for static hosting)
  4. Enable Static Website Hosting
  5. Note the bucket URL (you’ll need it later)

Bucket policy example:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-react-app-bucket/*"
    }
  ]
}

🌍 Step 2: Set Up CloudFront

  1. Go to the CloudFront Console
  2. Create a new distribution:
  • Origin: Your S3 bucket website endpoint
  • Viewer Protocol Policy: Redirect HTTP to HTTPS
  • Cache Behavior: Set TTLs, enable compression
  • Optional: Add a custom domain with ACM SSL

📌 Save the CloudFront domain (e.g. d1234xyz.cloudfront.net)

🤖 Step 3: Create IAM User for GitHub Actions

  1. Go to IAM β†’ Create user github-deploy-user
  2. Attach permissions:
  • AmazonS3FullAccess
  • CloudFrontFullAccess
    1. Download Access Key ID & Secret

Store these as GitHub Secrets:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • DISTRIBUTION_ID (CloudFront ID)
  • S3_BUCKET_NAME (your bucket)

⚙ Step 4: Add GitHub Actions Workflow

Create .github/workflows/deploy.yml in your repo:

name: Deploy React App to S3 + CloudFront

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v3

    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'

    - name: Install dependencies
      run: npm install

    - name: Build app
      run: npm run build

    - name: Sync to S3
      run: |
        aws s3 sync build/ s3://$S3_BUCKET_NAME --delete
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        AWS_REGION: us-east-1

    - name: Invalidate CloudFront cache
      run: |
        aws cloudfront create-invalidation --distribution-id $DISTRIBUTION_ID --paths "/*"
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        AWS_REGION: us-east-1

📦 Bonus: Speed Tips

  • Add a custom domain with Route 53
  • Use S3 lifecycle rules to manage stale assets
  • Enable gzip + Brotli in CloudFront for performance

✅ Done! Push & Deploy

Now, every time you git push, your app:

  1. Builds
  2. Uploads to S3
  3. Invalidates the CloudFront cache
  4. Goes live globally 🌎

Zero manual steps. Just speed and satisfaction. 😌

💬 What Will You Build Next?

Will you use this pipeline for:

  • Your portfolio site?
  • A React landing page for your startup?
  • A client dashboard?

👇 Share your use case, tips, or questions below!

If you loved this, smash that ❤ and share with someone building React apps.
Let’s deploy smart, fast, and like pros. 💪


This content originally appeared on DEV Community and was authored by Yash Sonawane