| name | add-sanity-chatbot |
| description | Add an AI chatbot that operates on your Content Lake to an existing Next.js + Sanity project. Use when adding a chat assistant to a site that already has the Studio and a Next.js frontend. Covers dependency installation, API route setup, chat UI components, Studio plugin configuration, and system prompt design. |
Add an AI Chatbot That Operates on Your Content
Add an AI chatbot to your existing Next.js + Sanity project. The chatbot connects to the Content Lake via the Sanity Context MCP server, giving the LLM structured, schema-aware access to your content. It can answer questions, run GROQ queries, and reason over your data, not just match keywords.
What this gives you:
- A chat widget in your Next.js app connected to an LLM
- Schema-aware content access: the agent understands your content model, not just text similarity
- Semantic search layered on top of structural GROQ queries against the Content Lake
- Client-side tools for page context and screenshots
Prerequisites
Before starting, confirm:
- Existing Next.js app (App Router) with a working frontend
- Existing Studio (v5.1.0+), either embedded or separate
- Sanity project credentials available
Gather these credentials:
| Credential | Where to get it |
|---|
| Sanity Project ID | Your sanity.config.ts or sanity.io/manage |
| Dataset name | Usually production. Check your sanity.config.ts |
| Sanity API read token | sanity.io/manage -> Project -> API -> Tokens |
| Anthropic API key | From console.anthropic.com (or other provider) |
Workflow
Step 1: Set Up Sanity Context in Studio
Install the plugin and create a Sanity Context document to scope what content the chatbot can access.
See references/studio-setup.md
Step 2: Install Dependencies in Your Next.js App
IMPORTANT: Do NOT guess package versions. AI SDK packages update frequently. Always check the versions below or run npm info <package> version.
npm install @ai-sdk/anthropic@^3.0.23 @ai-sdk/mcp@^1.0.13 @ai-sdk/react@^3.0.52 ai@^6.0.50 zod@^4.3.6
Optional dependencies for advanced features (page context capture, screenshots):
npm install turndown html2canvas-pro lucide-react
npm install -D @types/turndown
Version reference (from the working ecommerce example):
| Package | Version | Notes |
|---|
@ai-sdk/anthropic | ^3.0.23 | Anthropic provider for Vercel AI SDK |
@ai-sdk/mcp | ^1.0.13 | MCP client for tool discovery |
@ai-sdk/react | ^3.0.52 | React hooks (useChat) |
ai | ^6.0.50 | Core Vercel AI SDK |
zod | ^4.3.6 | Schema validation for tool inputs |
turndown | ^7.2.2 | HTML-to-markdown for page context |
html2canvas-pro | ^1.6.6 | Screenshot capture |
lucide-react | ^0.563.0 | Icons for chat UI |
Step 3: Set Up Environment Variables
Add to your .env.local:
NEXT_PUBLIC_SANITY_PROJECT_ID=your-project-id
NEXT_PUBLIC_SANITY_DATASET=production
SANITY_API_READ_TOKEN=your-read-token
ANTHROPIC_API_KEY=your-anthropic-key
The MCP URL is constructed automatically from your project ID, dataset, and the optional SANITY_CONTEXT_SLUG (defaults to default).
Step 4: Create the Chat Implementation
Create the API route and chat UI components.
See references/chat-implementation.md
Step 5: Test the Integration
- Start your dev server:
npm run dev
- Open your app and interact with the chat widget
- The agent should call
initial_context first to understand your content types
- Try asking: "What content do you have access to?"
You can also test the API route directly:
curl -X POST http://localhost:3000/api/chat \
-H "Content-Type: application/json" \
-d '{"messages": [{"role": "user", "content": "What content do you have access to?"}]}'
Step 6: Customize the System Prompt
The system prompt shapes how your chatbot behaves. Define it inline in the API route or store it in a Sanity document for easy editing.
Basic inline prompt:
const SYSTEM_PROMPT = `
You are a helpful assistant for this website.
## Your Capabilities
- Search and retrieve content using the available tools
- Answer questions about the site's content
- Help users find what they're looking for
## How to Respond
- Be concise and helpful
- When referencing content, include relevant details
- If you can't find what the user wants, suggest alternatives
## Tool Usage
- Use initial_context first to understand available content types
- Use groq_query to find specific content
- Use schema_explorer when you need field details
`;
For more prompt examples (e-commerce, docs, support), see the system prompts guide in the reference skill.
Step 7: Explore and Optimize (Recommended)
Once the chatbot works, explore your dataset and build a production-quality system prompt:
npx skills add https://github.com/sanity-io/context --skill optimize-agent-prompt
Important Notes
AI SDK v6: convertToModelMessages()
The Vercel AI SDK v6 requires converting UI messages to model messages before passing to streamText:
import {convertToModelMessages} from 'ai'
messages: await convertToModelMessages(messages),
Do not pass raw UIMessage[] directly to streamText. This will cause type errors or silent failures.
Next 16 + Turbopack: next/dynamic Issues
If you are using Next.js 16 with Turbopack (the default dev bundler), you may encounter issues with next/dynamic for client components. If the chat component fails to render:
- Try importing it directly instead of using
next/dynamic
- Or disable Turbopack:
next dev --no-turbopack
- Check the Next.js GitHub issues for the latest status
MCP URL Format
The Sanity Context MCP server URL has two forms:
- Base URL (all content):
https://api.sanity.io/:apiVersion/context/mcp/:projectId/:dataset
- Scoped URL (filtered content):
https://api.sanity.io/:apiVersion/context/mcp/:projectId/:dataset/:slug
Use the scoped URL for production. It limits what content the agent can access based on the GROQ filter in your Sanity Context document.
Available MCP Tools
| Tool | Purpose |
|---|
initial_context | Get compressed schema overview (types, fields, document counts) |
groq_query | Execute GROQ queries with optional semantic search |
schema_explorer | Get detailed schema for a specific document type |
Troubleshooting
MCP connection fails
- Create a Sanity Context document in Studio and give it a slug
- If the slug is not
default, set SANITY_CONTEXT_SLUG in .env.local
- Ensure the Studio is deployed (
npx sanity deploy)
"401 Unauthorized" from MCP
Your SANITY_API_READ_TOKEN is missing or invalid. Generate a new token at sanity.io/manage -> Project -> API -> Tokens with Viewer permissions.
"No documents found" / Empty results
Check your Sanity Context document's content filter:
- Is the GROQ filter correct?
- Are the document types spelled correctly?
- Are there published documents matching the filter?
Tools not appearing in LLM responses
- Log
mcpClient.tools() to verify tools are returned
- Check the MCP URL (project ID, dataset, slug)
- Verify the Sanity Context document is published
The Sanity Context MCP server returns errors or no schema
The Sanity Context MCP server needs your schema deployed server-side. This happens automatically when Studio runs, but if it's not working:
- Ensure Studio is v5.1.0+
- Open your Studio in a browser (triggers schema deployment)
- Or manually deploy:
npx sanity schema deploy
Chat component not rendering
- Verify the component is marked
'use client'
- Check browser console for hydration errors
- If using
next/dynamic, try direct import instead (see Turbopack note above)