← All posts
Web Design
Late night code

Next.js + Sanity

My first attempt at building with Next.js and Sanity to develop my website and this blog.

Minuit SpenceMinuit Spence

Next.js + Sanity

I'm sure all of us here are acquainted with Next.js at this point in our development careers. I'm sure plenty of you are also familiar with Sanity aswell. Me on the other hand I am just getting used to the combo, and I honestly like how it works well together. The whole process from setup to deployment is pretty straightforward and comprehensive. I only ran into a few issues during my learning path, and I had to either restart the lesson because I overlooked a command or a path was wrong. Complete user error, and I should have just referred to the docs sooner in most cases when I didn't understand something.

Quick history lesson

Next.js is a React framework that utilizes both front-end and back-end functions and makes all requests in one bundle. Allowing for client and server content to be stored seamlessly.

Sanity is a headless CMS built in code and can be customized from the ground up or using a pre-made template. This allows for easier content management and, with a few steps, quick deployment of your site with all your content accessible with the built-in studio.

Getting Started

Okay, so on to my tutorial on how to build your own Next Sanity project. This won't be a high-level tutorial, but it will cover setting up your project. I use "pnpm" for my package manager, so that's what I'll be using throughout this explanation.

Okay, let's get started. If you don't have a project, which I'm assuming you don't, you can run the following to start a new Next.js application.

pnpm create next-app@latest next-js-sanity-tutorial --typescript --tailwind --eslint --app --src-dir --import-alias="@/*" --turbopack --react-compiler

This will build our Next.js app. Move into the newly created directory and run pnpm run dev to verify that all dependencies are installed and that you can start the development environment.

Screenshot of running the development server

Next, let's add Sanity to the project. In a new terminal window inside the project directory "blog-tutorial/next-js-sanity-tutorial" or whatever you named your project at build, run pnpm dlx sanity@latest init which will add sanity to our project. You'll be prompted to auth via CLI if you haven't already, or create a sanity user account. Name your project and select your organization, or create one if you don't already have one.

Follow the remaining prompts for creating a dataset for now; we will go with the default "production". Refer to the docs for the different dataset options and how to configure them. Add the config files for sanity in the next.js folder, typescript, embedded sanity studio, all yes. When asked what route you want to use for the studio, keep the default "/studio" option, but you can name this "/admin" as well, since this is where we can house all of the settings for our site. For simplicity's sake, we will use the Blog (schema) option, but you can create a clean project and make your own types. Finally, add the environment variables to the .env.local file. Restart your dev environment and navigate to "http://localhost:3000/studio".

Studio access page

Sign in using whichever method you set up for your Sanity account. You will be greeted with the sanity studio ui.

Sanity Studio UI dashboard

That's it... Okay, maybe not "it", but we've successfully added Sanity Studio to our Next.js application. Next, let's work on actually seeing the content that we are going to populate here.

After adding your content, we're going to get it to display in the browser. First, some housekeeping. Moving into the app folder "/src/app" were going to create a new directory "(frontend)". We will be creating a new "layout.tsx" file and moving the "page.tsx" file from the root of the app folder into the frontend directory. We will need to update the layout to show the content on the pages that are being rendered.

In the new layout.tsx file (/src/app/(frontend)/layout.tsx), paste the following

import { SanityLive } from"@/sanity/lib/live";

export default function RootLayout({

children,

}:Readonly<{children:React.ReactNode;}>) {

return (

<htmllang="en">

<body>

<SanityLive/>

{children}

</body>

</html>

);

}

In the default layout in our app directory (/src/app/layout.tsx), we need to do some housekeeping as well.

import "./globals.css";
export default function RootLayout({

children,}:Readonly<{

children:React.ReactNode;}>) {

return (

<htmllang="en">

<body>{children}</body>

</html> );

}

This will allow us to render our content from Sanity using the Sanity Live. Sanity Live allows for real-time updates to content on the live site without needing to redeploy the whole site after changes are made.

Next on the page.tsx file we pasted in from the app directory, let's change it as well, remove all boilerplate data, and paste in the following.

import { PortableText } from "next-sanity";

import { sanityFetch } from "@/sanity/lib/live";

import { POST_QUERY } from "@/sanity/lib/queries";

import { urlFor } from "@/sanity/lib/image";

import Image from "next/image";


export default async function Home() {

const { data: posts } = await sanityFetch({ query:POST_QUERY });

return (

<div>

<h1 className="text-2xl font-bold mb-4">

Next.js Sanity Tutorial

</h1>

{posts.map((post) => (

<div key={post._id}>

<Imagesrc={urlFor(post.mainImage).url()}alt={post.title}width={100}height={100}/>

<h2className="text-xl font-bold">{post.title}</h2><pclassName="text-sm text-gray-400">{post.author.name}</p><pclassName="text-sm text-gray-400">{post.publishedAt}</p>{post.body && <PortableText value={post.body}/>}</div> ))}</div> );

}

A lot is going on here, but let me break it down. First, we are converting this page to an "async" function page, which allows for queries to be made against the studio. Then, to get the data for each post, we are using the "sanityFetch" function. Our queries are coming from our queries.ts file that we still need to setup we will do that next. PortableText is for rendering all post data that is within the body. That includes all text, links, images, etc. "urlFor" imports the sanity URL generated when an image needs to be referenced for the source for "Image" that we imported from next.

Let's create the "gueries.ts" file. In the sanity directory (/src/sanity), locate the "lib" directory and add "queries.ts: file there (/src/sanity/lib). Paste in the following code. This will handle the "POST_QUERY" we imported back in our "page.tsx" file.

import { defineQuery } from"next-sanity";
export const POST_QUERY = defineQuery(`

*[_type == "post"] {

_id,

title,

slug,

body,

mainImage,

publishedAt,

author -> {

name,

}

}

`);

Now there is the possibility of type errors occurring, so we need to fix that, and we can do so by updating the scripts in our "package.json" file, but first lets export the sanity schema. Run the following command in the terminal.

pnpm dlx sanity schema extract

This will generate a schema file for our project. It's always a good idea to run a typegen script if there are any changes made to the schema or if you add any new schema types. Lets automate this by adding a few scripts to the "package.json" file.

Open the "package.json" file at the root of the project and add the following to the list of exisiting scripts.

"predev": "pnpm run typegen",

"prebuild": "pnpm run typegen",

"typegen": "sanity schema extract --enforce-required-fields --path=./src/sanity/extract.json && sanity typegen generate"

Adding these scripts automates the typegen process, and when you start the development server pnpm run dev It will automatically run the extract and update all types.

Lastly, in our "globals.css" file remove all but the tailwind import at the top of the file.

Post being rendered on home page

There we go. We are now able to view our post on our home page. Now, of course, this is a very basic way of setting up a blog. But it works; this can quickly be improved on by using components or building pages within Studio. Both of which are outside the scope of this tutorial. So now you know how to set up a basic blog structure and view of your Next.js Sanity app.

For more structured ways to improve your sanity application, visit the official docs page for the most up-to-date methods for building your site. Or if you're like me and still learning how to use Sanity, check out their Sanity Learn platform that has more in-depth tutorials and explanations. I'm taking my exam for my Sanity certified content operator this evening. Check out their platform and learn more about the tools and how seamless you can make adding content to your site.