惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Hacker News
The Hacker News
D
Docker
GbyAI
GbyAI
Y
Y Combinator Blog
C
Check Point Blog
M
MIT News - Artificial intelligence
Martin Fowler
Martin Fowler
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Blog — PlanetScale
Blog — PlanetScale
P
Palo Alto Networks Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
V
Vulnerabilities – Threatpost
I
InfoQ
Simon Willison's Weblog
Simon Willison's Weblog
博客园_首页
T
Threat Research - Cisco Blogs
J
Java Code Geeks
Hacker News - Newest:
Hacker News - Newest: "LLM"
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
The Register - Security
The Register - Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
阮一峰的网络日志
阮一峰的网络日志
O
OpenAI News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Recent Announcements
Recent Announcements
Forbes - Security
Forbes - Security
AWS News Blog
AWS News Blog
雷峰网
雷峰网
博客园 - 三生石上(FineUI控件)
S
Security Affairs
H
Heimdal Security Blog
Engineering at Meta
Engineering at Meta
T
Troy Hunt's Blog
T
Tenable Blog
MongoDB | Blog
MongoDB | Blog
H
Hacker News: Front Page
IT之家
IT之家
N
News and Events Feed by Topic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
G
GRAHAM CLULEY
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Visual Studio Blog
S
Secure Thoughts
U
Unit 42
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Last Watchdog
The Last Watchdog
S
Security @ Cisco Blogs
NISL@THU
NISL@THU
T
The Blog of Author Tim Ferriss

Sanity.io

A Board Game agent built using Sanity Context and Vercel's AI SDK | Sanity Build a prototype with Claude Code that your whole team can edit | Sanity What’s New - May 2026 | Sanity I built a London pub guide with v0 and the Sanity MCP in six hours. Here's what I learned. | Sanity Build a conference concierge with Agent Context and Anthropic | Sanity Build a content-aware Telegram agent with Vercel AI SDK and Chat SDK | Sanity How I used Agent API to generate photos for my family’s recipes | Sanity What’s New April - 2026 | Sanity Better context, better matches: An AI love story (for dogs) | Sanity How to write for an agent | Sanity Content Agent, meet Slack: AI content operations in your workflow | Sanity Structure powers intelligence | Sanity Your agent needs better content. Here's how to give it. | Sanity How to serve content to agents (a field guide) | Sanity Sanity TypeGen GA: Automatic TypeScript types for content and GROQ | Sanity Sanity is now available on the Vercel Marketplace | Sanity The logo soup problem (and how to solve it) | Sanity Content Releases: From scattered updates to coordinated publishing | Sanity What's New - February 2026 | Sanity How we solved the agent memory problem | Sanity v0 Builder Challenge: The winners | Sanity Introducing: Sanity Agent Skills | Sanity Content Agent: Days of work in one conversation | Sanity Our Sanity Values | Sanity Open Source Pledge 2025: Stepping up when it matters | Sanity v0 builder challenge: $3000 in prizes | Sanity Why AI Breaks Without Structured Content Operations | Sanity What’s New January - 2026 | Sanity BFCM 2025: What teams built when infrastructure stopped being the problem | Sanity How AI shaped holiday shopping and what it means for content in 2026 | Sanity Sanity Studio v5: Embracing React 19 | Sanity You’ll need a CMS eventually. Let your agent set it up. | Sanity “You should never build a CMS” | Sanity AI Content Operations: A 30-Day Implementation Guide | Sanity What’s New December - 2025 | Sanity Scheduled Drafts: Stop manually publishing content at midnight | Sanity What’s New November - 2025 | Sanity Everything *[NYC] 2025 recap: A day of AI, Content Operations, and Culture | Sanity Clankers and content operations | Sanity Content Agent: AI that understands your structured content is here | Sanity Why design-driven content modeling creates technical debt, not velocity | Sanity What's New October - 2025 | Sanity From studio to inbox: How Kevin Green eliminated email campaign friction | Sanity The content editor's guide to content operations [E-commerce edition] | Sanity styled-components maintenance mode: A 40% faster fork | Sanity From zero code to a live website in 7 hours (thanks, Cursor!) | Sanity First attempt will be 95% garbage: A staff engineer's 6-week journey with Claude Code | Sanity Internationalization is more than translating words | Sanity What's New - September 2025 | Sanity We just deleted our 35k-member community Slack | Sanity What's New - August 2025 | Sanity The engineer's guide to content operations [E-commerce edition] | Sanity SEO for AI: Evolving from Web Pages to the Content Lake | Sanity What's New - July 2025 | Sanity Sanity Studio v4: A major version bump for a minor reason | Sanity What's New - June 2025 | Sanity Dashboard and Insights: Your New Content HQ | Sanity Canvas: AI-accelerated, context-aware, freeform authoring | Sanity Agent Actions: AI building blocks for structured content | Sanity Functions: Life beyond pressing publish | Sanity A new era for content applications with Sanity App SDK | Sanity The end of CMS era and our $85M Series C. | Sanity What's New – May 2025 | Sanity Introducing the Sanity Model Context Protocol (MCP) server | Sanity What's New – April 2025 | Sanity Pushing all the envelopes with ambitious content | Sanity Self-hosting is only free if your time is worth nothing | Sanity Content that lasts: Scaling beyond your frontend | Sanity The Live Content API is now Generally Available | Sanity The future beyond AI chat bots | Sanity Learning the new skill of working with AI | Sanity What's New - March 2025 | Sanity Give it in plain text: Making your content AI-Ready | Sanity No More 'DO NOT PUBLISH': Introducing Content Releases | Sanity React in 2025, what's next? | Sanity The final boss of front-end: block editors | Sanity Introducing Sanity for Startups | Sanity A block content editor that loves you back | Sanity A Black Friday Snooze Fest: Massive Traffic, No Drama | Sanity How to make a recipe site that scales well | Sanity The Sanity Winter Release 2024 | Sanity AVIF Arrives, Sanity’s Promise Fulfilled | Sanity Sanity joins the Open Source Pledge | Sanity Your content is now Live by default | Sanity Begin Team to Join Sanity | Sanity Sanity Digest - September '24 Edition | Sanity Sanity partners with Google. Now live on the Google Cloud Marketplace. | Sanity Sanity Digest - August ‘24 Edition | Sanity Now playing: the latest Mux Video Input plugin for Sanity | Sanity Community Digest - June ‘24 Edition | Sanity Community Digest - May ‘24 Edition | Sanity Guide to Sanity's newest product announcements | Sanity AI and Content Creation: A Leader's Guide | Sanity Of course, you should be able to type your content quickly! | Sanity New to AI Assist: translation, reference suggestions, image generation | Sanity Speak the language of your editors: Sanity Studio UI localization | Sanity Introducing the new Sanity Growth plan to serve collaborative teams | Sanity Presentation: Work faster than ever with structured content | Sanity Goodbye Feedback Frenzy, Hello Sanity Studio Comments! | Sanity Easing into the App Router with the Sanity Toolkit for Next.js | Sanity
Build your own blog with Next.js and Sanity | Sanity
Knut Melvær · 2026-03-17 · via Sanity.io

Sometimes you just need a blog. While there are plenty of dedicated blogging platforms, there are good reasons for having your blog content live alongside your other content, be it documentation, products, a portfolio, or whatever else you're building. A blog is also a great first project for learning how to build with structured content.

In this tutorial, we'll build a blog with Sanity as the content backend and Next.js for rendering web pages. You'll learn how to:

  • Set up a Sanity Studio with a blog schema
  • Fetch content using GROQ, Sanity's query language
  • Render blog posts with Next.js server components
  • Work with references, images, and rich text
  • Get auto-generated TypeScript types for your queries
  • Deploy your blog to the web

We'll also set up AI tooling so your coding assistant can help you along the way.

Prefer to prompt?

If you're using an AI coding assistant like Cursor, Claude Code, or GitHub Copilot, we'll set it up in Step 0 so it has full context of your Sanity project. You can follow this tutorial by typing the code, by prompting your assistant, or by mixing both. The concepts are the same either way, and understanding them is what matters.

0. Set up your projects and tools

In this project, you'll have two separate apps:

  1. Sanity Studio, where you create and manage your blog content
  2. Next.js frontend, the website that displays your blog

We'll keep them in separate folders. You can embed the Studio directly in a Next.js app, but keeping them separate makes it easier to learn how the pieces connect.

Create the Sanity Studio

Open your terminal and run:

The CLI will ask you to log in (or create an account), name your project, and confirm a dataset. Choose the defaults. When it's done:

Open http://localhost:3333 in your browser. You should see the Studio with document types for posts, authors, and categories already set up.

Next.js blog tutorial interface displaying content types (Author, Category, Post) in a sidebar and an empty main view under the 'Structure' tab.

Create the Next.js app

In a new terminal, go back to your project root and run:

This gives you a Next.js app with the App Router, Tailwind CSS, and TypeScript. Start it up:

Open http://localhost:3000. You should see the Next.js welcome page.

Your folder structure now looks like this:

Set up AI tooling

Before we start building, let's connect your AI coding assistant to your Sanity project. This step is optional, but if you use Cursor, Claude Code, VS Code, or similar tools, it means your assistant can see your schema, query your content, and follow Sanity best practices as you work through this tutorial.

From your studio directory:

This detects your editor and sets up the Sanity MCP server. For additional best-practice rules:

This installs context rules and skills covering schema design, GROQ queries, Portable Text, and framework integration. Think of it like installing a linter for your assistant's suggestions.

If you're prompting

Try asking your assistant "What document types are in my Sanity project?" If it can answer, you're set up correctly. From here on, whenever you see a code block in this tutorial, you can also try describing what you want and compare what your assistant generates with the code shown here.

For more on working with AI and Sanity, see the AI quickstart guide.

1. Explore the blog schema

The blog template gave us three document types: Post, Author, and Category. Let's look at the post schema. Open studio/schemaTypes/postType.ts:

A few things to notice:

  • defineField and defineType are helper functions that give you TypeScript autocompletion for your schema. You'll see these everywhere in Sanity projects.
  • slug has options: {source: 'title'}, which means the Studio will offer to generate a URL-friendly slug from the title.
  • author is a reference to another document type. We'll come back to this. References are how you connect documents in Sanity, and they're central to how you'll model content.
  • body is an array of blocks. This is Portable Text, Sanity's structured rich text format.

If you're prompting

Ask your assistant "Explain the post schema in my Sanity project." It should be able to walk you through each field and what it does.

2. Create some content

Before we build the frontend, let's create something to display. In the Studio (localhost:3333):

  1. Create an author. Click the + button, choose Author, fill in a name, and upload a photo. Hit Publish.
A content management system interface showing the author profile for Alice Johnson, with input fields and a portrait image.
  1. Create a category or two. Something like "Next.js" and "Tutorial." Publish them.
  2. Create a blog post. Give it a title like "Hello World!", click Generate next to the slug field, attach your author, select your categories, upload a main image, and write some body text with a heading, a paragraph, and maybe a bold word or two. Hit Publish.
A content management system editing a "Hello World!" blog post, showing a coastline image and categories Next.js, Tutorial.

Make sure the post is published. Unpublished drafts aren't available through the public API.

3. Connect Next.js to Sanity

Now let's wire up the frontend. Quit the Next.js dev server (Ctrl+C) and install the packages we need:

next-sanity is the official Sanity toolkit for Next.js. It gives you a Sanity client, the PortableText component for rendering rich text, defineQuery for type-safe GROQ queries, and TypeScript types. One package instead of three.

Create a file for the Sanity client:

Replace <your-project-id> with your actual project ID. You can find it in studio/sanity.config.ts, or by running npx sanity manage in the studio folder.

If you're prompting

Ask your assistant "Set up a Sanity client for my Next.js app using next-sanity." It knows your project ID from the MCP connection and can generate this file for you.

To allow the frontend to fetch content from Sanity, add its URL to your project's CORS settings. Run this from the studio folder:

Set up TypeGen

Sanity TypeGen generates TypeScript types from your schema and GROQ queries. This means client.fetch() returns typed results automatically, no manual type annotations needed.

First, enable TypeGen in your Studio's CLI config:

This tells TypeGen to scan your frontend code for GROQ queries and generate types into sanity.types.ts. The overloadClientMethods option means client.fetch() will automatically return the right type when you pass it a query defined with defineQuery.

Run the initial type generation:

You should see a sanity.types.ts file appear in your frontend folder. Run this command again whenever you change your schema or queries.

Add a convenience script to your Studio's package.json:

If you're prompting

Ask your assistant "Set up Sanity TypeGen for my project." It should configure sanity.cli.ts and run the extraction commands.

4. Fetch and display a blog post

Here's where it gets fun. Let's create a page that fetches a blog post from Sanity and renders it.

In the App Router, pages are files inside the src/app directory. A file at src/app/[slug]/page.tsx creates a dynamic route, so any URL like /hello-world or /my-first-post will be handled by this page.

Create the file:

Start the dev server again (npm run dev) and go to http://localhost:3000/hello-world (or whatever slug your post has). You should see the title on the page.

Let's break down what's happening:

  • This is a server component. The async keyword means this component runs on the server, not in the browser. The data fetching happens before the HTML is sent to the user. No useEffect, no loading spinners, no client-side API calls.
  • defineQuery wraps the GROQ string so TypeGen can find it and generate types. When you hover over post in your editor, you'll see the actual shape of the data, not just any.
  • The GROQ query *[_type == "post" && slug.current == $slug][0] means: "find all documents where the type is 'post' and the slug matches, then give me the first one." The $slug is a parameter that we pass as the second argument to client.fetch.
  • params is a Promise in Next.js 16. We await it to get the slug from the URL.
Blog post titled "Hello World!" by Alice Johnson, featuring an image of a rocky ocean shore, "Next.js" and "Tutorial" tags, and the quote "If you greet the world, the world will eventually greet you back."
Screenshot needed — see alt text for art direction

If you're prompting

Try "Fetch a blog post by slug from Sanity and display it in a Next.js page." Compare what your assistant generates with the code above. The GROQ query and server component pattern should look similar.

5. Add a byline with author and categories

Our post page is bare. Let's add the author name and categories. This is where GROQ projections come in. They let you shape the API response to exactly what you need.

In Sanity, the author field on a post is a reference. It stores an ID pointing to an author document, not the author data itself. To get the author's name, we need to follow the reference using the -> operator.

Update the query and the component:

Notice we don't need any type annotations on client.fetch or the .map() callback. TypeGen (which we set up in step 3) knows the shape of the query result, so TypeScript already knows that categories is an array of strings and post.title is a string. That's the payoff of defineQuery plus overloadClientMethods.

Let's look at the new parts of the GROQ query:

  • "name": author->name follows the author reference (->) and gets the name field. The "name": part creates a custom key in the response, so instead of getting a reference object, we get a plain string.
  • "categories": categories[]->title loops through the categories array ([]), follows each reference, and returns just the title. This turns an array of reference objects into an array of strings.
  • "authorImage": author->image follows the author reference and gets their image object. We'll use this next.

This is what makes GROQ particularly useful: you reshape the response in the query itself, following references and picking exactly the fields you need. No extra API calls, no data massaging on the client.

If you're prompting

Try "Add author name and categories to my blog post page using GROQ projections." Your assistant should generate a similar query with the -> operator. If it doesn't use projections, ask it to.

6. Add the author image

Images in Sanity are stored as references to assets. To generate URLs with the right dimensions and format, we use the @sanity/image-url package.

Create a small utility:

Now add the author image and main image to the post page:

But first, we need to tell Next.js that it's okay to load images from Sanity's CDN. Update your next.config.ts:

Now add the author image and main image to the post page using Next.js's Image component:

We're using Next.js's Image component instead of a plain <img> tag. It handles lazy loading, responsive sizing, and format optimization automatically. The urlFor() function generates the source URL from Sanity's CDN, and the Image component handles the rest.

The urlFor() helper also respects the image hotspot feature. If an editor has set a focal point on an image, the URL builder uses it when cropping.

7. Add rich text with Portable Text

A blog isn't much without body text. Sanity stores rich text as Portable Text, a structured format that can be rendered to HTML, React components, or anything else.

The next-sanity package re-exports the PortableText component, so you don't need to install anything extra.

First, install the Tailwind Typography plugin so our body text looks good:

Add it to your Tailwind config, then update the post page:

A few things to notice:

  • PortableText takes a value prop (the body array from Sanity) and renders it as React elements. Headings, paragraphs, lists, bold, and italic all work out of the box.
  • The components prop lets you customize how specific block types render. Here we're telling it how to render images that appear in the body text. You can customize any element: links, code blocks, and custom types.
  • The prose class from Tailwind CSS Typography (which we installed above) gives us nice default styling for the rendered text.
Screenshot of a blog post titled 'Hello World!' by Alice Johnson, featuring a tranquil seascape with rocks in the foreground.

If you're prompting

Try "Add Portable Text rendering to my blog post page." Your assistant should import PortableText from next-sanity and set up the components prop for custom block types.

8. Build the index page

Now let's list all posts on the home page. Replace the contents of src/app/page.tsx:

No manual type annotations needed here either. TypeGen infers the exact shape of POSTS_QUERY's result, so post._id, post.title, and post.slug are all typed automatically.

Let's look at the GROQ query:

  • defined(slug.current) only includes posts that have a slug. This filters out any drafts or incomplete posts.
  • | order(publishedAt desc) sorts by publish date, newest first. The | pipes the results into the ordering function.
  • [0...12] takes the first 12 results. This is a slice, like Array.slice(0, 12) in JavaScript.
  • { _id, title, slug, publishedAt } returns only the fields we need. No point fetching the full body text for a list page.

The { next: { revalidate: 30 } } option on client.fetch tells Next.js to cache the page and revalidate it every 30 seconds. When you publish a new post in the Studio, it'll appear on the index page within 30 seconds without a full rebuild.

Go to http://localhost:3000 and you should see your blog posts listed. Click one to go to the full post.

9. Deploy to the web

Time to put your blog on the internet.

Deploy the Studio

From the studio folder:

Choose a hostname (like my-blog). Your Studio will be available at https://my-blog.sanity.studio. You can invite collaborators from sanity.io/manage.

Deploy the frontend

The easiest way to deploy a Next.js app is with Vercel. Push your frontend code to a GitHub repository, then:

  1. Go to vercel.com/new
  2. Import your repository
  3. Add your environment variables (NEXT_PUBLIC_SANITY_PROJECT_ID and NEXT_PUBLIC_SANITY_DATASET if you've extracted them)
  4. Deploy

Or from the command line:

Once deployed, add your production URL to your project's CORS settings, running this command in the studio folder:

Your blog is live. 🎉

Next steps

You've built a blog with structured content, type-safe GROQ queries, server-side rendering, and Portable Text. Here are some ways to keep going:

  • Visual Editing: Click-to-edit your blog posts directly on the frontend. This is the next big upgrade for your editing experience.
  • Work-ready Next.js course: Our that goes deeper on caching, Visual Editing, page builders, and SEO.
  • Make it yours: Add more CSS, create new document types, and customize the Portable Text rendering. The schema is yours to extend.

If you're using AI tooling

Your assistant now has full context of your project. Try prompting it with things like "Add a related posts section to the blog post page" or "Create a new document type for project case studies." The MCP server and agent toolkit mean it'll generate code that follows Sanity best practices.