Keeping my blogfolio (a mix of a blog and portfolio) up to date used to feel like a chore. Every little change—whether it was fixing a bug, or updating my design—meant manually uploading files, testing everything locally, and praying nothing broke once it went live.
Then I discovered CI/CD (Continuous Integration and Continuous Deployment), and let me tell you—it’s a total game changer. Now, updates are quick, smooth, and (almost) stress-free. In this post, I’ll show you how I use CI/CD to keep my blogfolio running at almost all time.
What Even Is CI/CD?
Don’t let the fancy tech terms scare you. Here’s what CI/CD actually means:
CI (Continuous Integration)
Every time I update something—like code, content, or styles—CI tools make sure those changes work well with the rest of my project. It automatically runs tests, builds my site, and checks for errors. Think of it as having a super-picky editor who catches mistakes before you publish.
CD (Continuous Deployment)
Once CI gives the green light, CD swoops in and handles deploying everything to the live site. No more manually uploading files or forgetting to restart a server. It just works.
In short, CI/CD takes care of all the boring, repetitive stuff, so I can focus on the fun parts—like writing blog posts or tweaking my portfolio design.
Why Bother With CI/CD?
When you’re managing a blogfolio, updates happen all the time. You might:
- Fix a typo or broken link.
- Try out a fancy new design idea.
- Add a new page
Without CI/CD, every update feels like a gamble. You’re constantly double-checking that you didn’t break something. With CI/CD, the process is automated and reliable. I get to relax knowing my site is in good hands.
How I Set Up CI/CD for My Blogfolio
Here’s how I got everything working:
1. Version Control with Git
I keep all my code and content in a GitHub repo. It’s like my site’s brain, storing every change and letting me roll back if something goes wrong.
My repo is pretty simple. It is based off Remix and NextUI:
├── .github/ # GitHub Actions workflows
├── app/ # The actual website code, with routes.
├── public/ # The locally stored content.
├──
├── Dockerfile # The Dockerfile for the CI/CD
├── docker-compose.yml # The docker-compose file for the project.
├── package.json # Dependencies and scripts.
└── README.md # Notes about the project.
With Git, I can experiment on feature branches without messing up the live site. When I’m ready, I merge my changes into the main branch, and CI/CD takes it from there.
2. Automating the Process with GitHub Actions
GitHub Actions is my go-to for CI. It runs a workflow every time I push changes to the main branch or open a pull request.
Here’s what the workflow does:
- Checkout Code: Grabs the latest version of my repo.
- Install Dependencies: Installs everything my site needs (like npm packages).
- Run Tests: Checks that the site builds without errors and links work.
- Build the Site: Compiles my code into a static site ready for deployment.
Here’s a super-basic example of my GitHub Actions workflow:
name: 🚀 Deploy
on:
push:
branches:
- main
pull_request: { }
jobs:
build:
name: 🐳 build
uses: ./.github/workflows/build.yml
secrets: inherit
deploy:
name: 🚀 Deploy
runs-on: [ self-hosted ]
needs: [ build ]
if: ${{ (github.ref == 'refs/heads/main') && github.event_name == 'push' }}
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v4.1.1
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 🚀 Run Docker Compose on Production
if: ${{ github.ref == 'refs/heads/main' }}
env:
NODE_ENV: production
run: |
docker pull docker/image:version
docker compose -f docker-compose.yml up -d
docker system prune --all --volumes --force
This makes sure nothing funky happens before my changes go live.
3. Deploying on Self-Hosted runner
Here’s where things get interesting. Instead of relying on a managed hosting platform, I use an IONOS VPS to self-host my site. This gives me full control over the server, costs less for high traffic, and integrates perfectly with Docker.
All that was needed was to follow the GitHub instructions for setting-up a self-hosted runner, installing docker and it was done! The system was now on autopilot! 🛫
Challenges I’ve Faced
Writing Good Tests
At first, I didn’t write enough tests. This led to some embarrassing bugs slipping through. I’ve since learned that even basic tests (like checking if pages load) can save a ton of headaches.
Keeping It Simple
It’s tempting to over-complicate your CI/CD setup. I started small and added features as I needed them, which kept things manageable. Though sometimes, the simpliest things are the best.
Final Thoughts
CI/CD has totally changed how I manage my blogfolio. Updates are faster, deployment is stress-free, and I spend way less time worrying about breaking stuff. If you’re still manually deploying your site, I highly recommend giving CI/CD a try.
Start simple—set up GitHub Actions for testing and building your site, then hook it up to a hosting service. Once it’s running, you’ll wonder how you ever managed without it.
Happy CI/CDing! 😊