Founderflow Logo

Sanity Integration

Complete guide to integrating Sanity CMS in your Founderflow Boilerplate. Learn how to set up content management, create schemas, and build dynamic blog pages.

Overview

๐Ÿ“

Sanity CMS Integration

Sanity is a headless CMS that provides a powerful content management system with real-time collaboration, rich text editing, and flexible content modeling for your blog and content pages.

โœ“

Content Management

Rich content editing with live preview

โœ“

Real-time Collaboration

Multiple editors working simultaneously

โœ“

Flexible Schemas

Custom content types and fields

โœ“

Image Optimization

Automatic image processing and CDN

โœ“

API & Webhooks

RESTful API and real-time updates

โœ“

Version Control

Content versioning and history tracking

Setup & Configuration

Environment Variables

Configure your Sanity integration with these environment variables:

.env.local
# Sanity Configuration
NEXT_PUBLIC_SANITY_PROJECT_ID=your_project_id
NEXT_PUBLIC_SANITY_DATASET=production
SANITY_API_TOKEN=your_api_token
# For development
# NEXT_PUBLIC_SANITY_DATASET=development

Sanity Client Configuration

Set up the Sanity client for data fetching:

lib/sanity.ts
import { createClient } from 'next-sanity';
export const sanityClient = createClient({
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
dataset: process.env.NEXT_PUBLIC_SANITY_DATASET!,
apiVersion: '2024-01-01',
useCdn: true,
token: process.env.SANITY_API_TOKEN
});
// Query helper
export const sanityFetch = async <T>(query: string, params?: Record<string, any>) => {
return await sanityClient.fetch<T>(query, params);
};

Content Schemas

Blog Post Schema

Define the structure for your blog posts in Sanity:

schemas/post.ts
export default {
name: 'post',
title: 'Blog Post',
type: 'document',
fields: [
{
name: 'title',
title: 'Title',
type: 'string',
validation: Rule.required()
},
{
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'title'
}
},
{
name: 'content',
title: 'Content',
type: 'array',
of: [{ type: 'block' }]
},
{
name: 'excerpt',
title: 'Excerpt',
type: 'text',
rows: 3
},
{
name: 'featuredImage',
title: 'Featured Image',
type: 'image',
options: {
hotspot: true
}
},
{
name: 'publishedAt',
title: 'Published At',
type: 'datetime'
}
]
}

Data Fetching

Fetching Blog Posts

Query and fetch blog posts from Sanity:

lib/queries/posts.ts
export const postsQuery = `
*[_type == "post"] | order(publishedAt desc) {
_id,
title,
slug,
excerpt,
featuredImage,
publishedAt
}
`;
export const postBySlugQuery = `
*[_type == "post" && slug.current == $slug][0] {
_id,
title,
slug,
content,
featuredImage,
publishedAt
}
`;

Using in Components

Fetch and display Sanity content in your React components:

app/blog/page.tsx
import { sanityFetch } from '@/lib/sanity';
import { postsQuery } from '@/lib/queries/posts';
interface Post {
_id: string;
title: string;
slug: { current: string };
excerpt: string;
featuredImage: any;
publishedAt: string;
}
export default async function BlogPage() {
const posts: Post[] = await sanityFetch(postsQuery);
return (
<div className="container mx-auto px-4">
<h1 className="text-3xl font-bold mb-8">Blog</h1>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{posts.map((post) => (
<article key={post._id} className="bg-white rounded-lg shadow-md p-6">
<h2 className="text-xl font-semibold mb-2">{post.title}</h2>
<p className="text-gray-600">{post.excerpt}</p>
</article>
))}
</div>
</div>
);
}