Products
Products
Video Hosting
Upload and manage your videos in a centralized video library.
Image Hosting
Upload and manage all your images in a centralized library.
Galleries
Choose from 100+templates to showcase your media in style.
Video Messaging
Record, and send personalized video messages.
CincoTube
Create your own community video hub your team, students or fans.
Pages
Create dedicated webpages to share your videos and images.
Live
Create dedicated webpages to share your videos and images.
For Developers
Video API
Build a unique video experience.
DeepUploader
Collect and store user content from anywhere with our file uploader.
Solutions
Solutions
Enterprise
Supercharge your business with secure, internal communication.
Townhall
Webinars
Team Collaboration
Learning & Development
Creative Professionals
Get creative with a built in-suite of editing and marketing tools.
eCommerce
Boost sales with interactive video and easy-embedding.
Townhall
Webinars
Team Collaboration
Learning & Development
eLearning & Training
Host and share course materials in a centralized portal.
Sales & Marketing
Attract, engage and convert with interactive tools and analytics.
"Cincopa helped my Enterprise organization collaborate better through video."
Book a Demo
Resources
Resources
Blog
Learn about the latest industry trends, tips & tricks.
Help Centre
Get access to help articles FAQs, and all things Cincopa.
Partners
Check out our valued list of partners.
Product Updates
Stay up-to-date with our latest greatest features.
Ebooks, Guides & More
Customer Stories
Hear how we've helped businesses succeed.
Boost Campaign Performance Through Video
Discover how to boost your next campaign by using video.
Download Now
Pricing
Watch a Demo
Demo
Login
Start Free Trial
In modern web applications, Next.js manages rendering, routing, and performance, while Sanity provides a structured backend for storing and delivering content. It keeps the frontend focused on user experience while content is managed independently. Content is retrieved from Sanity with GROQ queries and consumed by Next.js to pre-render pages, generate routes, and support live previews. Editors update content directly in Sanity, and changes appear on the frontend without requiring a redeploy. This makes the workflow efficient for both content teams and developers. Prerequisites Before integrating Sanity with Next.js, make sure you have: Set up a Sanity Project : You can create a new Sanity project by following this official documentation: Installation | Sanity Docs Basic Next.js Knowledge (Routing, `getStaticProps`, etc.) Install Node.js on your development machine Set Up a Next.js Project : You can create a new Next.js project by following this official documentation: Getting Started: Installation Fetching Content from Sanity To connect Sanity and Next.js, the first step is to set up a client and write queries. This makes structured content available to your application in a predictable format, which keeps rendering logic consistent across pages. Installing Dependencies In your Next.js project, install the Sanity client: npm install @sanity/client Configure a Sanity Client Create a utility at lib/sanity.js : // lib/sanity.js import { createClient } from '@sanity/client' export const client = createClient({ projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID, dataset: 'production', apiVersion: '2025-01-01', // lock version for stability useCdn: process.env.NODE_ENV === 'production', // cache in prod, fresh in dev }) Add to .env.local : NEXT_PUBLIC_SANITY_PROJECT_ID=your_project_id Write GROQ Queries to Fetch Content Start with a query to fetch the content fields your application needs from Sanity. export const postsQuery = `*[_type == 'post'] | order(publishedAt desc) { _id, title, slug, publishedAt, excerpt, mainImage { asset-> { url } } }` This query fetches posts with their IDs, titles, slugs, publication dates, excerpts, and main image URLs, which is optimal for listing pages where you want summary information. If you want to fetch full content including the body (usually for single post pages), you would add body like this: export const postDetailQuery = `*[_type == 'post' && slug.current == $slug][0]{ _id, title, slug, publishedAt, body, mainImage { asset-> { url } } }` This separates summary fetches from detail fetches cleanly and matches common Sanity + Next.js usage patterns. Create a Reusable API Helper Summarizing GROQ queries into API helper functions avoids duplication and centralizes access to your structured content data; the individual pieces of information (like titles, slugs, excerpts, and images) that compose your documents in Sanity. // lib/api.js import { client } from './sanity' import { postsQuery } from './queries' // Fetch all blog posts (summary content for listing pages) export async function getAllPosts() { return client.fetch(postsQuery) } // Fetch single post details by slug (full content including body) export async function getPostBySlug(slug) { const query = `*[_type == 'post' && slug.current == $slug][0]{ _id, title, slug, publishedAt, body, mainImage { asset-> { url } } }` return client.fetch(query, { slug }) } Now, these functions can be imported wherever your Next.js app needs consistent, predictable access to blog post content. It reduces repetitive query code and improves maintainability. Drafts / Preview Fetches To support live previewing of unpublished draft content in your Next.js app, use a server-side authenticated Sanity client configured with a read token and useCdn: false . This ensures fresh draft data is fetched securely without using cached published content. // lib/previewClient.js (server-only) import { createClient } from '@sanity/client' export const previewClient = createClient({ projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID, dataset: process.env.NEXT_PUBLIC_SANITY_DATASET || 'production', apiVersion: '2025-01-01', useCdn: false, // Disable CDN for fresh draft content token: process.env.SANITY_READ_TOKEN, // Server-only token with read access to drafts }) This specialized client complements the reusable API helpers by enabling your app to fetch draft content securely and efficiently during preview mode, improving the editing and review workflow for content teams. Displaying Content in Next.js With content available, the next step is to render it. Using static generation ensures pages load fast and are search-friendly, while incremental static regeneration (ISR) allows content updates from Sanity to appear on the site without redeploying. Creating a Page (e.g., /blog) to List Posts Create a file at pages/blog/index.js : import { getAllPosts } from '../../lib/api' export default function Blog({ posts }) { return (
Blog
{posts.map(post => (
{post.title}
))}
) } export async function getStaticProps() { const posts = await getAllPosts() return { props: { posts }, revalidate: 60 } } Dynamic Routes for Each Post Dynamic routes let you render each post individually, ensuring scalability as the number of posts grows. Create a dynamic route at pages/blog/[slug].js : import { client } from '../../lib/sanity' export default function Post({ post }) { if (!post) return
Post not found
return (
{post.title}
{post.publishedAt}
{post.body}
) } export async function getStaticPaths() { const slugs = await client.fetch(`*[_type == 'post']{ 'slug': slug.current }`) const paths = slugs.map(slug => ({ params: { slug: slug.slug } })) return { paths, fallback: 'blocking' } } export async function getStaticProps({ params }) { const post = await client.fetch( `*[_type == 'post' && slug.current == $slug][0]{ title, publishedAt, body }`, { slug: params.slug } ) return { props: { post }, revalidate: 60 } } Optional: Enabling Live Preview Preview mode lets editors see draft changes in real time on the frontend. This reduces the risk of publishing errors and creates a smoother workflow for content teams. Step 1: Enable Preview Mode in Next.js Next.js has a built-in Preview Mode . You need to create an API route at pages/api/preview.js : export default function handler(req, res) { if (req.query.secret !== process.env.SANITY_PREVIEW_SECRET) { return res.status(401).json({ message: 'Invalid secret' }) } res.setPreviewData({}) res.redirect(req.query.slug ? `/blog/${req.query.slug}` : '/') } Step 2: Adjust Client for Draft Content When in preview mode, set useCdn: false in your Sanity client to fetch the most recent draft content. // lib/sanity.js export const client = createClient({ projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID, dataset: 'production', apiVersion: '2025-01-01', useCdn: false, // always fetch fresh data in preview }) Step 3: Secure Setup Add an environment variable in .env.local : SANITY_PREVIEW_SECRET=mySecret123