How to allow multiple users to create and manage their own content in Sanity

7 replies
Last updated: Nov 29, 2025
Hi there, I recently started on a blog website project with nextjs that allows any user to sign up and publish blogs on the site/manage their own content (similar to Medium.com ). I'm working with Sanity as my CMS/publishing editor and have managed to set up a project to publish content I personally create to the site. Could someone please point me in the direction of docs that could help with the feature that allows others to independently create/manage their own content?
AI Update

Great question! Building a Medium-like platform where users can independently create and manage their own content with Sanity is definitely possible. Here's how to approach this:

Core Architecture

For a user-generated content platform, you'll need to handle authentication separately from Sanity, then use Sanity for content storage with proper access control. Here's the recommended approach:

1. Authentication Layer (NextAuth or Similar)

First, implement your own authentication system using something like NextAuth.js to handle user sign-ups and logins. This manages your user sessions in your Next.js application. Note that Sanity's built-in users and roles are designed for content editors/administrators, not end-users of your application.

2. Writing Content from the Frontend

To allow users to create content from your frontend, you'll use Sanity's JavaScript Client to perform mutations (create, update, delete operations). Here's the key pattern:

Never expose write tokens in frontend code. Instead, use Next.js API routes or Server Actions:

// app/api/posts/route.js (Server-side)
import { createClient } from '@sanity/client';

const client = createClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
  apiVersion: '2025-02-19',
  token: process.env.SANITY_WRITE_TOKEN, // Stored securely server-side
  useCdn: false
});

export async function POST(request) {
  const session = await getSession(request); // Your auth check
  if (!session) return Response.json({ error: 'Unauthorized' }, { status: 401 });
  
  const { title, content } = await request.json();
  
  const result = await client.create({
    _type: 'post',
    title,
    content,
    author: session.user.id, // Link to your authenticated user
    publishedAt: new Date().toISOString()
  });
  
  return Response.json(result);
}

Check out the Mutations API documentation for all available operations.

3. Access Control & Permissions

For a production app where users should only edit their own content, you have two main options:

Option A: Application-Level Security (Simpler)

  • Validate user ownership in your Next.js API routes before allowing mutations
  • Use read-only tokens for public content queries
  • Keep all write operations server-side with validation

Option B: Sanity Custom Roles (Enterprise) If you're on an Enterprise plan, you can use Custom Roles to define document-level permissions using GROQ filters. This allows you to restrict which documents users can access directly in Sanity based on field values (like author ID).

4. API Tokens Setup

You'll need to create API tokens in your Sanity project:

  1. Go to your project at sanity.io/manage or run npx sanity manage
  2. Navigate to the API section
  3. Create a robot token with Editor permissions for server-side writes
  4. Store it in your environment variables (never commit to git!)

For public read access, you can either use your project without authentication (for public datasets) or create a read-only token.

5. Schema Design

Design your schema to include user references:

// schemas/post.js
export default {
  name: 'post',
  type: 'document',
  fields: [
    {
      name: 'title',
      type: 'string',
      validation: Rule => Rule.required()
    },
    {
      name: 'content',
      type: 'array',
      of: [{ type: 'block' }]
    },
    {
      name: 'author',
      type: 'string', // Store your auth system's user ID
      validation: Rule => Rule.required()
    },
    {
      name: 'publishedAt',
      type: 'datetime'
    }
  ]
}

6. Image Uploads from Frontend

For user-uploaded images, use the Assets API through your server-side API routes:

// Server-side upload handler
const imageAsset = await client.assets.upload('image', fileBuffer, {
  filename: file.name
});

Key Resources

Alternative: Sanity Functions

For more complex workflows, consider Sanity Functions - serverless compute that runs within Sanity's infrastructure. These can handle content validation, notifications, or custom business logic when documents are created/modified.

The key takeaway: Sanity is your content backend, while NextAuth (or similar) handles your user authentication. Your Next.js API routes act as the secure bridge between them, validating users and performing authorized mutations on their behalf.

Show original thread
7 replies

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?