Introduction
Overview of Sanity and Next.js
Sanity is a powerful headless CMS that offers real-time collaboration, flexible content modeling, and a robust API for delivering content to various platforms. Next.js, on the other hand, is a React framework that supports server-side rendering (SSR) and static site generation (SSG), making it a perfect match for building high-performance web applications.
Purpose of Integration
Integrating Sanity with Next.js allows developers to manage content dynamically while leveraging Next.js’s performance optimizations. This integration is ideal for creating fast, SEO-friendly, and scalable web applications with a seamless content management experience.
1. Setting Up Sanity
Create a Sanity Project
- Install the Sanity CLI: Open your terminal and run:
npm install -g @sanity/cli
- Initialize a New Project:
sanity init
Choose a project template: Select “Blog (schema + sample data)” for a quick start. Configure your project: Follow the prompts to configure your project, including the project name, dataset, and preferred features.
- Deploy Sanity Studio:
sanity deploy
This command will deploy your Sanity Studio to the web, allowing you to manage content online.
Configure Your Schema
Sanity allows you to define custom schemas for your content. Here’s an example of a simple schema for a blog post:
export default {
name: 'post',
title: 'Post',
type: 'document',
fields: [
{ name: 'title', title: 'Title', type: 'string' },
{ name: 'slug', title: 'Slug', type: 'slug', options: { source: 'title', maxLength: 96 } },
{ name: 'body', title: 'Body', type: 'blockContent' },
{ name: 'publishedAt', title: 'Published At', type: 'datetime' },
],
};
This schema defines a blog post with a title, slug, body content, and publication date.
Add Sample Data
To add initial content:
- Open Sanity Studio: Navigate to the URL provided after deploying.
- Add Content: Click on “Posts” and add sample blog posts. Fill in the fields as defined by your schema.
2. Setting Up Next.js
Create a New Next.js Project
Start by creating a new Next.js project:
npx create-next-app sanity-nextjs cd sanity-nextjs
Install Dependencies
Install the necessary dependencies for integrating Sanity with Next.js:
npm install @sanity/client next-sanity-image
- @sanity/client: This package allows you to interact with your Sanity content.
- next-sanity-image: A helper library to optimize and render Sanity images in Next.js.
3. Configuring Sanity Client in Next.js
Install Sanity Client
In your Next.js project, create a file called sanity.js in the lib directory:
import { createClient } from '@sanity/client';
export const sanityClient = createClient({
projectId: 'yourProjectId',
dataset: 'yourDatasetName',
useCdn: true,
apiVersion: '2023-01-01',
}
);
Replace yourProjectId and yourDatasetName with the values from your Sanity project settings.
Set Up Client Configuration
The configuration above connects your Next.js application to Sanity, using the Sanity Client to fetch and manage content.
4. Fetching Data from Sanity
Create a Sanity Query
Sanity uses GROQ (Graph-Relational Object Queries) for querying content. Here’s an example query to fetch all blog posts:
export const allPostsQuery = `*[_type == "post"] | order(publishedAt desc){
_id,
title,
slug,
publishedAt,
body
}`;
Fetch Data in Next.js Pages
Next.js provides two main methods for data fetching: getStaticProps and getServerSideProps.
import { sanityClient } from '../lib/sanity';
import { allPostsQuery } from '../lib/queries';
export async function getStaticProps() {
const posts = await sanityClient.fetch(allPostsQuery);
return { props: { posts } };
}
export default function Home({ posts }) {
return (
Blog Posts
{posts.map((post) => (
{post.title}
{post.publishedAt}
))}
);
}
This example fetches blog posts from Sanity and passes them as props to the Home component.
5. Displaying Data in Next.js
Rendering Content
To display the fetched data, iterate over the posts array and render each post’s title and publication date.
Handling Rich Text and Media
Sanity stores rich text content in a structured format. Use a library like @portabletext/react to render rich text:
npm install @portabletext/react
Then, create a portable text component:
import { PortableText } from '@portabletext/react';
export default function PortableTextComponent({ value }) {
return ;
}
import PortableTextComponent from '../../components/PortableText';
export default function Post({ post }) {
return (
{post.title}
);}
6. Implementing Dynamic Routes
Create Dynamic Routes
To create dynamic routes, Next.js uses [param] syntax:
import { sanityClient } from '../../lib/sanity';
import { postQuery } from '../../lib/queries';
export async function getStaticPaths() {
const paths = await sanityClient.fetch(
`*[_type == "post" && defined(slug.current)][].slug.current`
);
return { paths: paths.map((slug) => ({ params: { slug } })), fallback: false };
}
export async function getStaticProps({ params }) {
const post = await sanityClient.fetch(postQuery, { slug: params.slug });
return { props: { post } };
}
Fetch Data for Dynamic Routes
In the getStaticPaths function, you fetch all available slugs and generate paths dynamically. In getStaticProps, you fetch the specific post data based on the slug.
7. Optimizing and Caching
Static Generation vs. Server-Side Rendering
Use Static Generation (getStaticProps) for pages that don’t require frequent updates. It pre-renders the page at build time, providing faster load times.
Use Server-Side Rendering (getServerSideProps) for pages that need to display dynamic data on every request.
Caching Strategies
- Revalidation: In Next.js, you can use Incremental Static Regeneration (ISR) by adding a revalidate property in getStaticProps to periodically update static pages.
- API Caching: Implement caching layers for Sanity API responses to reduce load times.
8. Handling Images and Media
Integrate Sanity Image CDN
Sanity provides an Image CDN for optimized image delivery. Install the necessary package:
npm install next-sanity-image
Configure and use the Image component from the next-sanity-image package:
import { useNextSanityImage } from 'next-sanity-image';
import Image from 'next/image';
import { sanityClient } from '../lib/sanity';
export default function BlogImage({ image }) {
const imageProps = useNextSanityImage(sanityClient, image);
return ;
}
Display Media in Next.js
To display media content, use the BlogImage component within your post template:
<BlogImage image={post.mainImage} />
9. Error Handling and Debugging
Common Issues
- Invalid API configuration: Ensure that your project ID and dataset in the sanityClient configuration are correct.
- Missing Slug: Ensure that all your documents have unique slugs for dynamic routing.
Debugging Tips
- Console Logs: Use console.log() to inspect fetched data in getStaticProps or getServerSideProps.
- Sanity Studio: Check your data directly in Sanity Studio to ensure it’s correctly structured and available.