Introducing the Written Realms Blog

A look at why and how the Written Realms blog was built.
Feb 27 2020

A proper blog had been on the roadmap for a long time. Announcements, dev updates, newsletters and the occasional essay so far could only be circulated using Discord, Twitter or Patreon.

Philosophically, I've always felt that the best place to host what matters most is directly on the open internet, in a place whose stack you fully control. You want to be able able to make sure your title, meta tags and thumbnails come out just right, that your URLs are stable, and that no editorial entity can censor your speech.

Social platforms are powerful tools, but ultimately they serve us best when the arrows point inward: when the tweets, the threads and the shares link back to a space that we control.

What We're Going to Blog About

We're going to start with four broad categories of posts:

  • Newsletters - Like the winter newsletter that went out today! And it is no coincidence that this blog is being published at the same time.
  • Updates - New features, important bugs fixes, new content releases.
  • Essays - On game design or some of the technology / challenges we come across. Pat has already published one such essay, Handrolling an RPG Stat System
  • Fiction - Occasionally we're going to publish new fiction that takes place in some of our worlds. One short story is currently underway, called 'The Forbidden Spark.' It will be released here when it's ready.

In time, we'd like to integrate some of the blog content with the rest of the Written Realms platform. For example, links to updates published here will find their way to the newly-built desktop-width sidebar.

Implementation - Nuxt and Tailwind

Blogs are always a great opportunity to play with new technology. I've recently rewritten the whole of WrittenRealms in Vue.js, so I'm pretty sold and invested in that general ecosystem. I also just built a new docs site in Vuetify, a Material Design framework on top of Vue, and have generally liked it.

Another framework I've been looking at is Nuxt.js. Its biggest draw for the purposes of a blog engine is that it handles static site generation. This means that while you're developing everything works more or less like how a normal Vue app would work, but when you're ready to go to production, Nuxt builds out every page that a user could visit statically. A static site performs much better than a single-page application, and is more easily searched by crawlers. Nuxt also ships with a helpful out-of-the-box integration with vue-meta, which implements easy title and description configuration.

I tried initially to use both Nuxt and Vuetify together (with the latter installed on top of the former) but was not successul at that. Using standard installers gave an older Vuetify release, and it's hard enough learning a new framework where you're constantly running into versioning problems. When I tried to manually install Vuetify on top of Nuxt, I went down a configuration rabbit hole I did not care to get out of.

Given that blogs are in my opinion at their best when they are as minimal as possible and get out of the writing's way, I decided I really didn't need a material framework for that and opted for Tailwind, a lovely css framework that helps you style things without actually writing css. Music to my ears, and I'd used it on a client project in the past and liked it.

Routing

A quick note on routing. It's typically very easy to set up a blog where the url patterns follow rough the format /posts/1/. It's trickier to let posts define their own root urls so that you can go to /about-birds/ and it shows the contents of the corresponding post, where post authors can pick any name they want. It's especially difficult when you want these routes to get generated without you having to change the frontend's code.

Solving this took a little work but we ended up making Nuxt's config load asynchronously, which thankfully the framework supports. We fetch the custom routes from the API and then instruct Nuxt to generate one static page for each of those paths. As the site is generated, each page queries the API for the post's contents.

There is almost certainly a way to improve this by fetching all of the post's contents along with their path in that initial route building call, but due to some issues with Nuxt I ran into, I'm waiting for v3 to be released. A slightly longer site generation time (an infrequent task I can run locally anyway) is not an issue at this point.