Building a 300 page website with Gatsby & Craft
It all started with ‘can we change just this one thing on our site?’
Anyone who works in an agency knows what it’s like when it comes to working on your own stuff. You’re so busy working with clients on their projects, that when you notice pain points on your own website, they get put on the back burner. Eventually though, you spot a block of free time in your schedule and you can finally tackle the pile of jobs that have been building since the last redesign.
We sat down to discuss the pain points on the Bluegg website that we’d discovered over the 2 years of using it. When the dust had settled, it turns out nearly every page needed some significant changes, so it felt best to give the team free rein to re-design our website from scratch.
With a fresh re-design comes the opportunity to try new technologies and dev team felt this would be a great opportunity to use Gatsby for a larger and more complex project. And complex it was...
Getting content from Craft
I’m not sure if you know, but here at Bluegg we use Craft as our CMS of choice. We try not to mention too much why we think it’s superior, except maybe here, here or here. We knew it was possible to use Craft CMS headless-ly, and since we’re using Gatsby we needed that data via GraphQL. We used the excellent CraftQL Plugin by Mark Huot to add a GraphQL API to the CMS so that we could get to the data.
Update: Craft 3.3 now has a GraphQL API built in and a headless mode. Pixel and Tonic must have been reading our tweets.
Our site acts as a portfolio of our work and so images are very important. One of the big benefits of using Gatsby is a built-in image component, specially designed to work with Gatsby’s GraphQL queries. It offers the ability to lazy-load, transform, and resize images for different device sizes. To do all of this, Gatsby needs to access images locally to be able to process them. However, all of our images were in a Craft CMS install on another server. We would need to pull all of the images into the site at build time. To do this Jack built a Gatsby source plugin to fetch the 1000-ish images from Craft and bring them into Gatsby.
This was a long struggle. Many blog posts read, Twitter chats with the Gatsby team were had, and following a tweet from @jlengstrof (Gatsby’s Head of DevRel) got Jack on the right path. After a couple of iterations, we have a working plugin.
To give you an outline of what the plugin does:
- We created an API endpoint for all asset urls in Craft
- Create a new plugin in Gatsby and then loop through each URL
- Within the loop, create a new Gatsby File Node and assign the url and all other relevant info to it
- Create an imageNode for each image within the loop and then link these two nodes via their ids
Then run ‘gatsby develop’ and head over to your GraphiQL, and search for the new node that you’ve created.
And just like that (after a few minutes of pulling down images), your Craft CMS images are available in Gatsby ready to use. We're not convinced it's as good as it could be and maybe there is more that could be done to use the Gatsby Cache more effectively, but it will have to do for now.
Crossing the line, just about
Now we had the content, but that caused us another problem. Deploying a Gatsby website is normally incredibly simple. Our usual method is to link the repo to Netlify, click approve, and after a couple of minutes your website is live. Deploying is also easy, deploying when code is pushed to a Git repository/branch. Not this time.
We found that Netlify has a time limit for builds (it’s 15 minutes per task in case you’re wondering). Years of content meant Gatsby's build took too long and Netlify was timing out.
We needed an alternative platform to host our website. We decided to move the project over to Amazon Web Services (AWS) Amplify. It was annoying that we weren't going to be able to use Netlify, but Amplify looks pretty good, if not quite as user friendly.
Image source: The Next Web
AWS Lambda lets you run server-side code without provisioning or managing servers - incredibly handy since we’re building a static website. Jack created a Lambda function that handles the contact form’s input and sends it to our email address using Simple Email Service. We use AJAX to submit the data to the URL provided by SES and we’ve now got a “Serverless” ™ contact form running on Gatsby.
We still have a build time of nearly 20 minutes in production. This is less than ideal. The Gatsby team have been talking about incremental builds since day one and once this feature is released, this problem will hopefully go away. It truly sucks though.
Legacy content & uber flexible templates
One of the pain points identified by the design team was not being having enough layout flexibility when creating work case studies. Jack built a new grid layout, which gives the author more flexibility when laying out case studies.
No live preview
One of Craft CMS’s best features is live preview, and breaking the news to the design team that they would lose live preview and that they’d have to wait upwards of 15 minutes to see their changes on the live website didn’t go down well.
The quickest fix was to recreate the templates in twig, to use with live preview. This allows the team to preview the content they were entering into the CMS. It's not exactly slick, but the problem may not last for long. The Gatsby team have announced that live preview is currently in beta (currently only for Contentful). Hopefully this feature will be released soon and someone will get it working with Craft's new headless preview feature. 👀
Videos and images are still expensive and slow things to download. We have had to do quite a bit of performance tweaking for loading of videos, fonts and the homepage animation to help improve the perceived performance. Our website now looks and feels like it loads very quickly on a 3G connection, even if a lot of the loading is done in the background.
On top of this, Gatsby's special sauce makes the website blazingly fast if you’ve visited before. We're also using page transitions to navigate between content (if JS is available). The site is looking and feeling pretty slick.
We couldn’t get the page transitions to play nicely with a Service Worker however. This is the first problem we want to solve when we get a free block of time.
A good website is never really finished
The reason we think it’s great to experiment with new technologies when we redesign and redevelop our own website is we’re testing them out to see if they can be used in our workflow to better serve our clients going forward.
We’re big believers in eating your own dog food at Bluegg and we couldn’t recommend these technologies to clients without knowing their benefits and limitations on a project of this scale.
Now that we’ve gone through the process of building a project of this scale and done a lot of the discovery that comes with that (looking at you createRemoteFileNode), the next time we use Gatsby and Craft CMS together, the dev time will be reduced, which in turn leaves time to focus on other aspects of the project.
Was using these technologies together difficult at times? Yes.
Have we learnt even more about React and Gatsby? Yes.
Would we do it again?
Gatsby is great and fun to build with, but it doesn't feel ready to use on sites of this size (combined with a CMS). The issues above come with the territory when you're on the cutting edge. We're happy(ish) to put up with the issues in order to play with a new toy. There is no way we could ask a client to put up with a 20 minute build time though. However in a 6 months I think a lot of the issues we had will be less of an issue as Gatsby matures and Craft adds features to version 3..
Any questions about this blog post? Get in touch with us via Twitter.
This project was so long and arduous it lasted longer than the main developer, Jack, who has decided that he'd rather live in London than spend another minute working on this. Just kidding :) Thanks to Jack for all his hard work on the build and this post which I have shamelessly stolen (and ruthlessly edited). Have fun in the big smoke!