How I built my Website

Trying to figure out how to build my website was a challenge for me. As a web designer, I wanted it to be fully customisable, but I also wanted ease of use to reduce friction and make it easy to maintain.

This is not a tutorial. It's more of an outline of what I considered when creating my website.

These were my requirements:

  • Ease of use
  • Fully customisable
  • A blog part where I can write articles
  • Aesthetically pleasing

Finding the right platform

WordPress as a platform was quickly ruled out. I then considered using React/Next.js-based website. However, the static generation and lack of CMS was a huge hurdle for my ease of use objective.

There are a number of solutions for writing posts that dynamically compile in NextJS, such as Josh W Comeau's site which has posts written in Markdown:

A great feature of his blog workflow is the way he can use native React components in posts, thanks to next-mdx-remote.

However, as a person who has never used Markdown before, I wasn't ready to start learning its quirks, plus since editing a post in MD is the equivalent of editing a text file, it lacks many features native to CMS's such as the ability to preview drafts and automatic timestamps. Josh mentioned these problems he came across in the "Downsides" section.

I then came upon Vercel's Next JS with WordPress demo:

The idea is to use WordPress as the backend CMS, and to use Next.js as the interface, hosted with Vercel. Every time the site renders, data is fetched from the WordPress database via a plugin called GraphQL. This is useful as it means that the WordPress site isn't accessed every time users visit the site, reducing overhead and loading times.

Plus, WordPress has a solid interface for managing posts, pages, authors and the like.

I started building off the base repository, adding a landing page and moving the posts page to appropriately named /posts. Since Vercel is the company behind Next.js, I build the entire site with the idea of hosting it on Vercel once production has been reached.

Implementing WordPress pages

Another thing I wanted to do was to create a pages mechanism that dynamically fetches pages created on WordPress, and makes them available on the Next.js site at the same slug. To do this, I created a file at pages/[...slug]/index.js. With Next.js dyanamic routing, the [...slug] part of the filepath would be replaced by the slugs of individual pages.

The getAllPagesWithSlug and getPageBySlug functions are based on the functions that get posts from GraphQL:

Making Next.js sassy

Another obstacle I came across was implementing Sass in Next.js. Throughout the course of my web design journey, I became accustomed to using Sass files which includes a lot of syntactic sugar making it much faster to write stylesheets. The solution I found was to use an aptly-named sass NPM package. Having little to no knowledge on Next.js config files, I used next-compose-plugins to make it easier to use multiple plugins in my project. In the end, my config file looked like so:

WordPress + custom React components?

With a solid platform for writing and publishing posts while being able to code my own custom React pages, the only thing that I lacked to meet feature parity with Josh's blogging system was a way to implement custom react components in my posts.

In my research, I came upon the react-jsx-parser module, which provides a component for converting strings of raw JSX into react components. Perfect!

What I ended up doing was creating custom character sequences, [ | and | ] in my wordpress posts, which are a signal to my <Post> component to interpret the text as JSX and not HTML:

However, I quickly ran into a battle with the way WordPress formats HTML... it's simply not made for JSX. I would insert a "custom HTML" block, happily type my JSX tags and close the post editor once I was happy with everything, only to come back and see that WordPress had turned everything into lower case, replacing my <Code> tags with <code> ones and wreaking absolute havoc on my Next.js frontend.

Because of the way React works, only capitalized tag names are treated as components and not as DOM tags.

Not letting myself get discouraged, I wrote a hacky find and replace algorithm which matches lowercase tag names with component names and replaces them with the capitalized ones if there is a match.

Hooray! This means I can use my own components such as the ones used on this post, <Warning> for the orange disclaimer at the beginning, and my own <Code> component for syntax highlighting.

Deploy Next.js on every post update

How can Vercel possibly know when a post has updated and to rebuild the entire site? you may ask. Thanks to a WordPress plugin called Vercel Deploy Hooks. Every Vercel app comes the ability to create Deploy Hooks, unique URLs which when visited will trigger a rebuild of the site. All you have to do is create a hook and feed it to the Vercel Deploy Hooks WordPress plugin.

Design

With everything implemented on the mechanical side of things, one important key of my website was design. All the work I did meant nothing if I was left with a clunky, 2007s remnant of a site.

My homepage has a mesh gradient animation that actually works on WebGL, such as the one used on the Stripe.com homepage:

Another choice to make was the color scheme. I wanted the site to feel fresh and airy, so I settled on pastel for the accent colors, using black, white and cream for the primary colors:

#ffffff

Primary

Copied!

#edeae6

Secondary

Copied!

#000000

Tertiary

Copied!

#F4BFBF

Accent 1

Copied!

#FFAB6E

Accent 2

Copied!

#FAF0D7

Accent 3

Copied!

#8CC0DE

Accent 4

Copied!

When it comes to fonts, I use three different ones. Four actually, if you count the monospace font used in my <Code> components:

Title - Migra

Heading - Poppins

Text - Inter

Monospace - Monaco

I considered using Poppins for text, but because of its typographical quirks it made it hard to read at small sizes:

Why would the ascender of the "h" be higher than the capital "T"?? What about the dot of the "i"???

I then resorted to Inter for paragraph text, a beautiful font which is made specifically for screens.

Room for improvement

As always, there is a number of things that could be done better. I'm still battling with GraphQL trying to figure out a way to filter posts based on categories, and I'm hoping to one day implement a search feature!

I ran into an issue when fetching images hosted on the WordPress server. Many web-hosting services have hotlink protection, which prevents access to images from external sites. This is done based on the Referer header, and I added an API route in order to scrape images from my WordPress site:

Another performance improvement I would like to make is image loading times: While I should be seeing speed improvements with next/image, there is a delay before images load when fetched from the external WordPress website. I'm assuming the images aren't caching properly and they are fetched each time from the WordPress serve, which results in a delay.

There are many accessibility enhancements to be made as well, such as adding alt attributes to all images, making sure tab works on buttons/links and color contrast.

Felix

Felix

Last edited:

Last edited:

F

More posts

Cover Image for Locate Website Visitors in Next.js with IP and Supabase

Locate Website Visitors in Next.js with IP and Supabase

Using an IP lookup API, a backend database and Next.js middleware, we’ll explore how to display the location of the last visitor on a website.

Cover Image for Making the Internet More Human

Making the Internet More Human

Navigating the internet has become difficult with all the accessibility issues, pop-ups, cookie banners and advertisements. We’ll explore different ways to make the web a more welcoming place for humans.