Deploy a React Portfolio with CI/CD
Build a React portfolio and automate deployment with GitHub Actions.
Introduction
30 Second Summary
Every time a developer finishes a feature, they need to get it in front of users. Doing that manually every single time is slow, error-prone, and honestly a bit painful.
In this project, you will build a personal portfolio website with React and Vite, then set up a CI/CD pipeline with GitHub Actions so your site automatically builds and deploys every time you push code.
What You'll Build
A personal portfolio website built with React and Vite, deployed to GitHub Pages through a fully automated GitHub Actions CI/CD pipeline.
By the end of this project, you'll have:
- A React + Vite portfolio site with an About section, a Projects section, and a Contact section.
- A GitHub Actions workflow file (.github/workflows/deploy.yml) that automates the entire build and deployment process.
- A live portfolio URL hosted on GitHub Pages that automatically redeploys whenever you push to main.
- A linting step in your pipeline that catches broken code before it ever reaches production.
Are there any prerequisites?
You should have basic familiarity with HTML, CSS, React, Git, and GitHub. You'll also need Node.js, npm, Git, and VS Code installed on your machine, along with a free GitHub account.
Before We Start
Before We Start...
Scaffold Your React Portfolio with Vite
Every portfolio site starts with a solid foundation. In this step, you'll create a brand new React project using Vite, a fast and modern build tool. You'll verify everything works locally before moving on to building your portfolio content.
In This Step, Get Ready To:
- Create a new React project with Vite and install its dependencies.
- Start the development server and confirm the app runs in your browser.
- Explore the project file structure and identify the key files you'll work with.
Create a New React Project with Vite
Vite is a build tool that scaffolds a ready-to-go project structure for you. It handles bundling, hot reloading, and production builds so you can focus on writing your portfolio code.
- Open your terminal and navigate to the folder where you want to create your project.
- Run the following command to scaffold a new React project:
npm create vite@latest my-portfolio -- --template react
What does this command do?
This command uses npm to run Vite's project creator. The my-portfolio part names your project folder. The --template react flag tells Vite to set up a React project with all the right defaults.
- Navigate into your new project folder and install the dependencies:
cd my-portfolio
npm install
The npm install command downloads all the packages your project needs into a node_modules folder. This might take a minute.
Why Vite Instead of Create React App?
You might have heard of Create React App (CRA), which used to be the standard way to start React projects. CRA is now deprecated and no longer maintained. Vite is the recommended replacement. It is faster, lighter, and actively maintained.
Start the Development Server
Vite includes a built-in development server that lets you preview your app locally. It also supports hot reloading, which means changes you make to your code will appear in the browser instantly.
- Run the development server:
npm run dev
- Open http://localhost:5173 in your browser.
You should see the default Vite + React welcome page with the Vite and React logos and a counter button.
I see the welcome page
Your React app is running. Keep the dev server running in your terminal for now.
I see an error
Having trouble starting the dev server?
Make sure you are inside the my-portfolio folder. Run pwd (macOS/Linux) or cd (Windows) to check your current directory. Also confirm that npm install completed without errors.
Vite requires Node.js 20.19+ or 22.12+. Check your version by running node --version in your terminal.
Still stuck? Ask NextWork for help troubleshooting your Vite dev server.
Explore the Project File Structure
Before you start building, it helps to know where everything lives. Vite created a clean project structure with a few key files you'll be working with throughout this project.
- Open the my-portfolio folder in VS Code.
- Look at the file explorer panel on the left side and find these key files:
- src/App.jsx is your main React component. This is where you'll build your portfolio layout.
- src/App.css is the stylesheet for your main component. You'll add your portfolio styles here.
- vite.config.js is the Vite configuration file. You'll update this later to configure deployment to GitHub Pages.
- package.json lists your project's dependencies and scripts. It includes three default scripts: dev, build, and preview.
What Are These Scripts For?
The dev script starts your local development server. The build script creates an optimized production version of your site in a dist folder. The preview script lets you test that production build locally before deploying it.
Your React project is scaffolded and running locally. Next up, you'll replace the default content with your actual portfolio layout.
Build Your Portfolio Content
In the last step, you scaffolded a React project with Vite and confirmed the default app runs in your browser. Now it's time to turn that template into an actual portfolio.
A portfolio site needs structure. You'll build three sections that showcase who you are, what you've built, and how to reach you. These sections will become the content that your CI/CD pipeline deploys automatically in later steps.
In This Step, Get Ready To:
- Replace the default Vite template with a portfolio layout containing three sections.
- Style your portfolio with custom CSS.
- Verify all three sections render correctly in your browser.
Replace the Default Template with Your Portfolio Layout
The default Vite template shows a counter app with React and Vite logos. You'll replace all of that with a portfolio layout that has three distinct sections: a hero/about section, a projects section, and a contact section.
- Open src/App.jsx in VS Code.
- Select all the existing code and replace it with the following portfolio layout:
import './App.css'
function App() {
return (
<div className="portfolio">
{/* Hero / About Section */}
<section className="hero">
<h1>Hi, I'm [[YOURNAME="your name"]]</h1>
<p>
I'm a developer who loves building things for the web.
Welcome to my portfolio!
</p>
</section>
{/* Projects Section */}
<section className="projects">
<h2>Projects</h2>
<div className="project-grid">
<div className="project-card">
<h3>Project One</h3>
<p>A brief description of your first project.</p>
<a href="#">View Project</a>
</div>
<div className="project-card">
<h3>Project Two</h3>
<p>A brief description of your second project.</p>
<a href="#">View Project</a>
</div>
<div className="project-card">
<h3>Project Three</h3>
<p>A brief description of your third project.</p>
<a href="#">View Project</a>
</div>
</div>
</section>
{/* Contact Section */}
<section className="contact">
<h2>Get In Touch</h2>
<p>Want to work together? Reach out!</p>
<div className="contact-links">
<a href="mailto:your@email.com">Email</a>
<a href="https://github.com" target="_blank" rel="noreferrer">GitHub</a>
<a href="https://linkedin.com" target="_blank" rel="noreferrer">LinkedIn</a>
</div>
</section>
</div>
)
}
export default App
What does this code do?
This is a single React component that renders your entire portfolio page. It's split into three <section> elements, each with its own class name for styling. The hero section introduces you. The projects section displays three placeholder cards in a grid. The contact section provides links for people to reach you.
Feel free to customize the text with your own name, bio, and project descriptions. The placeholder content is just a starting point.
Style Your Portfolio
Your portfolio has structure, but it needs visual polish. You'll replace the default Vite styles with custom CSS that gives each section a clean, professional look.
- Open src/App.css in VS Code.
- Select all the existing styles and replace them with the following:
/* Reset and base styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, -apple-system, sans-serif;
line-height: 1.6;
color: #333;
}
/* Hero / About Section */
.hero {
text-align: center;
padding: 80px 20px;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
}
.hero h1 {
font-size: 2.5rem;
margin-bottom: 16px;
}
.hero p {
font-size: 1.2rem;
max-width: 600px;
margin: 0 auto;
opacity: 0.9;
}
/* Projects Section */
.projects {
padding: 60px 20px;
max-width: 900px;
margin: 0 auto;
}
.projects h2 {
text-align: center;
font-size: 2rem;
margin-bottom: 32px;
}
.project-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 24px;
}
.project-card {
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 24px;
transition: box-shadow 0.2s;
}
.project-card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.project-card h3 {
margin-bottom: 8px;
}
.project-card p {
margin-bottom: 12px;
color: #666;
}
.project-card a {
color: #667eea;
text-decoration: none;
font-weight: 600;
}
/* Contact Section */
.contact {
text-align: center;
padding: 60px 20px;
background: #f8f9fa;
}
.contact h2 {
font-size: 2rem;
margin-bottom: 12px;
}
.contact p {
margin-bottom: 24px;
color: #666;
}
.contact-links {
display: flex;
justify-content: center;
gap: 24px;
}
.contact-links a {
color: #667eea;
text-decoration: none;
font-weight: 600;
font-size: 1.1rem;
}
What do these styles do?
The hero section gets a purple gradient background that makes your name stand out. The projects section uses CSS Grid to arrange your project cards in a responsive layout that adapts to different screen sizes. The contact section has a light gray background to visually separate it from the rest of the page.
- Also open src/index.css and delete all of its contents.
The default index.css file contains Vite's template styles that would conflict with your custom CSS. Clearing it ensures your portfolio styles take full effect.
Verify Your Portfolio in the Browser
Your dev server should still be running from the previous step. If you stopped it, start it again.
- Open your browser to http://localhost:5173.
- Confirm you see three sections: the hero with your name on a purple gradient, the project cards in a grid, and the contact links at the bottom.
- Try resizing your browser window to see the project cards reflow responsively.
What should I see?
Your page should show a purple gradient header with your name, followed by three project cards arranged side by side (or stacked on narrow screens), and a gray contact section at the bottom with Email, GitHub, and LinkedIn links.
Still seeing the old Vite template?
Make sure you saved both src/App.jsx and src/App.css. Vite's dev server hot-reloads on save, so the browser should update automatically. If styles look off, check that you also cleared src/index.css. Help me troubleshoot my portfolio not rendering correctly.
Your portfolio is looking great locally. Next up, you'll push this code to GitHub so it's ready for your CI/CD pipeline to deploy.
Push Your Portfolio to GitHub
Your portfolio looks great locally, but it needs to live somewhere accessible before you can deploy it. GitHub will host your source code and serve as the foundation for the CI/CD pipeline you'll build in the next steps. In this step, you'll create a remote repository and push your project to it.
In This Step, Get Ready To:
- Create a new public repository on GitHub.
- Initialize Git locally and push your portfolio code to the remote repository.
- Confirm your files appear on GitHub.
Create a New Repository on GitHub
Your GitHub repository is the central hub that connects your local code to the deployment pipeline. It needs to be public so that GitHub Pages can serve your site for free.
- Go to github.com and sign in to your account.
- Click the + icon in the top right corner and select New repository.
- Enter my-portfolio as the Repository name.
- Make sure Public is selected.
- Leave all the initialization checkboxes unchecked. Do not add a README, .gitignore, or license.
- Click Create repository.
Why skip the README and .gitignore?
Vite already created these files in your local project when you scaffolded it. If GitHub also creates them, you'll get merge conflicts when you try to push. Starting with an empty repository avoids this problem entirely.
Initialize Git and Push Your Code
Now you'll connect your local project to the remote repository you just created. This involves initializing a Git repository locally, committing your files, and pushing them to GitHub.
- Open your terminal in VS Code and make sure you're in the my-portfolio directory.
- Run the following commands to initialize Git, stage all your files, and create your first commit:
git init
git add .
git commit -m "Initial portfolio site"
- Connect your local repository to the remote on GitHub and push your code:
git remote add origin https://github.com/[[GITHUB_USERNAME="YOUR_USERNAME"]]/my-portfolio.git
git branch -M main
git push -u origin main
What do these commands do?
- git remote add origin links your local project to the GitHub repository you just created.
- git branch -M main renames your default branch to main.
- git push -u origin main uploads all your committed files to GitHub and sets main as the default upstream branch for future pushes.
Getting an authentication error?
GitHub no longer accepts passwords for Git operations. You need to use a personal access token or SSH key. If you're seeing an authentication failure, help me set up GitHub authentication.
Confirm Your Files on GitHub
- Go back to your repository page on GitHub in your browser.
- Refresh the page.
You should see all your project files listed, including src/, package.json, vite.config.js, and your commit message "Initial portfolio site" at the top.
Your code is now on GitHub and ready to be deployed. Next up, you'll configure Vite so your portfolio works correctly when hosted on GitHub Pages.
Configure Vite for GitHub Pages
Your portfolio code is now on GitHub, but GitHub Pages needs to know where your site's assets live. When you deploy to GitHub Pages, your site doesn't live at the root of a domain. It lives at a subpath like /my-portfolio/. Without telling Vite about this, your CSS, JavaScript, and images will all point to the wrong URLs and your site will appear broken.
In This Step, Get Ready To:
- Configure the Vite base path so assets load correctly on GitHub Pages.
- Build your portfolio for production and verify the output.
- Preview the production build locally to confirm everything works.
Set the Base Path in Vite Config
GitHub Pages serves project sites at a subpath based on your repository name. Your portfolio will be available at https://YOUR_USERNAME.github.io/my-portfolio/, not at the root of the domain. The base property in vite.config.js tells Vite to prefix all asset URLs with this subpath.
- Open vite.config.js in VS Code.
- Add the base property to the configuration object, setting it to your repository name wrapped in forward slashes.
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
base: '/[[REPONAME="my-portfolio"]]/'
})
Why does the base path matter?
Without the base property, Vite generates asset URLs that start from the domain root (/assets/style.css). On GitHub Pages, your site lives at /my-portfolio/, so the browser would look for assets in the wrong place. Setting base fixes every generated URL to include the correct subpath.
Build Your Portfolio for Production
The npm run build command tells Vite to compile your React code into optimized static files that a browser can serve directly. This is the same command your CI/CD pipeline will run automatically later.
- Run the build command in your terminal.
npm run build
Vite creates a dist folder containing your production-ready HTML, CSS, and JavaScript files. This is the folder that will be uploaded to GitHub Pages during deployment.
What should I see?
Your terminal should show a successful build with output listing the files generated in the dist folder, including an index.html file and bundled asset files. If you see any errors, check that your vite.config.js syntax is correct.
Build failing?
Make sure you saved vite.config.js before running the build. The most common issue is a missing comma between the plugins and base properties. If you're still stuck, ask NextWork for help debugging your Vite config.
Preview the Production Build Locally
Before deploying, it's worth previewing the built site locally. Vite includes a preview server that serves the dist folder exactly as a static host would. This catches issues that only appear in production builds, like broken asset paths.
- Run the preview command in your terminal.
npm run preview
- Open http://localhost:4173 in your browser.
- Verify that all three sections of your portfolio (About, Projects, and Contact) render correctly.
- Press Ctrl+C in your terminal to stop the preview server when you're done.
What is the difference between dev and preview?
The npm run dev command runs a development server with hot reloading and unoptimized code for fast feedback. The npm run preview command serves the final, optimized production build from the dist folder. Previewing the production build is the closest you can get to testing what your deployed site will look like.
Your portfolio is now configured and ready for deployment. Next up, you'll write the GitHub Actions workflow that automates the entire build and deploy process.
Write Your GitHub Actions Workflow
Your portfolio code is on GitHub and your Vite config is ready for deployment. Now it's time to build the actual CI/CD pipeline. A GitHub Actions workflow is a YAML file that tells GitHub exactly what to do every time you push code. In this step, you'll write that file from scratch.
In This Step, Get Ready To:
- Create the workflow directory and YAML file.
- Write a complete GitHub Actions workflow that builds and deploys your site.
- Understand each section of the workflow file.
Create the Workflow Directory Structure
GitHub Actions looks for workflow files in a specific location: the .github/workflows directory at the root of your repository. Any .yml file placed in this folder becomes a workflow that GitHub can run.
- Open your terminal in the my-portfolio project root.
- Run the following command to create the required directory structure:
mkdir -p .github/workflows
- Create a new file at .github/workflows/deploy.yml in VS Code.
Why deploy.yml?
The filename can be anything you want, as long as it ends in .yml or .yaml. Naming it deploy.yml makes its purpose obvious to anyone reading your repository.
Write the Workflow YAML
This is where the magic happens. Your workflow file defines the entire CI/CD pipeline: when it runs, what permissions it needs, and every step from checking out code to deploying the live site.
- Open .github/workflows/deploy.yml and paste the following workflow:
# Deploy React portfolio to GitHub Pages
name: Deploy to GitHub Pages
# Trigger the workflow on every push to the main branch
on:
push:
branches: ['main']
# Grant the workflow permission to deploy to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Prevent overlapping deployments
concurrency:
group: 'pages'
cancel-in-progress: true
jobs:
deploy:
# Use the GitHub Pages deployment environment
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
# Step 1: Pull down the repository code
- name: Checkout
uses: actions/checkout@v6
# Step 2: Install Node.js with npm caching for faster builds
- name: Set up Node
uses: actions/setup-node@v6
with:
node-version: lts/*
cache: 'npm'
# Step 3: Install project dependencies
- name: Install dependencies
run: npm ci
# Step 4: Build the production-ready site
- name: Build
run: npm run build
# Step 5: Configure GitHub Pages settings
- name: Setup Pages
uses: actions/configure-pages@v6
# Step 6: Upload the built site as a deployment artifact
- name: Upload artifact
uses: actions/upload-pages-artifact@v4
with:
path: './dist'
# Step 7: Deploy the artifact to GitHub Pages
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5
What Does This Workflow Do?
This single file automates your entire deployment process. Here's what each major section controls:
- on: defines when the workflow runs. Here, it triggers on every push to the main branch.
- permissions: grants the workflow access to read your code and write to GitHub Pages.
- concurrency: prevents multiple deployments from running at the same time. If you push twice quickly, the first deployment gets cancelled.
- jobs: defines the actual work. The seven steps checkout code, install Node.js, install dependencies, build the site, and deploy it to GitHub Pages.
What is npm ci?
You might have noticed the workflow uses npm ci instead of npm install. The ci command stands for "clean install." It installs dependencies exactly as specified in your package-lock.json file, which makes builds faster and more reliable in automated pipelines.
Review the Workflow Structure
Before moving on, take a moment to trace through the workflow file from top to bottom. Every GitHub Actions workflow follows the same pattern: triggers, permissions, and jobs.
The uses keyword in each step references pre-built Actions created by GitHub and the community. Think of them as reusable building blocks. Instead of writing dozens of lines of bash to set up Node.js or upload files, you reference an action like actions/setup-node@v6 and it handles everything for you.
The run keyword is for steps where you want to execute a shell command directly, like npm ci or npm run build. Every step uses either uses (for a pre-built action) or run (for a custom command), never both.
Pro tip: reading YAML
YAML uses indentation to define structure, similar to Python. Each level of indentation creates a nested section. If your workflow ever fails with a syntax error, check your indentation first. Every level should use exactly two spaces.
Your pipeline is written and ready to go. Next up, you'll enable GitHub Pages and push this workflow to watch it run live.
Deploy and Watch Your Pipeline Run
Your workflow file is written and your Vite config is ready. Now it's time to connect everything and trigger your first automated deployment. In this step, you'll enable GitHub Pages to accept deployments from GitHub Actions, push your pipeline code, and watch your portfolio go live.
In This Step, Get Ready To:
- Configure GitHub Pages to deploy from GitHub Actions.
- Push your workflow file and trigger the CI/CD pipeline.
- Visit your live portfolio site on the internet.
Enable GitHub Pages in Your Repository
By default, GitHub Pages expects to deploy from a branch. Your workflow uses the modern artifact-based deployment approach instead, so you need to tell GitHub Pages to accept deployments from GitHub Actions.
- Open your repository on GitHub.
- Click Settings in the top navigation bar.
- Select Pages from the left sidebar.
- Under Build and deployment, find the Source dropdown.
- Change the source from Deploy from a branch to GitHub Actions.
Why do I need to change this setting?
GitHub Pages originally only supported deploying from a specific branch (like gh-pages). The modern approach uses GitHub Actions to upload build artifacts directly. Your workflow uses actions/upload-pages-artifact and actions/deploy-pages to handle this. Without switching the source, GitHub won't know to look for your workflow's deployment.
Push Your Workflow and Trigger the Pipeline
Your workflow is configured to trigger on every push to the main branch. Pushing your new workflow file and the updated vite.config.js will kick off the pipeline for the first time.
- Open your terminal in the project root directory.
- Stage all your changes, commit, and push.
git add .
git commit -m "Add CI/CD pipeline"
git push
- Go back to your GitHub repository in the browser.
- Click the Actions tab at the top of the repository.
You should see a workflow run in progress with the commit message "Add CI/CD pipeline". Click on it to watch each step execute in real time.
What should I see?
The Actions tab shows your workflow runs as a list. Click into the run to see the deploy job. Each step (checkout, setup Node, install, build, configure pages, upload, deploy) appears with a green checkmark as it completes. The entire run typically takes about 1-2 minutes.
Seeing a red X on your workflow run?
Click into the failed run to see which step failed and read the error message. Common issues include forgetting to change the GitHub Pages source to GitHub Actions, a typo in the deploy.yml file, or a mismatched base path in vite.config.js. Help me debug my failed workflow run.
Visit Your Live Portfolio
Once the workflow run shows a green checkmark, your site is live on the internet.
- Open a new browser tab.
- Navigate to https://YOUR_USERNAME.github.io/my-portfolio/.
Your React portfolio is now live. This is the same site you were viewing on localhost, but now it's hosted on GitHub Pages and accessible to anyone with the URL.
Pro tip: find your URL from the Actions tab
You can also find your live URL by clicking into the completed workflow run. The deploy step shows the URL where your site was published. This is handy if you forget your repository name or username.
Your portfolio is live and your CI/CD pipeline is working. Next up, you'll put the pipeline to the real test by making a change and watching it deploy automatically.
Test the CI/CD Pipeline with a Live Change
Your portfolio is live, and your CI/CD pipeline is wired up. But the real magic is what happens when you change your code. Every push to main triggers an automatic build and deployment with zero manual steps. In this step, you'll prove it by making a visible change and watching the full pipeline do its thing.
In This Step, Get Ready To:
- Make a visible change to your portfolio code.
- Push the change and watch GitHub Actions automatically trigger a new deployment.
- Verify the change appears on your live site without any manual steps.
Make a Visible Change to Your Portfolio
To prove the pipeline works end-to-end, you need a change that is easy to spot on the live site. A headline update or a color change works perfectly.
- Open src/App.jsx in VS Code.
- Change your headline text to something noticeably different. For example, update your name heading to include "v2" or change your bio text.
- Save the file.
You can also open src/App.css and change a background color or font size. The key is picking something you will immediately recognize on the live site.
Pro tip: check locally first
Run npm run dev to preview your change at http://localhost:5173 before pushing. This confirms the change looks right and catches any syntax errors before they hit the pipeline.
Push the Change and Watch the Pipeline
Every push to main triggers your GitHub Actions workflow. The moment your code reaches GitHub, the pipeline kicks off automatically.
- Stage, commit, and push your change:
git add .
git commit -m "Update portfolio content"
git push
- Open your GitHub repository in your browser.
- Click the Actions tab.
You should see a new workflow run appear with your commit message "Update portfolio content". Click on it to watch the pipeline execute each step in real time.
What Should I See?
The workflow run page shows your deploy job with each step listed vertically. You can expand any step to see its logs. A yellow spinning icon means the step is running. A green checkmark means it passed.
What is Happening Behind the Scenes?
When you pushed, GitHub detected the push to main and matched it against the on trigger in your deploy.yml workflow. GitHub spun up a fresh ubuntu-latest virtual machine, checked out your code, installed dependencies with npm ci, and ran npm run build to generate the dist folder.
Then it uploaded that folder as an artifact and deployed it to GitHub Pages. All without you lifting a finger.
Verify Your Change on the Live Site
The final proof is seeing your change live on the internet. Once the workflow shows a green checkmark, your updated site is already deployed.
- Open your live portfolio URL in your browser: https://your GitHub username.github.io/my-portfolio/.
- Do a hard refresh if you don't see the change right away. Press Cmd+Shift+R (macOS) or Ctrl+Shift+R (Windows) to bypass the browser cache.
Your updated headline, color, or whatever you changed should now be visible on the live site. This is CI/CD in action. You changed code locally, pushed it to GitHub, and the pipeline handled everything else.
I see my change live
Your CI/CD pipeline is working perfectly. Every future push to main will trigger this same automated build and deploy process.
I don't see the change
- Check the Actions tab to make sure the workflow completed with a green checkmark. If it shows a red X, click on the run to see which step failed.
- Try a hard refresh with Cmd+Shift+R (macOS) or Ctrl+Shift+R (Windows). Browsers often cache the old version.
- Verify that base in vite.config.js matches your repository name exactly, including the leading and trailing slashes.
- Confirm that GitHub Pages source is still set to GitHub Actions under Settings > Pages.
Still not working?
If your workflow passed but the site is not updating, wait a minute or two. GitHub Pages can take a short time to propagate changes. If the problem persists, help me debug my GitHub Pages deployment.
Why Does This Matter?
In professional development teams, this exact pattern runs hundreds of times a day. Developers push code, and automated pipelines handle testing, building, and deploying. Nobody manually uploads files to a server.
You just experienced the core loop of modern software delivery. The workflow you built is the same pattern used at companies of every size.
Secret mission
Add a Linting Step to Your Pipeline
Your CI/CD pipeline builds and deploys your site automatically. But what happens if you push broken code? Right now, nothing stops it from going live. In this secret mission, you'll add a code quality gate that catches errors before they ever reach your users.
Before you go
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely on GitHub's free tier and your local machine, so there are no ongoing costs.
Resources you used:
- Local project folder (my-portfolio) with your React + Vite source code.
- GitHub repository (my-portfolio) containing your code and workflow file.
- GitHub Pages site hosted at https://YOUR_USERNAME.github.io/my-portfolio/.
- GitHub Actions workflow (.github/workflows/deploy.yml) that triggers on every push to main.
Keep everything running
No action needed. Choose this if you're still actively building your portfolio or plan to keep it as a live site.
- Your GitHub Pages site will remain live and free for public repositories.
- Your GitHub Actions workflow will continue to run automatically on every push to main.
- GitHub Actions is free for public repositories with 2,000 minutes per month for private repos on the free plan.
- GitHub Pages has no bandwidth or credit limits for public repositories.
Pause - I'll come back to this later
Disable the live site and workflow while keeping all your code and configuration intact.
- Go to your GitHub repository's Settings > Pages and change the Source back to Deploy from a branch with no branch selected. This disables GitHub Pages without deleting anything.
- Your repository, code, and workflow file will remain intact. You can re-enable Pages at any time by switching the Source back to GitHub Actions.
- Stop the local dev server if it is still running by pressing Ctrl + C in your terminal.
Delete - I don't want to use this again
Remove all project resources and start fresh.
- Delete the GitHub repository. Go to Settings > scroll to the bottom > Danger Zone > Delete this repository. This will also remove the GitHub Pages site and all workflow run history.
- Delete the local project folder. Run rm -rf my-portfolio on macOS/Linux or delete the my-portfolio folder manually on Windows.
- Stop the local dev server if it is still running by pressing Ctrl + C in your terminal.
Mission accomplished
That's a Wrap!
Nice work! You just built a personal portfolio site and deployed it to the internet with a fully automated CI/CD pipeline.
Here's what you learned:
- Built a React + Vite portfolio site from scratch and configured it for GitHub Pages deployment.
- Wrote a GitHub Actions workflow YAML file from scratch that automatically builds and deploys your site on every push to main.
- Tested the full CI/CD loop by pushing a live change and watching it deploy automatically with zero manual steps.
- Added a linting step to your pipeline to catch code quality issues before deployment, applying the "fail fast" principle of CI/CD.
Ready to quiz yourself?