Personal website

This project entails... everything you are looking at right now! 

I thought it would be cool to have my own website where I could show off some of the work I have done. I also thought it would be nice for myself to get an overview of what I've been doing over the years. 

Inception

The original idea was to create a modern and minimalistic portfolio website using pre-existing component libraries, but I quickly figured out that it looked... well... very boring. I wanted something more unique! I ended up with the "pixel art"-style you are looking at right now. I thought that was a fitting theme for someone who is very passionate about game development. 

The tech stack

I initially started researching different technologies I could use to create this website. I had a few different ideas from the very start:

  1. I wanted to use a CMS solution due to the flexibility it offers. I wasn't entirely sure what I wanted this website to be yet, so future-proofing was essential.
  2. I wanted the website to be fast - both because it's great for SEO, but also because slow websites are the worst. In order to fulfill this criteria, I decided that building a static site would be ideal. 

Regarding point 1. I ended up choosing Strapi CMS as my backend. Partly because it's so popular and partly because I wanted to learn how it worked. 

Regarding point 2. I first started looking into Gatsby and SvelteKit , but decided to go with NextJS in the end. NextJS has a beautiful combination of server-side rendering (SSR), static site generation (SSG) and client-side rendering (CSR) , which allows for great flexibility.  I'll admit though, these concepts are a bit confusing to differentiate at first. 

Static site + Content Management System - How do these two work together?

The site you are looking at is a completely static site. It does not fetch any data from any CMS when you are browsing it. How is that possible, when you just said you are using a CMS you might ask? Well, the deployment of this website is split into two parts:

  1. The first deployment deploys NextJS and Strapi to a staging environment. This staging environment is where I edit and preview all the content for the website.
  2. Afterwards, I run a second deployment where NextJS builds a completely static site by fetching data from the CMS during the build stage itself. Clever, right? This allows me to use a CMS solution for flexibility, but also reap the benefits of having a static site! 

The result is production-optimized, static files that can be hosted on any static website cloud provider. Excellent speed, low cost and no security hassles!

Automation

The steps outlined above were automated using two Jenkins pipelines running on my Homelab. For the staging environment, Jenkins pulls the latest Git changes and creates custom docker images for the frontend (NextJS) and backend (Strapi). My Jenkins server runs as a docker container itself, so when building the images they are automatically available in the local Docker image registry. If I was working for a customer, I would have pushed the images to a centralized container repository instead of utilizing this shortcut. 

When I have made changes in the staging environment, I can manually trigger a deployment pipeline that builds the static website and pushes all the generated files to a Github repo that has a Cloudflare Pages automation configured.  

Pixelated style

To achieve the pixelated style I used various different tools and techniques:

  1. For the pixelated borders on buttons and boxes/panels I used the CSS property "clip-path". This allowed me to have pixelated borders that work for dynamic content. Clip-path can be quite complicated though, so I found a very nice website that generates this for you . There is also a great blog on his website that explains how this works in more detail.
  2. Artwork was created by me using a well-known pixel art program called Aseprite . It contains a lot of great tools for creating pixel art specifically.
  3. In order for the pixel art not to look blurry (happens when browser scales up images), the images are purposefully scaled up beforehand when exporting from Aseprite. Browsers expect images to be photorealistic and therefore choose an inappropriate scaling interpolation method that works poorly for pixel art (making it blurry instead of crisp). 
  4. The artwork you see is displayed using regular CSS background images with repeating enabled.