For a web developer the hardest thing to do is to build your own site. I imagine this is the same for any profession, I often hear about contractors in trouble with their spouses because their own home is in disrepair. The basic problem stems from two places. First, you spend all day doing this to make your living, do you want to spend more time doing it for free (yes I know investing in your business isn’t technically free, but it doesn’t generate an immediate pay cheque). Second, for me at least, is indecision. How do I want it to look? What style? What language am I going to write it in? Unlike client work, this is all up to you. There’s no provided brief or design to go by. So the first step, like any other job, is to outline what you want.
For this iteration of the site I decided I wanted an SPA (Single Page Application) style with an inline contact form and smooth scrolling navigation. I also wanted a blog. The site had to be fast, sub two second page loads, and accessible.
I could have done all of this with WordPress, but honestly the main portion of the site doesn’t really need a CMS. In my mind the main reason for a CMS is to allow a non-technical client to easily update their content. Since this isn’t a concern here, a CMS just added bloat. It would also significantly increase page load times based on unnecessary database queries.
Since I wasn’t using a CMS I decided to build the site using the Slim PHP Framework. I chose Slim because all I really needed was easy routing, there is no database and most PHP Frameworks include an ORM and database connectivity leading to more unnecessary bloat. Slim also allows you to use middleware, so this easily allowed me to add functionality to the site. I added Twig templating to keep my HTML nice and clean and a SendGrid middleware to handle the contact form. SendGrid is nice mainly because it adds really nice analytics on your emails.
To avoid reinventing the wheel, I decided to use Twitter BootStrap for the CSS. I also used Gulp as my build tool to do things like compiling SASS to CSS, concatenation of CSS and JS files and compression of images.
So that covered the main page. I wrote a basic router that loads certain page variables such as the OG:Tag information and the Social Media link data. It also handles the POST request from the contact form. The page is made up of multiple small templates to make the HTML easier to read and edit and all the main content is written directly in HTML.
So now I had to decide how to handle the blog. This would have been a non-issue if I had gone with WordPress, but now I was left with deciding how to handle the blog.
Option 1 – Write each blog post in HTML just like the main page. This isn’t really practical in a couple of ways. First, HTML isn’t really a lot of fun to write in when it comes to creative writing. It also means that for every post I would have to update any blog listing pages or teasers to reflect the new post.
Option 2 – Write each blog post in JSON and load them from a flat file. This solved the problem with updating the post listing pages and teasers, but JSON is an even worse way to write creatively than HTML is. One problem solved, the other made worse.
Option 3 – Use some sort of external writing room/software and import the result to the site. This seemed the best approach, so this is what I did using WordPress as the writing room.
Making it work
WordPress, as of version 4.7, has a JSON REST API built in, so getting the data out of a WordPress install is straight-forward. It is a pretty simple thing to write a route that pulls the data from the WP-API and populates the page. That defeated the performance concerns I made a priority though. Now not only was I waiting for WordPress database queries I was waiting for them to transmit across two domains to populate my blog posts (and worse the teasers on the main page).
The solution was to create a function that retrieved the WordPress posts, generated a posts.json file local to my site and also copied all the images used in the posts to the local server.
So now the blog loads from a JSON file locally, and the images are loaded locally too. The final step was making it so that any time I wrote, or updated a post these local files would be updated locally without manual intervention. Thankfully there is a great plugin to accomplish this feat. HookPress allows you to generate a Web Hook on most of WordPress’s internal functions.
It was as simple as adding a Web Hook every time WordPress saved a post, to call the function on calder.io that updated the posts.json file with any new posts/edits and downloaded all the images from the posts to the local server.
The results are significant. This post scores 99% on Page Speed using GTMetrix with a load time of 1.0 seconds. The same post loading from the WordPress site scores 88% with a load time of 2.0 seconds.
There is still work to do, like adding categories and tags but so far I am quite pleased with the results and the performance.
Sometimes you have to think outside the box. WordPress is a very versatile tool but for this particular use case it offered more than I needed. Being able to use its excellent writing room experience and leverage its built in API meant I got the best of both worlds.