In Posts / Projects • January 1st, 2020 • CSS, JavaScript, React, Gatsby

Personal Website

This site itself is one of the projects of which I'm proudest. It is entirely self-designed with a fast, modern stack behind it.

Concept

I made this site's predecessor in high school using Squarespace's platform. At the time, it was a great way to showcase my work without saddling myself with upkeep and maintenance.

Into early college, though, I started using it as a blogging platform, and found that it was simply too restrictive. The breaking point was when I'd direct people to my GitHub account to look at my projects, because the "README" files there could be formatted better than the blog posts on my own site.

For a new site, I wanted a few things:

  • I wanted to learn something new—languages, frameworks, deployment, something
  • I wanted to be able to write blog posts in Markdown—not pasted into a CMS; literal .md files
  • I wanted code blocks in blog posts to be well formatted (long an issue with Squarespace)

Along the way, I added quite a few more things to my list. Read on for a rundown of what I ended up with.

Overview

This website is built with Gatsby, a React framework that uses GraphQL to bring data into static site generation. This approach, also known as JAMstack, means that the site isn't closely coupled to the server: it is a client-side web app at heart.

In the case of my website, I use Gatsby's site generation to transform and package content so that visitors get the benefit of quick, static pages while I get the benefit of a developer- and writer-friendly environment.

The entire website's codebase is available right here on GitHub.

Features

Light and Dark Mode

Light mode

Dark mode

I happen to swear by light mode, but those who prefer dark can find it jarring when they are met with a bright website.

The best of both worlds? Light and dark modes, automatically set based on device preference, user-customizable, and persistent between visits.

This works by using CSS variables and HTML attributes for wide browser support. The toggle switch uses React hooks and synchronizes itself across all instances of the component on a page.

Many thanks to Ananya Neogi's excellent article on the subject and Mozilla's web documentation on browser feature support.

Design Scheme

Lorem ipsum dolor sit amet

Duis tincidunt mauris at sapien fermentum porta

Integer malesuada arcu vel nisi convallis vehicula. Phasellus scelerisque justo nunc. Praesent finibus tellus at nunc dapibus elementum. Phasellus eget fermentum diam. Phasellus dignissim finibus felis a tristique.

Light mode

Dark mode

A color scheme switch isn't any good without a design language that stays cohesive and legible.

For the color scheme, thanks go to Google's Material Design Color Tool for color and legibility info and this tweet by Steve Schoger for pointers on depth cues in dark modes. Typography is done via Kyle Matthews' typeface packages, and Sass and Gatsby's support for style modules help wire it all up.

Code Blocks

// Run each time the default theme changes
useEffect(() => {
    // If we aren't storing a user preference for the theme,
    // update the theme to match the new default
    if (!localStorage.getItem("theme")) setCurrentTheme(defaultTheme)}, [defaultTheme])

To match with the light and dark modes, Markdown code blocks are styled to automatically switch between light and dark solarized color schemes. The syntax analysis is done at the point of the site's generation, resulting in a fast client experience.

Thanks here go to Prism and Gatsby's plugin and resources for it. The solarized color scheme was originally created by Ethan Schoonover and my adaptation of it is based on Hector Matos's Prism port.

Deployment

Netlify Status Indicator

This site is deployed to Netlify, with their GitHub integration providing a continuous deployment pipeline. DNS and proxying are done with Cloudflare.

Headers and redirects are made courtesy of gatsby-plugin-netlify.

In addition, Dependabot updates packages when possible. It waits for Netlify to deploy and verify branches with the package updates and then automatically merges in certain scenarios. Several GitHub actions run in tandem with Netlify to organize and approve the Dependabot pull requests. Especially for security updates, this enables live, interaction-less, verified updates. This does introduce a risk of faulty updates, but I believe there is a net benefit to updating automatically and Netlify can be leveraged to revert to a previous deployment.

Addendum: Details

I'm a bit of a perfectionist, and there's a lot of work I've done on this site that doesn't condense down to a list of features. Some of the smaller highlights that didn't make the cut:

  • Maskable vector and raster favicons are all derived from a single SVG file at build-time, with built-in cache-busting.
  • In-site navigation is dynamic and doesn't actually reload the page
  • In code blocks, the line numbers hide on mobile for easier skimming
  • gatsby-plugin-sharp and gatsby-transformer-sharp use deferred loading for images
  • It might not be obvious on first glance, but the post pages aren't the only thing generated from markdown: category and link pages are entirely generated too, complete with statically-generated pagination
  • Inline click-to-copy functionality from the contact page is nice and portable:
  • Markdown parsing is augmented to render custom components (this entire page is just a Markdown file)
  • Markdown headers are linked automatically and will reveal a link icon upon hovering
  • gatsby-plugin-manifest and gatsby-plugin-offline make this site work offline as a Progressive Web App
  • There's a significant amount of linting and workflow support in this site's codebase: beyond what Gatsby already packages in, Prettier, Husky, stylelint, and a reflected GraphQL schema are all in use
  • robots.txt files are automatically customized for deployments, so deploying from a branch via Netlify won't be indexed by search engines
  • An RSS feed is generated from all markdown GraphQL nodes descending from the posts category