Set initial value to current user and scope document access in Sanity Studio
The part:@sanity/base/user syntax you're seeing is from Sanity Studio v2 and no longer works in v3+. Here's how to properly handle user tracking and document access control in modern Sanity Studio.
Setting Initial Values with Current User
Unfortunately, field-level initialValue does NOT have access to currentUser context in schema definitions. The context with currentUser is only available in specific places:
1. Using Initial Value Templates (Recommended)
The proper way to set user information when creating documents is through Initial Value Templates in your sanity.config.ts:
// sanity.config.ts
import {defineConfig} from 'sanity'
export default defineConfig({
// ... other config
document: {
newDocumentOptions: (prev, context) => {
const {currentUser} = context
return [
...prev,
{
id: 'my-document',
title: 'My Document',
schemaType: 'myDocument',
value: {
createdBy: {
_type: 'reference',
_ref: currentUser?.id
}
}
}
]
}
}
})2. Using Conditional Fields Callbacks
You CAN access currentUser in conditional field callbacks like hidden and readOnly:
// In your schema
defineField({
name: 'sensitiveField',
type: 'string',
readOnly: ({currentUser}) => {
// currentUser has: id, name, email, roles
return !currentUser?.roles.find(({name}) => name === 'administrator')
}
})The currentUser object includes:
id(string)name(string)email(string)roles(array of objects withname,title,description)
Document-Level Permissions (Scoping Access)
To control which documents editors can access based on who created them, you need custom roles with content resources. This is an Enterprise plan feature and is configured through the Sanity Manage dashboard, not in your code.
How It Works
- Content Resources use GROQ filters to define subsets of documents
- Custom Roles apply permissions to those content resources
- You can filter based on Sanity's built-in
_createdByfield or your own custom fields
Example content resource filter:
_createdBy == identity()Where identity() represents the current user's ID.
Important Notes
- Custom roles and content resources require an Enterprise plan
- These are configured via the Sanity Manage web interface or the Roles API, not in your Studio code
- Roles in Sanity are additive - if a user has multiple roles, they get the combined permissions
- For filtered access to work properly, your dataset should typically be set to private (public datasets allow reading all documents regardless of authentication)
Complete Working Example
Here's a practical setup:
// schemas/myDocument.ts
import {defineField, defineType} from 'sanity'
export default defineType({
name: 'myDocument',
type: 'document',
fields: [
defineField({
name: 'title',
type: 'string'
}),
defineField({
name: 'createdBy',
type: 'reference',
to: [{type: 'sanity.user'}],
readOnly: true,
// Note: initialValue here won't have access to currentUser
// Use Initial Value Templates instead
})
]
})// sanity.config.ts
export default defineConfig({
// ... other config
document: {
newDocumentOptions: (prev, {currentUser}) => [
...prev,
{
id: 'myDocument',
title: 'My Document',
schemaType: 'myDocument',
value: {
createdBy: {
_type: 'reference',
_ref: currentUser?.id
}
}
}
]
}
})Then configure custom roles in Sanity Manage to filter documents based on the createdBy field or use the built-in _createdBy system field.
Show original thread6 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.