For the past couple of weeks, I’ve been rebuilding my personal website from scratch, live at https://jiahao.codes with the source code on GitHub. In this article, I’ll tell the story of this long overdue rewrite and talk about the new static site framework I eventually settled on, Gatsby.
For a bit of background, I originally built my website while I was an undergraduate back in 2016. It was a single page React application, with the design based around an interactive search box where visitors could type in things. The application would then change based on what was typed in, to show projects I’ve done, like a website resume or portfolio. I tagged it on Git for posterity here.
Some drawbacks were that the content was very coupled with the code to style the page, and it was difficult to change the theme without having to rewrite a lot of code. It uses a customized version of JSON Resume to display data, but ultimately I didn’t do a good job and it was a bit of a mess.
Furthermore, being a single page application, it takes a little too long to load just to display some static content. I wanted to add routing and different pages to add blogging functionality, which it wasn’t really suitable for without major refactoring.
This led me to pick something very minimal and lightweight to rebuild it. In my time at Grab, I worked a little on maintaining our engineering blog which was built on top of Jekyll. I liked how minimal it was, you just had to pick a theme and drop in your posts in the markdown format. There is clear separation of concerns between the content and the site design.
It’s nice that pages, layouts, and categories in Jekyll are just small building blocks that are composed together to build a website, making it easy to reason about how everything fits together. I picked the Hyde theme to start off, and played around a little with the CSS to touch up a few areas.
When delivering content to users on mobile devices, it is important to optimize delivery of images to the users. Users on smaller mobile devices should not need to load large image resources, but instead should load the appropriate image for their viewport. HTML5 specifies the
srcset attribute for
<img /> tags which is ideal for this.
However, it would be a pain to have to manually convert images into different sized thumbnails for a post. I wanted an automated image processing pipeline to automatically resize the images extracted from the markdown documents, and then automatically populate the
srcset attribute on the images in the output HTML document. I found the Jekyll Responsive Image Plugin great for this. It allows me to create templates which will be used by Jekyll when rendering the markdown and automatically does the image resizing.
Gatsby is a static site generator that can render sites from markup documents using templates defined as React components. It functions similarly to Jekyll, where you can pick a starter project, drop in some markdown documents for articles, and be rewarded with a website with minimal effort.
Let me briefly give a high level overview of how Gatsby works from my short experience using it.
Developing the application is the same as developing a React application, with useful things like hot module replacement to aid easy development already set up by Gatsby. What’s different is that there is a framework in place to use GraphQL queries to pull content into the client side browser environment. React components can define a query and the component will be hydrated with the result of the query as props when it is rendered.
For example, I defined a
PostTemplate which will be used to render pages for articles.
<PostTemplate /> component needs to be rendered into a page, the accompanying exported
pageQuery, a GraphQL query is made, and the results are passed in as props into the component.
The real magic happens when the website is compiled into a production bundle. Running
Because of the APIs exposed by Gatsby for interfacing with its internals, powerful plugins can be built to extend the core functionality of Gatsby and reducing work by developers.
- Can be extended with a
gatsby-node.jsfile in the root of the project
The Node.js APIs let plugins extend or modify the heavy lifting performed by the Node.js process when compiling the application. Your gatsby-node.js file can export functions which modify the GraphQL data that is provided to React components when they are rendered. The APIs are also used by plugins to extend the internals of Gatsby e.g. the default webpack config can also be customized here.
Take the example of what happens during the processing of markdown files into pages. The gatsby-source-filesystem plugin scans directories and from files it finds, creates File nodes. These File nodes are then processed by gatsby-transformer-remark, parsing the markup into HTML with the Remark markdown processor.
- Can be extended with a
gatsby-ssr.jsfile in the root of the project
The server side rendering APIs allow hooks to be defined to modify the rendering process of the application. For example, the Typography.js Plugin uses this to inline the styles required into the DOM head when rendering.
- Can be extended with a
gatsby-browser.jsfile in the root of the project
Finally, the browser APIs allows plugins to run code on lifecycle events while Gatsby is running in the browser. The Google Analytics Plugin uses these APIs to track the location of the user on route changes.
The best part about using Gatsby is that there plenty of plugins available leveraging these APIs that give us new features almost for free. Want to add offline mode to your application? RSS feeds? Styled components? Just lookup the available plugins and drop them into the
Jump over to my website to read the follow up post where I showcase the amazing integrations and features I have set up, to be on the cutting edge of web development!
Check out the source code for my site on GitHub!