Intro
During these crazy times of uncertainty, quarantine, and practicing social distancing, many people are looking for ways to stay productive and taking this “me” time to do that one thing they’ve been putting off forever. Those “todo” list items that you never seem to have the time to accomplish. This can be taking online courses, learning new recipes and cooking more, learning or improving your yoga practice, learning an instrument, etc. Everyone is trying to find ways to stay sane while being trapped in their homes.
For me, the primary task that has been taking up all my free time over the past couple of months has been rebuilding my personal portfolio website, finally! And I couldn’t be happier. I built the first version of this website 8 years ago in 2012 when I finished school in web design. It was a static website with static content built in good ol plain HTML, CSS (Sass), and jQuery (including lots of jquery plugins). Not that there’s anything wrong with that or anything. But I’ve been wanting to back it up with a CMS to manage all my content and rebuild the front end with React. I’ve been curious about Gatsby for quite some time now and wanting to build something in it.
I’ve also been working with WordPress primarily now for a little over a year in my current full-time job with Alley Interactive. And because of this, I’ve been researching alternative CMS solutions to see what modern CMS products are out there these days. And finally, why not add a blog to the mix? I’ve been wanting to start one for a while now to write about web development and my travels around the world.
Now I’ll discuss the process, tools, and the great experience I had while building this site.
So, what is Sanity?
Sanity is a CMS software that acts as your single source of truth for all your content, data, and assets. It allows you to easily structure your content, create “post and content types” through easily configured JSON schemas. It is built on top of Node and React, super-fast, easy to extend and customize, and includes real-time updates/collaboration and hot module live reloading. It’s amazing 😍
I discovered Sanity while listening to Wes Bos’ podcast, https://syntax.fm/ because Sanity is one of their sponsors. I’m glad I finally looked into it because I’ve really been enjoying building my site on top of this software. Which reminds me, I need to tell the folks at Sanity how I heard about them because I totally forgot to use the link in Wes’ podcast to get a discount when signing up.
With Sanity, you choose your front end and just query your data through GraphQL or their own query language called GROQ. This was my first time using GraphQL on a project besides tutorials and let me tell you, I love it compared to using traditional REST methods to fetch data. They have tons of guides and starter packages for almost every front end framework you can think of. Since my website didn’t need a user system and its only fetching data, Gatsby seemed like a great choice. As for your data and scaling, good news, Sanity takes care of all that for you with their “fully managed, reliable and compliant, cloud-hosted database for your content”.
As far as pricing is concerned, it’s definitely one of the cheaper options out there with their pay as you go for user’s model. Get started for free with 3 users, 500k API CDN request per month and just $1 USD per 100k additional, 10GB bandwidth per month, 100 listeners, 100k API request, 2 datasets, 5GB in assets and 10K Documents. Now that’s a pretty 🔥 deal!
More reasons I dig Sanity
- Developer Experience
- Being able to easily customize the dashboard, white label it with CSS variables, add icons has been really nice.
- As someone who has worked with WordPress for quite a while, I really enjoy working in a full javascript stack.
- Slack community
- There is a very active slack community with Sanity. They are very active with post weekly newsletters, blog posts, tutorials, and helping other developers who need it.
- Open-source
- There is a blossoming ecosystem of plugins and its very easy to extend.
- Hot module live reloading
- Any time you make a content update or update to the UI, see your updates instantly. No messing around with a Webpack config. It just works. This is a breath of fresh air coming from WordPress.
- Image and asset handling
- “Sanity comes with a powerful image pipeline that does image metadata(dimensions, colors etc) extraction on upload, and on-the-fly transformations in front-end usage. All served from a global CDN.”
- The combination of working with images in Sanity, graphQL, and the Gatsby image plugin is magnificent.
- Being able to control the focal point is not something easily done in WordPress and something I struggled with just recently. It comes stock in Sanity 😍
- Content Editing
- Sanity uses a content editing tool called Portable Text . “Portable Text is a JSON based rich text specification for modern content editing platforms.”
- “Portable Text is an agnostic abstraction of rich text that can be serialized into pretty much any markup language, be it HTML, Markdown, SSML, XML, etc. It's designed to be efficient for real-time collaborative interfaces, and makes it possible to annotate rich text with additional data structures recursively. Portable Text is built on the idea of rich text as an array of blocks, themselves arrays of children spans. Each block can have a style and a set of mark definitions, which describe data structures distributed on the children spans. Portable Text also allows for inserting arbitrary data objects in the array, only requiring _type-key. Portable Text also allows for custom content objects in the root array, enabling editing- and rendering environments to mix rich text with custom content types.”
- This makes it super easy to extend the editor, add custom components, and serialize it on the front end with whatever front end framework you like.
Why use Gatsby?
This was my first time using Gatsby and it’s been a great experience. The developer community is large, very friendly, welcoming, and inclusive. The plugin ecosystem is outstanding and the documentation is very thorough. And it’s blazing fast! What's that you say? Prove it! Happy to.
Before:
After with Gatsby
And this is the beauty of static generated web sites.
From their home page, “Gatsby is an open-source, modern website framework that builds performance into every site by leveraging the latest web technologies such as React and GraphQL. Create blazing-fast apps and websites without needing to become a performance expert.”.
Let’s go over situations when it makes sense to use Gatsby as your front end framework. For simple personal websites and blogs such as this one. Simple eCommerce sites with a lot of content that doesn’t change to often. Small to medium size marketing and business websites are great for Gatsby.
But larger enterprise size sites, apps behind authenticated content, sites where lots of routes are getting dynamically generated, when most of the page doesn’t get rendered until it requests data on load in the browser is better suited for a framework such as Next.js. To learn more about GatsbyJS check out their docs and tutorials at https://www.gatsbyjs.com/
What is GraphQL?
GraphQL is a query language for API’s that gives the front end power to ask exactly for what data you want. “GraphQL queries access not just the properties of one resource but also smoothly follow references between them. While typical REST APIs require loading from multiple URLs, GraphQL APIs get all the data your app needs in a single request. Apps using GraphQL can be quick even on slow mobile network connections.” I really enjoy this query language and the JSON like schema you use to request exactly what data you want. It’s also pretty easy to learn, check out more on their site and docs at https://graphql.org/.
Here is an example of one of my queries to grab all the data I need from a portfolio project on my site.
1query ProjectTemplateQuery($id: String!) {
2 sanityProject: sanityProject(id: { eq: $id }) {
3 id
4 youtubeId
5 videoPoster {
6 alt
7 asset {
8 _id
9 url
10 title
11 assetId
12 fluid(maxWidth: 720) {
13 base64
14 aspectRatio
15 src
16 srcSet
17 srcWebp
18 srcSetWebp
19 sizes
20 }
21 }
22 }
23 _rawBackground
24 _rawProcess
25 carousel {
26 title
27 slides {
28 image {
29 alt
30 asset {
31 _id
32 assetId
33 url
34 fluid {
35 base64
36 aspectRatio
37 src
38 srcSet
39 srcWebp
40 srcSetWebp
41 sizes
42 }
43 }
44 }
45 }
46 }
47 categories {
48 title
49 id
50 }
51 clientName
52 employerName
53 launchDate(formatString: "MMMM YYYY")
54 projectName
55 projectTags
56 projectThumbnail {
57 alt
58 asset {
59 assetId
60 _id
61 fixed(width: 350) {
62 base64
63 aspectRatio
64 width
65 height
66 src
67 srcSet
68 srcWebp
69 srcSetWebp
70 }
71 url
72 }
73 }
74 projectUrl
75 title
76 video {
77 asset {
78 url
79 title
80 mimeType
81 assetId
82 }
83 }
84 slug {
85 current
86 }
87 relatedProjects {
88 _id
89 slug {
90 current
91 }
92 title
93 }
94 }
95 }
My Process of Rebuilding this Site with Sanity CMS and Gatsby
I quite like the current design on my site. And in my opinion, the design is probably not hip to the newest design trends. But hey, it’s functional, easy to navigate, readable, and I get lots of compliments on it. So for these reasons I decided to do very little in terms of changing the UI design. Like I mentioned earlier in this article, my previous site was static HTML, Sass, and jQuery. It felt so damn good to get rid of jQuery when building this site. Gatsby comes with CSS Modules by default and it’s also what we tend to use most of the time on projects at my job. So I decided to stick with CSS Modules and PostCSS for some extra fanciness.
Because I’m new to GraphQL and Sanity, my data model for all my “Documents” and “Objects” took some iterating and I still think there is some room for improvement. But it’s pretty dialed for the most part. My Documents are Settings, Projects, People, Categories, About Section, Carousels, Contact Form, Countries, Jobs, Nav Menu Blog Post, Resume Page, Services Section. I probably should have created just a general Section document and then created all my sections within that document model, but I decided to leave it because some sections just vary a lot in the content they offer.
Once I had the foundational items sorted and dialed, I built the site section by section, components, templates, etc. I created a Trello board and basically followed an agile scrum-ish type workflow to keep track of what needed to be completed and also making sure I didn’t forget anything. I would say the one and the only item that was a pain in the ass when building was the Contact form. I could send a form in PHP with like 7 lines of code, it was great. When using Node and Netlify, I have to use a serverless function that gets executed on form submission and then use a 3rd party service to send the form data. It was pretty frustrating how much code I had to write to get the contact form functioning.
For the layout and UI design I did not use any UI framework or 3rd party grid system. Just CSS Grid and Flexbox, which is a very good feeling to have as little dependencies as possible. All the pages and routes for project pages and blog posts are dynamically generated with Gatsby’s Node API function. Here’s a snippet from this site where I am generating a page for each project based on one template with data that is queried with GraphQL.
1async function createProjectPages(graphql, actions, reporter) {
2 const { createPage } = actions;
3 const result = await graphql(`
4 {
5 allSanityProject(filter: { slug: { current: { ne: null } } }) {
6 edges {
7 node {
8 id
9 slug {
10 current
11 }
12 }
13 next {
14 title
15 id
16 slug {
17 current
18 }
19 }
20 previous {
21 title
22 id
23 slug {
24 current
25 }
26 }
27 }
28 }
29 }
30 `);
31
32 if (result.errors) throw result.errors;
33
34 const projectEdges = (result.data.allSanityProject || {}).edges || [];
35
36 projectEdges.forEach((edge) => {
37 const id = edge.node.id;
38 const previous = edge.previous;
39 const next = edge.next;
40 const slug = edge.node.slug.current;
41 const path = `/project/${slug}/`;
42
43 reporter.info(`Creating project page: ${path}`);
44
45 createPage({
46 path,
47 component: require.resolve('./src/templates/project.js'),
48 context: { id, previous, next },
49 });
50 });
51}
52
Some other “gotchas” while building this site was getting build errors on deploying to Netlify. This happened a couple of times because of npm modules I added that were trying to access the browser window without checking to see if it exist. And this is just the nature of using a statically generated site, you can’t do that. Plus its bad practice anyways.
Well, this pretty much sums up my enjoyable experience of rebuilding my site with Sanity and Gatsby. I hope you are taking the time during quarantine to learn something new, build something awesome, or whatever it may be that’s keeping you sane. This is the first public blog post I’ve ever written so if you have any feedback or wanna talk shop, feel free to reach out to me on the contact form on the home page 😉 Cheers! 🍻