Introduction: Building a Blog with Next.js & Sanity
In this video, I'm going to show you how I created the blog for Inbox Zero. It's fully open source, so you can see all the code behind it, and I use Sanity to create it. So let's get into it.
This is what the blog looks like, and then over here if I click in, you can see the article, sticky content on the side over here. And this is the blog and a bit of a read more section at the bottom.
So, you know, I wouldn't really recommend always creating your own blog, but at the same time, if you do, then it's free and you can optimize it, can change it as you want. So I wanted the full control, so I didn't mind spending a little bit of time creating it myself. It didn't take a whole lot of time. I'm using Sanity for it. Um, I think they could do a slightly better job for their documentation, but in the video, I'm going to show you how it's all set up and how you can do the same thing.
Why a Headless CMS? Sanity Studio Tour
What you'll notice is that you actually deploy Sanity Studio, which is the CMS admin area where you can go and create posts and authors and so on. So here's myself as an author. You can see the details around me and so on, my image, and then the posts over here. So here's the post that I uploaded.
And yeah, anyone can just jump in and go and edit this. So the huge benefit of this, in the past I had MDX, next-mdx for my blog, which was cool and simple when only I needed to manage it. But when I have team members that I need to bring on board, I don't really want them editing MDX files in GitHub. It was a bit annoying. So I went and set up Sanity. So this is what it looks like for them on the back end to go and edit it. Um, they're comfortable editing it with Sanity, and then this is what it looks like on the front end.
Code Walkthrough: The Blog Homepage
So let's dive into what this looks like. We're going to start from the blog homepage where you see all the different posts. That's the easiest place to start, and here you can see it's just blog/page.tsx. So it, you know, just got rendered, and this is what is going to come up.
So we're using sanity/fetch to get all the blog posts, and once we have them, we're just going to load this post component. Now I do still have the old MDX posts here, so it's a mix of the old post and new post, but Sanity is a headless CMS so you can mix and match between them.
I can have the old post here and the new posts. Sanity is basically just a backend providing me data, but if I want to have posts up here as well, hardcoded and, you know, stored in the MDX files like I had before, that still works for me. So, in the future, I'll probably simplify it to just be Sanity. There are benefits for me to doing that. But here you can see right now it's all the blog posts, and also it means you can have an incremental move over like I have done, if you're in a similar situation, so without having to move every single post over to Sanity for this to work.
Code Walkthrough: Individual Post Pages
So very simple Tailwind. Well, I need to stop clicking that. And then over here you can see postcard and it's basically just a grid of these different cards. And here you can see the UI for it for how it comes out. So very simple.
And then when we click into a post, it looks like this. So what that looks like over here, I have this post folder within it [slug]. So this is dynamic. And I do also have fixed blog post posts. These are the MDX files I mentioned before. This is how I used to have it done. But for the new post, basically if it's got a dynamic slug, it will match this one over here and it will go and basically do sanity/fetch again, load up the blog, and just display it over here on the front end. And here you can see the UI for it and so on.
Fetching Data with GROQ Queries
So jumping back to the blog contents page that we saw before, we have these utilities. sanity/fetch is one, and then postQuery is the actual query of what to to fetch. So let's take a look at sanity fetch. To be honest, I didn't write this file at all. This was just automatically created. I think I took it from another project, so I'll share that. And there was another YouTube video that helped me get started with this, so I'm going to share all of that with you.
sanity/client also, this is just I think set up for me automatically. There's image builder. So I haven't even read these docs honestly, but it just works for me. And here are the different queries. Now the queries, they use something called GROQ. I guess it's similar to GraphQL if you're familiar with that. Here you can see, like, I actually don't know how GROQ works. I haven't even read these. Most of this was just autogenerated.
Now, when I need to create a new one, I just ask AI to do it. But you can understand roughly how it works. Yeah, I want all the posts of type post, then I can also the different fields that I want. And let's say I want image URL and that's nested, I can go in mainImage.asset.url, and that's how all the blogs' blog posts are. Here you can see a single one, and current, let's say the last four we want to do some logic here. So order(date desc) [0..4]. But I didn't write this, so yeah, it just worked. The AI understood well enough how to do it, and that was enough.
Data Fetching & Caching in Next.js
So let's say I want to go and see all the posts that we just had a look at. So that's passed in over here to sanity/fetch again. So yeah, that's just an API call, we get all the data.
I did have some issues with caching around Sanity, so I just left it as revalidate: 60. So Next.js, it will always return the same blog statically, but if it's, like, it hasn't fetched in more than 60 seconds and someone comes to the page, it will return the existing cache of what it has, but after that, it will go and revalidate.
Generating a Dynamic Sitemap for SEO
One more thing I'll show you is the sitemap. I have static URLs which I just pasted into the sitemap, but I also have, now that I have lots of Sanity blog posts, so I'm basically asking Sanity for all the slugs. So here you can see, just ask for all the slugs and then I'm looping over them and creating a page, like a URL over here, which is what I need. And then the sitemap just returns it.
Now, this is part of Next.js, and here you can see if you go to sitemap.xml, I have the sitemap of all the different blog posts here at the bottom from Sanity. And that is helpful for SEO purposes. Google can now or other search engines can go and look at this sitemap and very easily find the URLs of your website.
Deploying & Configuring Sanity Studio
Now I mentioned Sanity Studio. I have deployed it, or it's just running at localhost:3000, but if you go to the deployed website studio, it will also be over there. So that's really, really cool. It's just deployed as part of your project. You can also deploy with Sanity so it doesn't have to be at /studio, you could just deploy to Sanity cloud and it would work fine as well.
Sanity is still doing a lot of the work here in terms of the data, where it's being stored. It's not being stored in one of my databases, it's being stored by Sanity, so I still am reliant on them. But in terms of this UI and the studio managing everything, this is all local.
So let's go take a look at that studio over here. And you can see we're basically just importing next-studio and yeah, the whole page is just loaded up from there. You can take a look here. That's basically everything around Studio. So very, very easy.
Some more pieces I'll show you, there's a Sanity CLI. So here we need to, if the Next.js Sanity deployment, we need to have the project ID and the dataset is basically production. This is my project ID, and this allows us to load the correct Sanity Studio. Here you have config. I think this was all automatically generated. I didn't touch it at all. Don't know too much what's happening here, but you can, let's say you didn't want base path to be studio, you could change it. And yeah, some other things you can set here.
Defining Content Schemas
Oh, something I didn't mention yet is schema types. So you can define what your Sanity project looks like in terms of the fields that are available. So most of this I just, like, used default out of the box. But here you can see the name is defined for each author and the slug and so on. And this is what will appear in Sanity Studio and what will be saved in the Sanity database as well.
Here you can see this is a field I did add, a Twitter handle for every author. So if I go over here, click my name, you will see my bio, my Twitter handle, and this. So this was actually created by me, and the AI went and sort of made this a bit better with validation and a bit of a description. But you know, just keeping it simple like this also works completely fine.
And so we have the different schemas. This code I didn't write either. It just sort of was automatically generated, I think when I set up Sanity with the CLI, I just hit that I wanted a blog and it went and created the standard types for me. And as I mentioned, the only thing I actually added was Twitter. And so yeah, if you do want to add a field like this, basically you'll just, like, restart the Next.js project that you have running, and it will automatically add in this field. And when you deploy it, the same thing, Sanity will know to display that field.
Here you have like an .env file where you can go and set certain things. It's also automatically generated. And a structure file where, I don't fully know what this does, but yeah, you can see, you know, the structure of the blog. These are different categories I have. Again, I'm assuming this is a general structure that Sanity needs to know.
Conclusion & Why Sanity is a Great Choice
So all of this code, it's part of Inbox Zero so you can go and read it and you can copy and paste it yourself. A lot of this was copy and pasted from other places, automatically generated by Sanity.
So that's the end of the video about Sanity. This is how it came out. I'm very happy with it as a headless CMS. It does exactly what I need. It provides an API for all the different blog posts and authors and structure and all of that. And it also gives marketers and non-technical people the ability to quickly add posts and like to see visually what it all looks like, which is great.
And the pricing also is really, really good. I am paying zero forever, well at least at my current size. 20 user seats, I'm not going to hit that anytime soon. Two data sets, public only, that's completely fine. My blog is public, so it does exactly what I need. And yeah, you should give it a try. Let me know what you think about it.