My personal space

Jan 18, 2020 · ☕ 5 min read

unfinished post

This is a README of this website, describing the interesting bits of the tech stack, the motivation behind it, and the goals of it.

I encountered swyx’s Learn in Public and realized I’m doing something wrong. I was doing a heckload of notes. It was before I found out about Roam, so my notes were a chaotic mess of random Notion pages, Dropbox Paper docs and sheets I took out of the printer to cover with illegible hieroglyphs. One future awaited all of them. Forgotten and lost. Thrown away with the rubbish.

“Maybe I can make them helpful for somebody else,” I thought. Spellcheck them in Grammarly. Write a bunch of MDX files. Publish them with Gatsby.

I started a blog. Turns out, blogging is hard for me. Polishing one piece of notes to “blog post quality” took a few days of writing and two weeks of minor fixes. I tried hard because I heard a lot about building a personal brand. Somebody asked how many impressions I make and where do they come from. What? I didn’t set up analytics. I don’t want to!

I want to publish the good parts of my notes and link to cool stuff I find on the internet. I want to have a personal website, like my former lecturers at the uni. A bit ugly. Practical and fun in a little weird way.

Take a look at swyx.io. It has a big heading saying “SWYX’S SITE!“. The about page is empty. These gradient link hovers aren’t pretty, but they put a big smile on my face. It’s awesome.

I’m gonna go this way. I want to stop spending half of my free evenings on this website and have fun with it.

Turns out I’m not the only one.

Here are the articles that clarified the idea for me and inspired me in the order I read them.

My goal isn’t to reach many and build my brand through a stream of targeted blog posts. I want to just enjoy having this garden. This is what gardens are about, right? Both pleasant and useful for their owner. I’m tweaking it a bit here and there, and writing posts occasionally.

I have encountered a few exciting problems while building it, and I’d love to write more about them and the solutions for them that I have implemented. I believe this website to be a good example of what is possible in a limited time with the sheer power of Gatsby. The two most interesting things I did:

  • Rendering social card images with React
  • Collecting post commits to display a history of edits in a blog post

I may turn them into standalone blog posts one day, but let me focus on the latter one here.

A Blog Post Git History

The publishing dates of posts are pretty problematic. I update my posts sometimes. Should I change the date then?

Kent C. Dodds asked why doesn’t he have dates on his blog posts said he just keeps all of them up to date. Publish dates would be confusing. I get that point, but I kind of want to keep the dates, at least for myself as a created_at information.

I firmly believe that knowing the road is more valuable than knowing only the destination.

Instead of showing fewer dates, I decided to show more. I keep my posts in a git repository, so I have a fairly good idea of what and when was changed.

Using createSchemaCustomization, I added a history field to posts frontmatter. This is nullable, so not all posts have history displayed and for those which do, I’d like to decide whether we show full commits or just a number of edits and a time span. You can find the Verbose variant in my reading list and the DatesOnly variant here, right below this post.

type Mdx implements Node {
  frontmatter: MdxFrontmatter

enum BlogpostHistoryType {

type MdxFrontmatter @dontInfer {
  title: String!
  spoiler: String!
  date: Date!
  history: BlogpostHistoryType

Based on a code I copied from a gist, I have formatted the git log in a parseable way. (see the code)

Then, I have added the corresponding property to MDXFields.

type Mdx implements Node {
  frontmatter: MdxFrontmatter
  fields: MdxFields

type BlogpostHistoryEntry {
  abbreviatedCommit: String
  authorDate: Date!
  subject: String
  body: String

type BlogpostHistory {
  entries: [BlogpostHistoryEntry!]!
  url: String!

type MdxFields {
  route: String!
  history: BlogpostHistory

Connected it all together with about 50 lines of code and a one function call in onCreateNode in gatsby-node-ts.ts.

export const onCreateNode: GatsbyNode["onCreateNode"] = async args => {
  const { node, getNode } = args;

  if (node.internal.type === "Mdx") {
    const mdxNode = (node as unknown) as generated.Mdx;

    const route = toLower(createFilePath({ node, getNode }));

    createBlogpostHistoryNodeField(args, route);

You can find the code of the function here. Adding the UI to the post layout was fairly straightforward.

to be continued

Edited 6 times between Jan 21, 2020 and Feb 07, 2020.