Writing This Blog - Part 2

Title

Created: 2024-01-03

In the second post on this site I give a follow up to the original post about why I wrote this blog. In this post I discuss, for those interested, how I wrote this blog, my experiences with it, technology decisions and some things I learned.

To view the first post, please click this link here

Outline of History

OK, so how did I make this happen (finally). Well this has been in the works for probably at least a year now but went through various pause stages for various reasons. I realised earlt that I could deploy a website without too much difficulty at pretty low cost (unless it becomes super popular I guess), but I wasn't sure how to write the frontend.

Things I was keen on at the time:

  • I wanted to be able to write blog posts straight to a Git repo, push it and have it auto-deploy itself. It was important that when writing blog posts I could use my standard dev setup (largely NeoVim in a terminal) and not have things like development or deployment get in the way of writing blog posts.
  • I wanted to showcase existing skills and learn new skills. In particular, I didn't want to just take something off-shelf even though that would have been quicker.
  • I wanted this to stand out a little bit. No ads, anything I wanted I could do, that kind of thing.
  • I wanted it to be hosted on the cheap and to be cool.
  • I wanted changes to be easily testable.

My first thought was (knowingly full well that it may end badly) can I write it in Rust as that would be the most fun, entertainment value counts here. Whilst that may sound completely wild I knew that you could compile Rust to WASM but didn't know how feasible it was. Another benefit was I'd learn a bit about that technology too, worth a punt I figured.

For reasons to be outlined below this failed. I did manage to write something working and got it deployed to AWS and I believe I'd have got it right in time in time but I ran out of time and energy for this, work got really busy as it does.

Many months then passed again until I found myself explaining Git rebasing for the not first time. I thought about putting such an article on dev.to as I'd done previously (personally I loathe Medium for reasons I won't go into here and refused to use them. Then I thought I've been meaning to brush up on React so I decided to look into using that. As far as sensibility goes it's clearly more battle tested than the Rust option.

After a couple of months of plugging away I finally got what I wanted and you're currently viewing the end product. I deployed a NextJS app where I'm writing the articles using MDX (JSX but for markdown) and deployed to CloudFlare pages as a statically generated site.

Experience of Writing it in Rust and WASM

Old Rust/WASM Blog

Figure 1: Old Rust/WASM Blog

Whilst my memory of this part of the process was a while back I will do my best to recall the details.

The rough process was:

  • I wrote a basic webpage with a left nav, a footer and some basic content in the middle;
  • I deployed it to AWS in an S3 bucket with a CloudFront distribution in front of that and other supporting infrastructure;
  • I had to write some code for handling the parsing of a markdown file and displaying it on the site.

Figure 1 is a screenshot of the status that it got to (that just took me a while to get running as it happens) after which point I ran out of time and energy and stopped working on it for a while (let's hope that doesn't happen again, but it may do, time will tell).

Writing the Basic Webpage

This initially involved me relearning some basics of frontend like HTML and CSS as it had been a while since I'd done much in these areas. After this I had a rough idea of what I wanted, something pretty simple to start with where I had a photo of me, a footer with my Email, GitHub and LinkedIn links.

It unfortunately wasn't responsive and I hadn't spent much time looking into how to do this kind of thing properly, it sure didn't look great on mobile.

After this I had to choose some basic technology. I'd already settled on Rust (to be cool :doh:) and WASM and I found a few things that would help with this. I settled on using Yew which was probably the most well known at the time. I had also trialled using Leptos but it seemed to not be quite as mature at the time (at least that's my recollection, it could well have improved by now as well).

Once I had the basic design done it was pretty straightforward to get it into Yew as Yew is very much the Rust communities version of React. In fact this works really nicely with Rust's macro system, where sometimes I've criticised Rust macros this is an excellent use case of them.

Deploying to AWS

So I had the basic static webpage now that compiled into a WASM file and I wanted to find the best way of deploying this to a cloud.

As a Platform Engineer I was very used to Azure cloud at the time and also had some experience in AWS as well. I chose to use AWS at the time for two reasons, I thought it would be cheaper than Azure and I needed to learn a bit of AWS as that was going to be the technology on my next project at work.

I figured out reasonably quickly that the easiest way to do this was to deploy the WASM to an S3 bucket and I put that behind a CloudFront distribution largely to be more secure. This along with the plumbing to setup HTTPS and Route53 was setting me back about 60p (British pence) a month, on an extreme month (to be fair I probably got about 0 traffic) it might be 61p. This was practically entirely the 50p + tax that the Route 53 hosted zone was costing me, the rest was basically nothing (don't let anybody tell you cloud always ends up more expensive than on premise, it all depends).

This seemed to work quite well but then I had to figure out a nice way of making this a bit more dynamic.

I also had this fully automated with an Azure DevOps workflow that would compile Rust code and deploy using Terraform to a code bucket but it took a long time to compile as I had to install trunk every time I made a change which took a long time.

Writing the Markdown Handling Code

This is where things got a bit trickier, everything worked great until I needed to generate HTML from Markdown.

The first thing I thought was can I just get something to statically generate at build time the HTML needed from markdown and then use that. The problem here is that it would regenerate the whole WASM again for the whole site and if I get enough blog posts then (presumably) we'd get a bigger and bigger site that's all or nothing. Not necessarily the end of the world for a small blog, and probably a pointer to something I already knew, that WASM wasn't the right tech here.

The other option was to dynamically get the markdown from an API and dynamically generate the HTML from there in the WASM. This would have worked and solved the above problem and I did manage to get an AWS Lambda deployed written in Rust that served this purposes with the surrounding infrastructure required. It worked, but it wasn't great and needed more work.

It was similarly automated and would deploy automatically every time we made a change on the main branch.

Experience of Rewriting it Using NextJS

New Site Original Design

Figure 2: New Site Original Design Mobile

New Site Original Design

Figure 3: New Site Original Design

Then when it came to look at NextJS I decided to rewrite this blog site from scratch. Some simple things had changed in what I wanted and essentially all I had previously was a "proof of concept" at best, it certainly wasn't what you would consider production ready if doing professionally.

Writing the Basic Webpage

I was never really happy with the original design so I ended up starting again. I read up a lot about producing responsive websites and finally figured out how to do this kind of thing, in my case using Tailwind CSS. Tailwind CSS is excellent in my opinion incidentally, this feels like how I always wanted CSS to be when you're using reusable components like we do in things like React.

I ended up producing something like the above sites in Figures 2 & 3, particularly from Figure 2 you can see I made a bit more effort to be responsive. However, I wasn't really happy with this still, the left nav seemed to be a bad choice to me in the end (not just become of the squashed image that I've since abandoned). Most blogs I was looking at that looked a bit more modern seemed to have moved away from this and towards a header at the top. I tried moving the header to the top and was a lot happier with how it looked. The hamburger menu for mobile I already had which was pieced together from bits I'd done previously and I was pretty happy with that.

I also got DALL-E to generate some images like the cloud image that you see above (at least at time of writing) which then kind of dictated the colour scheme (and I was quite happy for it to do so to be honest, I didn't want to get bogged down in this for something that is just a personal blog).

After a while I ended up with something closer to what you currently see (sure it's been tweaked since but the basic premise was there).

Rewrite in NextJS and Deploying to CloudFlare

Once I had the basic webpage I needed to rework it so that we were using NextJS. I'd also looked at Remix and a couple of other options but settled on NextJS purely because it seemed to be more popular and thus probably more useful.

The good news about NextJS though was that it was really easy to deploy using CloudFlare (I'm pretty sure Remix would be similar). You can hook the github repository up yourself and it'll just take care of everything for you. I wanted a big more control than that so I'm deploying it myself through my own GitHub actions which was pretty quick to write and seems to be working well for me. I used the instructions here for creating the bare bones and added on top of that basically.

I decided early on that a static website seemed best and was worth the effort of going to as I couldn't see any reason I'd need any dynamic content based on data from a server, also this was slightly further outside my comfort zone and this is a good thing.

My experience of NextJS was that separating between client and server components was the most frustrating part and figuring out how to use one vs the other in different parts was difficult. Sometimes what you do in an npm run dev doesn't work when you run a full build with npm run pages:build because you've put fontawesome icons in a server component and it doesn't warn you. Part of the problem here was that I was using the new app router in NextJS (as recommended) but the whole internet gives answers to questions based on the old pages router, even a lot of new pages.

A good example of this was building the component to list posts that can optionally take a tag and only display those tags. It was really difficult figuring out how to do this and I realised after half a day of getting frustrated it's because it can't (easily) use JS you write in the browser. My thinking was it should be possible for me to provide a single static list of all posts and I should be able to get the client side browser to narrow that out based on a tag (or even tags). Obviously I couldn't use a server to do this as there isn't a server (less I go to middleware which I didn't want to do, part of the challenge). Eventually I got it to statically generate a post listing page per tag that we have and that worked great, but it was difficult following the documentation in NextJS on this kind of thing.

Writing Markdown in MDX

Apart from this, I had a pretty positive experience with NextJS and React and the site turned out well. One of the big plus points for me was MDX.

Originally I had a plan for Markdown that I would generate jsx pages pre-build time from markdown files, similar I was doing on the previous Rust/WASM blog. Then I found out about MDX which is brilliant. In a nutshell I can now write a markdown file and get that to just automatically display, if I do want something in it that requires HTML/CSS though I can still do that, something like this displays the Figure component I wrote for example:

<Figure
  src="/images/large-logo.png"
  width="1024"
  height="1024"
  classes="lg:w-6/12 lg:float-right lg:mx-4"
  alt="Title" />

This was taken from the top of this document incidentally.

This seems really extensible too and at the time of writing I've only really scratched the surface. I look forward to seeing what else I can do with this in time.

Asciinema

Figure 4: Output from `btm` Process

Another big plus point of writing my own site, given the total control I know have is that if I want to do something it's just a case of can I figure out how to do it.

One example of this, I wanted to be able to show terminal videos but without the big overhead of having to make a video and get people to download large files. In comes Asciinema, I've certainly read articles of people claiming they don't like it but I can see how this could really help me in some articles, so I wrote a react component for showing Asciinema which I can add in by just doing the following:

<AsciinemaPlayer
  cast="writing-this-blog/btm-process.cast"
  classes="w-full lg:w-6/12 xl:w-3/12 pl-4 pt-2 xl:float-right"
  caption="Figure 2: Setup Git Repository in Terminal" />

This example is taken from the article I'm writing on Git merging and rebasing. Here's an example of btm running on my machine in Figure 4. At the time of writing we see that Asciinema is not perfect, but btm is a pretty complex TUI and it's still not a bad effort showing that in a JS library.

Lessons Learned

CloudFlare is Great

As mentioned above, deploying through CloudFlare is an absolute pleasure, especially (and probably mostly) when using technologies that they explicitly support. I've moved the DNS for strottos.dev to CloudFlare from AWS, and that has become so much easier to handle now.

CloudFlare even have a Terraform plugin which I'm using to deploy this.

How to Create Images

One of the things that largely put me off doing frontend work for many years was not writing HTML or CSS or JS (though I still find CSS frustrating) but also when you're going to write something like this yourself you need to think about web design, images, layouts, fonts, lots of things that by and large neither interest me nor align with my skillsets.

The mountain of Generative AI tools around now made a difference here. DALL-E was absolutely brilliant at generating pure images and absolutely terrible at putting text around them, plus to generate technical diagrams I still needed something but between draw.io (as everyone still seems to call it) and Figma I seem to be doing OK so far. Figma has a free plan which is really good for this kind of thing, I've not done much in it so far but it seems excellent.