How I Use CI/CD to Update My Blogfolio Without Losing My Mind
Written by Thomas Béchu
November 29, 2024

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:

  1. Checkout Code: Grabs the latest version of my repo.
  2. Install Dependencies: Installs everything my site needs (like npm packages).
  3. Run Tests: Checks that the site builds without errors and links work.
  4. 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! 😊

2024-present Thomas Béchu. All Rights Reserved