The Journey of this Site
From PHP to Golang

Over the years, this website has progressed through a few different versions. Was rewriting the code each time strictly necessary? Not really ⁠— it was perfectly functional in its original form ⁠— but I am always on the lookout for ways to tweak or increase the efficiency of my code, and I like to think that my personal website makes a nice, relatively low-risk place to try out new frameworks or technologies without the pressure and high stakes of somewhere like my actual job.

(I was also trying to think of something to write about, so that the “writing” section of my site wouldn’t be entirely empty, and this seemed like as good a topic as any.)

In the beginning: PHP

My very first version of this site was written in PHP. That choice was borne primarily out of a desire to be as DRY as possible ⁠— I had a header and footer that needed to be repeated on every page, and copy/pasting the header HTML everywhere didn’t seem to be the best solution. Enter PHP and its include and require functionality.

I was also looking for the ability to dynamically render content for my lighting design portfolio. Each portfolio subpage has the same format ⁠— just with different information, names, and pictures ⁠— so I was looking for a solution that would allow me to add a performance to my portfolio easily, without having to manually upload a new HTML page or repeat all the boilerplate for the different sections on each page. Here, I was swayed by PHP’s ability to read a parameter (say, the name of a show in the portfolio) from a URL and grab the corresponding data from a data file or database before sending the finished page to the viewer.

The PHP site did what it needed to do, and I was mostly happy with it. Particularly, since the HTML was rendered server-side by the PHP interpreter, the pages delivered to end users were extremely lightweight. JavaScript was only required for the Lightbox photo viewer on portfolio pages, but even that could gracefully degrade if the user had JavaScript turned off ⁠— full-size images would simply open directly in a new tab.

Everything was not sunshine and roses, however. There were two major reasons why I wasn’t happy with the PHP implementation of my site. First off, relying on server-side rendering obviously meant that I needed to have a server, as opposed to a simple CDN for static files. I knew that using a full-blown virtual server (like Amazon EC2 or Rackspace) was a ton of overkill for my tiny little personal site, so I tried out a series of “managed hosting” providers. By and large, those providers were missing things that I really wanted ⁠— one wouldn’t let me use an SSL certificate unless I bought it from them, one didn’t allow FTP access, etc. And I was frustrated knowing that I was paying mostly for computing power that I didn’t use.

There was another downside to consider ⁠— the .php at the end of all my URLs. PHP has a very bad rap among the developer community, which is not entirely undeserved (although recent PHP frameworks and the PHP 7 release have made things quite a bit better) ⁠— and I was worried that viewers would make implicit assumptions about me and my coding skills (or supposed lack thereof) just because the code was PHP. I was wary of the bad impressions that I was unintentionally causing, especially when the bad impressions could be being formed by potential employees and professional connections.

With all that in mind, having freshly earned my AWS Solutions Architect certification and having gained a good deal of experience with Angular 4 at my job, I set out to take my site client-side.

Angular, aka “I guess my website is an ‘app’ now”

I decided that I wanted to migrate away from server-side PHP, both so that I could have a relatively strong showcase of my ability to work with newer technologies (as in, technologies from the 21st century1), and so that the site would be composed entirely of (from the server’s perspective) static files, meaning that I could take advantage of much cheaper and more easily scalable hosting solutions. (In my case, that meant Amazon S3 and Cloudfront.2)

One of the things I enjoyed most about rewriting this site in Angular is just how easy it is to develop with Angular.3 I don’t necessarily mean “easy” in the patronizing “anyone who can’t code in Angular is stupid” sense, but rather in the sense that the Angular framework removes or takes care of lots of small-to-medium-size annoyances inherent in “traditional” web development. For instance, it automatically namespaces CSS on a per-component basis ⁠— no more specificity hell if you need, say, a <ul> styled differently on different parts of a page, and no more having to worry about screwing up the styling of other pages by changing the styling of one component.

There’s also the templating system. Though I was certainly not using its full power for my personal site, it was still a treat to use ⁠— specifying the outer framework and layout of the site in only one place, and then plugging in individual pages and components, felt like what I had wanted to do all along.

And finally, Angular’s CLI comes with a live-reloading development server. So I could run the server, open localhost:4200 in my browser, and then every time I saved a file as I was working, the browser window would automatically reload with my changes! Coming from the PHP workflow, this was a treat.4

As with the PHP site, however, things were not perfect. Although writing and developing in Angular was great, I couldn’t shake the feeling that I was being… wasteful. This site is 90% static content ⁠— did I really need to be burdening my site with all of the baggage that a single-page client-side app entails? A fresh load of the home page of my Angular site was about 470 KB, which is a hell of a lot for the small amount of content that’s on that page. And what’s more, the site (obviously) wouldn’t work at all without JavaScript enabled. Sure, the vast majority of people browse with JS turned on, but I felt I was rather pointlessly alienating the small fraction who don’t. (And also alienating some search engine crawlers, but SEO is a whole different can of worms.) So once again I set out to find a solution that checked all of my boxes.

The present day: Hugo

I began looking at “static site generators” ⁠— sets of scripts that take content (often written in Markdown), translate it to HTML, and plug it into HTML templates to build a publishable static website. For my use case, these combined most of the advantages of Angular with most of the advantages of PHP ⁠— that is, I could make use of a powerful templating system and the ability to quickly test and iterate, while still being able to serve an extremely lightweight, no-JS-required site to end users.

I explored several options in this space, including Metalsmith and GitHub Pages’ Jekyll, but those options fell short ⁠— Jekyll (and others) because they seemed entirely preoccupied with blogging (and, as I mentioned on my writing page, I hate the word “blog,” and certainly don’t want my writing to be the main focus of my site), and Metalsmith because I could just never actually get it to work (and its documentation leaves a lot to be desired).

In the end, I found Hugo, a static site generator written in Go, which seemed to be pretty close to what I was looking for. And the icing on the cake was when I found Netlify’s Victor-Hugo, a boilerplate/starter kit for Hugo that is preconfigured to use PostCSS, Babel, and Gulp for precompiling and pipelining CSS, JavaScript, and static assets. I was sold ⁠— I cloned Victor-Hugo and got to work, and (after a few minutes spent configuring Gulp) was up and running… and the rest, as they say, is history. (Fairly recent history at this point, but history nonetheless.)

I’ll admit there were some minor growing pains: around CSS (Angular’s automatic CSS namespacing had spoiled me) and templates (Hugo uses Go’s built-in template grammar, which was new to me). I was also wary at first of being limited by Markdown’s formatting abilities, but those fears were quickly assuaged when I learned that you can freely mix HTML into .md files as needed ⁠— no special syntax or escaping needed:

You can **mix** HTML and Markdown, 
like in this <em>pointless</em> example.

The above snippet renders as:

You can mix HTML and Markdown, like in this pointless example.

I also thought quite a bit about how I’d be reimplementing my portfolio with Hugo. I even briefly considered keeping just that portion of the site as an Angular app. But I thought I could do better. I realized I didn’t need the portfolio to be truly dynamic ⁠— the portfolio content itself only changes relatively rarely ⁠— rather, I simply needed the portfolio to be easily extensible and backed by data in a standardized format.

I read up on Hugo’s capacity for “data-driven” content ⁠— which, in Hugo-speak, simply means a page that gets its content from JSON, YAML, or TOML. The data is grabbed from either a local file or a specified URL during the build process, and then is substituted into a template page. I already had an API in place (which I was using with the Angular site) to get data for portfolio pages as JSON, so it was not much effort at all to write a Hugo template that used the existing API to get info for the portfolio pages.

To recap, based on the benefits I was looking for from Hugo: does it have a powerful templating system? Yes. Is it easy to test and iterate? Yes (just lke Angular, it comes with a built-in development server). Is it lightweight? Definitely. A fresh load of the homepage of my Hugo site is only 85 KB ⁠— less than a quarter the size of loading the exact same page from my Angular site.

Do I think I’ll stay with Hugo forever? I don’t know at this point. Several years ago, I would have thought I’d be content with my PHP site forever. But things change ⁠— and in the web development landscape, things change pretty rapidly. For now, though, I’m happy, and I can’t immediately point out any shortcomings with Hugo. But if that ever changes, this page will definitely be getting an update!

  1. PHP was created in 1994, and publicly released in 1995. (Source) [return]
  2. In case you’re unfamiliar with AWS, S3 is a static file storage service, and Cloudfront is a CDN. In my case, I obviously didn’t need Cloudfront for serving my site to every corner of the world with the least possible latency, but serving directly from S3 isn’t compatible with the combination of custom domains and SSL. You can have one or the other ⁠— a custom domain via a CNAME record, or SSL with the default Amazon URL ⁠— but to have SSL with your own domain, you need to go through Cloudfront. And I do want both of those, so Cloudfront was my only option. [return]
  3. Before the React fans start lining up outside my door with pitchforks, I’m sure React is great too ⁠— I just haven’t worked with it, so Angular was what I went with for my site. [return]
  4. I only later learned that apparently macOS ships with a preinstalled version of PHP that you can use as a dev server for local testing. Did you know that macOS has PHP preinstalled? Yeah, me neither. [return]