How I Built My Personal Website

matjones

Mat Jones

Posted on January 22, 2021

How I Built My Personal Website

I had a lot of fun building my personal site, because I used it as an opportunity to learn some new tech. Let's take a tour of what's in it.

Core

At it's core, the site is powered by Next.js and React. I used Next.js because the content is mostly static, which is a use-case Next excels at. Next enables Server Side Rendering (SSR) by default, but also supports Server Side Generation (SSG), which generates static HTML pages at build time. You can read more about the differences between SSR and SSG in this great article by the Vercel team.

GitHub logo vercel / next.js

The React Framework

Code Style

In the project, I used React functional components with hooks almost exclusively because I find I can write much cleaner and more concise components using the hooks API vs. traditional class-based components; the only exceptions being _app.tsx and _document.tsx, which extend base classes from the Next framework. A _document.tsx file allows you to customize the base HTML template that the React app is injected into, while _app.tsx allows you to use shared layouts, add an Error Boundary, import global stylesheets, and more.

Build Customization

Markdown Copy Content

I've also added @mdx-js/loader and @next/mdx to my build configuration, which allows me to import markdown (*.md) files as React components. Using this technique allows me to keep some of my copy text (such as the "about" page) in markdown rather than having to manually write out the JSX for it, which is just simpler and easier to maintain.

Working with SVGs

I'm using SVGR to transform my SVG files into React components, rather than loading them via <img src="/my-image.svg"/>. This means my SVGs will be loaded with the markup, rather than being loaded asynchronously, which can help eliminate Cumulative Layout Shift (CLS) issues. It's as simple as customizing your next.config.js file to use the @svgr/webpack loader for *.svg file types, then importing them in your components, a la:

import SvgAvatar from "/avatar.svg";

const MyComponent: React.FC = () => (
  <MyComponent>
    <SvgAvatar/>
  </MyComponent>
);
Enter fullscreen mode Exit fullscreen mode

DEV Blog

I previously wrote another article about how we can use the DEV API to load your articles in order to embed them in your own website.

I combined this technique with Next's getStaticProps method to load all my DEV articles at build time, and statically generate the blog pages for my site. To keep the pages up-to-date, I configured the GitHub Action that builds and deploys my site to run periodically. I configured it to run every 30 minutes, however in practice it seems like for some reason it actually runs closer to once every hour. If your CI/CD pipeline is actually time-sensitive, I recommend not using GitHub Actions.

Design

UI Framework

On a recommendation from a friend, I decided to learn Blueprint.js and use it to build my website. After building lots of components using it, tweaking it, and styling it, I think it has become my new favorite React UI framework.

Right out of the box, everything looks amazing, cohesive, and enterprise-quality. Their component library is pretty extensive, and includes just about everything you'd want in your base toolkit, from simple stuff like navbars and buttons, to layout things like cards, to more complex components like interactive menus, progress bars and drawers. It's pretty easy to customize and compose the built-in components to make more complex designs. My only complaint is that there are a select few places I had to use the dreaded !important CSS directive to override some specific styles from Blueprint's stylesheets.

Stylesheets

My go-to language for stylesheets has been SCSS for a long time, because, well, let's face it, writing vanilla CSS just sucks.

One of the greatest features of CSS preprocessors like Sass is the ability to write nested styles; if your markup can be nested, then why can't your stylesheets?!

You can also easily re-use bits of common styles via mixins, and even run compile-time logical operations to further customize the generated stylesheets. It's incredibly powerful and extensible.

Deployment

My site is hosted statically on GitHub Pages, configured to deploy from the gh-pages branch of the repository. Deployment happens automatically on push, periodically, and can be manually triggered via a GitHub Actions workflow. The date of the most recent build is injected into the app at compile time via an environment variable in next.config.js.

💖 💪 🙅 🚩
matjones
Mat Jones

Posted on January 22, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related