Skip to content
GitHub

Adding CMS

Headless CMS with Sanity for blog posts and marketing content.

cd packages
npx sanity init  # Create new Sanity project

pnpm add next-sanity @sanity/image-url

Environment:

# apps/web/.env.local
NEXT_PUBLIC_SANITY_PROJECT_ID=your_project_id
NEXT_PUBLIC_SANITY_DATASET=production

packages/sanity/schemas/post.ts:

export const post = defineType({
  name: "post",
  type: "document",
  fields: [
    { name: "title", type: "string", validation: (Rule) => Rule.required() },
    { name: "slug", type: "slug", options: { source: "title" } },
    { name: "body", type: "blockContent" },
    { name: "publishedAt", type: "datetime" },
  ],
});

apps/web/lib/sanity/client.ts:

import { createClient } from "next-sanity";

export const client = createClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
  dataset: "production",
  apiVersion: "2024-01-01",
  useCdn: true,
});
export async function getAllPosts() {
  return client.fetch(`
    *[_type == "post"] | order(publishedAt desc) {
      _id, title, slug, publishedAt, body
    }
  `);
}
export default async function BlogPage() {
  const posts = await getAllPosts();

  return (
    <div>
      {posts.map(post => (
        <Link key={post._id} href={`/blog/${post.slug.current}`}>
          <h2>{post.title}</h2>
        </Link>
      ))}
    </div>
  );
}

Deploy Studio: pnpm sanity deployhttps://your-project.sanity.studio

Pricing: Free 100k requests/mo, $99/mo for unlimited

Alternative: Contentful

Sanity docs · Next.js guide