This guide will help you set up Sanity CMS for your blog.
You have two options:
Option A: Using the Sanity CLI (Recommended)
npx sanity initFollow the prompts:
- Create new project or use existing? → Create new project
- Project name? → Good Robot Co. (or whatever you prefer)
- Dataset name? → production
- Output path? → Press Enter (files already exist, this is fine)
Option B: Using the Sanity Dashboard
- Go to https://www.sanity.io/manage
- Click "Create New Project"
- Name it "Good Robot Co." (or whatever you prefer)
- Create a dataset called "production"
After creating your project, you'll need two values:
- Project ID: Found in your Sanity dashboard or in the output from
npx sanity init - Dataset: Usually "production"
Create a .env.local file in the root of your project:
cp .env.local.example .env.localThen edit .env.local and add your credentials:
NEXT_PUBLIC_SANITY_PROJECT_ID=your-project-id-here
NEXT_PUBLIC_SANITY_DATASET=production
SANITY_API_TOKEN=your-api-token-here
Note: You'll need the API token later for webhooks. For now, the first two variables are enough to get started.
Your Next.js app needs permission to query Sanity's API:
- Go to https://www.sanity.io/manage
- Select your project
- Go to Settings → API
- Under "CORS Origins", click "Add CORS Origin"
- Add these origins:
http://localhost:3000(for local development)https://goodrobotco.com(for production)https://*.vercel.app(for Vercel preview deployments)
You can access Sanity Studio in two ways:
Option A: Embedded Studio (in your Next.js app)
npm run devThen visit: http://localhost:3000/studio
Option B: Standalone Studio
npx sanity devThis will start the studio at http://localhost:3333
- Open Sanity Studio (using either method above)
- Click "Blog Post" in the sidebar
- Click "Create new document"
- Fill in:
- Title
- Slug (auto-generated, but you can customize)
- Excerpt (short preview)
- Content (the main blog post body)
- Featured Image (optional)
- Author (defaults to "Ben Poon")
- Published At (defaults to now)
- SEO metadata (optional but recommended)
- Click "Publish"
# Start the dev server
npm run dev
# Visit your blog
open http://localhost:3000/blogYou should see your blog post!
# Build the static site
npm run build
# This will:
# - Fetch all blog posts from Sanity
# - Generate static HTML for each post
# - Output to /out directoryYour Sanity credentials need to be added to Vercel:
- Go to your Vercel project dashboard
- Go to Settings → Environment Variables
- Add these variables:
NEXT_PUBLIC_SANITY_PROJECT_ID→ your project IDNEXT_PUBLIC_SANITY_DATASET→ production
Note: These same values should be added to GitHub Secrets for CI/CD:
- Go to your GitHub repo → Settings → Secrets and variables → Actions
- Add
SANITY_PROJECT_ID(same value as NEXT_PUBLIC_SANITY_PROJECT_ID) - Add
SANITY_DATASETas a variable (not a secret) set to "production"
git add .
git commit -m "Add Sanity CMS integration"
git pushVercel will automatically deploy your site.
When you publish a blog post in Sanity, you want your site to rebuild automatically.
Step 1: Create a Deploy Hook in Vercel
- Go to your Vercel project → Settings → Git
- Scroll to "Deploy Hooks"
- Click "Create Hook"
- Name: "Sanity Content Update"
- Branch: main
- Copy the webhook URL
Step 2: Add Webhook to Sanity
- Go to https://www.sanity.io/manage
- Select your project
- Go to Settings → API → Webhooks
- Click "Create webhook"
- Fill in:
- Name: "Vercel Deploy"
- URL: [paste the webhook URL from Vercel]
- Dataset: production
- Trigger on: Create, Update, Delete
- Filter:
_type == "blogPost" - HTTP method: POST
- Save
Step 3: Test the Webhook
- Publish or update a blog post in Sanity
- Check your Vercel dashboard - you should see a new deployment triggered
- Wait 2-5 minutes for the rebuild
- Visit your site - the new/updated post should appear!
# Run smoke tests (requires dev server running)
npm run dev &
npm run test:smoke
npm run test:sanity
# Run build validation
npm run build
npm run test:build
# Or run everything at once
npm run test:allThe GitHub Actions workflow (.github/workflows/smoke-tests.yml) will automatically:
- Run smoke tests on every push/PR
- Run Sanity integration tests
- Validate the build output
- Ensure all blog posts are generated correctly
Make sure you:
- Created a
.env.localfile (not.env.local.example) - Added your project ID to the file
- Restarted the dev server after creating the file
Make sure you added your domain to CORS origins in the Sanity dashboard (see step 4 above).
- Check that you published (not just saved) your blog post in Sanity
- Check the browser console for errors
- Verify your environment variables are set correctly
- Try restarting the dev server
- Make sure SANITY environment variables are set in Vercel
- Check that your dataset name matches (usually "production")
- Verify your project ID is correct
To add services, testimonials, or other content:
- Create new schema files in
/sanity/schemaTypes/ - Add them to
/sanity/schemaTypes/index.ts - Create corresponding pages in
/app/ - Update queries in
/lib/sanity.client.ts
Edit /sanity/sanity.config.ts to:
- Change the studio title
- Add custom plugins
- Customize the theme
- Add custom document actions
Images are already optimized through Sanity's CDN. The urlFor() helper in /lib/sanity.image.ts handles:
- Automatic format conversion (WebP/AVIF)
- Responsive sizing
- Lazy loading (via Next.js Image component)
You're on the free tier which includes:
- 10,000 documents (plenty for a blog)
- 5GB asset storage
- 10GB CDN bandwidth/month
- Unlimited API requests (reads)
You'll likely stay on the free tier indefinitely for a business blog.