Not Just Another WordPress Site

Not Just Another WordPress Site

One of my first tasks when I started at AO.com as a Front End Developer was to build AO’s Tech Blog. This was my first experience using Gatsby, Typescript, GraphQL and Terraform amongst others so I naturally felt a bit nervous. It was also my first time working in a dedicated Front End team, which was brilliant. As a new starter I fended off imposter syndrome at times, but it was all worth it to see the final product go live with my name against it.

Now we have a pretty neat IT blog that’ll let the team share ideas amongst the wider community, and I had a ton of fun with all the different technologies used to bring this all together.

We wanted to use WordPress as our writing platform because almost everyone here is familiar with its admin area and WYSIWYG editor. However, the front end of WordPress can be restrictive as you are limited by your chosen theme’s functionality, and we didn’t want to rely on plugins.

We therefore chose to separate the content and the front end by building a ‘headless’ blog. We used Gatsby, a static site generator, to help us with this process. Gatsby has a dedicated plugin for working with WordPress, gatsby-source-wordpress, which allows us to query the content from our WordPress instance using the REST API. There are lots of other data-source plugin options available too.

Using Gatsby also means super-fast page loads, fantastic image compression and a rich offline experience. Gatsby compiles React page components into static HTML files, which makes load times almost instant.

Image compression is handled using its own native image processing library, gatsby-image, with help from GraphQL and Sharp. The GraphQL query will create multiple thumbnails with optimised PNG and JPEG compression. Gatsby-image will automatically set up a ‘blur’ effect (as seen in the above header image) and lazy load images further down the page.

Service workers can be used to provide an almost seamless offline experience. Again, Gatsby has a handy plugin for this, gatsby-plugin-offline. A service worker will run in the background, separate to the web page, and allow access to features that wouldn’t otherwise need user interaction or a page load. This increases the availability of the blog when served over intermittent connections, and also provides functionality like background synchronisation.

As mentioned earlier, Gatsby uses GraphQL to query the data being requested via the REST API.

The GraphQL function allows us to run arbitrary queries against the local WordPress GraphQL schema… like the site has a built-in database constructed from the fetched data that you can run queries against. (Gatsby Blog)

GraphQL also comes with an in-browser IDE, GraphiQL, that lets you explore your data and schema, which will be available at http://localhost:8000/___graphql when you have your development server running.

Here is an example from our main page query:

export const pageQuery = graphql`
    query($id: String!, $related: [String]) {
        wordpressPost: wordpressPost(id: { eq: $id }) {
            title
            content
            date(formatString: "MMM DD, YYYY")
            author {
                name
                avatar_urls {
                    wordpress_96
                }
            }
            featured_media {
                localFile {
                    childImageSharp {
                        fluid(maxWidth: 1200) {
                            ...GatsbyImageSharpFluid_withWebp
                        }
                    }
...

If you are familiar with WordPress you will no doubt recognise some of the data that is being queried, such as the post title, content, author name, author avatar and featured media. This helped me greatly when I first started working with GraphQL as I have worked with WordPress a lot, and as I recognised the shape of the data I was able to work my way around the post and page queries relatively easily.

One of the great strengths of WordPress is its familiarity to so many developers and content-editors alike, which was one of the reasons we chose it as our content provider. It is easy to use, allowing authors from a wide variety of backgrounds to add content including images, videos and code snippets. We have implemented a code syntax highlighter using Prism.js so all our code will display nicely.

Most importantly, WordPress can send push notifications, or webhooks, triggered by various actions. This meant we could implement a continuous deployment process based on different triggers, such as a new post being published in WordPress or one of our developers releasing a new feature in the codebase. For our WordPress trigger, we used the ‘publish post’ action which is fired (you guessed it) every time a post is published (or saved). This means the latest version of our blog is deployed every time this webhook is triggered.

These triggers feed into our Gitlab deployment process, which uses Gitlab CI/CD to deploy the blog when we deem appropriate. Alongside our WordPress webhook, we also automatically deploy when a new release is pushed to our master branch. This is handled by a Runner setup in Gitlab which is all configured in our .gitlab-ci.yml file. Here is a small section from the test stage and the beginning of the build stage for our development environment:

test:
stage: test
script:
- npm install
- npm run test:ci
coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/
except:
- master
- tags
- triggers

buildGatsbyDevelop:
stage: build
script:
- npm install
- npm run build
artifacts:
paths:
- public
...

Our runner will handle three stages: test, build and deploy. It will run through our unit tests using our preconfigured scripts (Jest), then build the blog using Gatsby, and then finally deploy the blog to our AWS bucket.

Which brings us to Terraform, the tech choice for configuring our blog infrastructure. Using Terraform meant we never had to login to AWS, allowing us to have the exact same process for deployment every single time. We can configure our entire AWS setup within one file, .main.tf, with things such as public access permissions, IP blocking, error documents, and environment tags.

This makes our entire deployment process faster and more reliable than a manual process. It also means we can handle everything from within the Front End team, without bugging other colleagues with deployment-related questions.

Finally, we have used TypeScript to keep our code tidy and ease the learning curve for other developers who want to contribute to the codebase, who may be more familiar to other statically-typed languages.

From a personal perspective, TypeScript helped me pick up on errors in my code as I was writing it, rather than after it had been compiled. This made development faster and smoother, and generally more enjoyable once I was used to defining types. It also gives us access to the latest JavaScript features, as TypeScript is compiled down to a version of JavaScript that will run on all browsers.

I hope you enjoy exploring our blog, and hope you can take something away from our learnings here at AO IT. We’ll be posting new tech articles from all across our IT team and we’ll also be expanding the blog functionality in the near future.

Jigsaw photo by Hans-Peter Gauster on Unsplash