Can a dataset contain both public and private documents with different access?

9 replies
Last updated: Sep 6, 2020
Is that possible to create a dataset that contains public & private documents, and the client can only access the public data while in the CMS can access both public and private data? Or I can only create different datasets individually?
AI Update

Yes, absolutely! You can create a single dataset that contains both public and private documents, and control access so that clients only see public data while CMS users can access everything. This is done through custom roles and content resources with GROQ filters, not by creating separate datasets.

Here's how this works:

Using Custom Roles with Content Resources

Custom roles let you define granular permissions using GROQ filters to control which documents different users or API tokens can access. You can create a "content resource" that filters documents based on any field - like a isPublic or visibility field.

For example, you could:

  1. Add a field to your documents (like isPublic: boolean)
  2. Create a custom role for your public-facing client that only grants read access to documents where isPublic == true
  3. Give your CMS users (editors/admins) roles that can access all documents

This approach using content resources with GROQ filters is much more flexible than separate datasets because you can filter on any document attribute - publication status, team assignment, locale, workflow state, or custom business rules.

Important Considerations

Dataset Privacy: When using custom roles to restrict content visibility, you should set your dataset to private. Public datasets allow all documents to be readable by anyone regardless of authentication, which would bypass your role-based restrictions.

API Tokens: You can apply custom roles to API tokens, which is perfect for controlling what your client-side application can access. Create a token with a role that only grants read access to your "public" content resource.

Availability: Custom roles are an Enterprise plan feature, so you'll need that plan level to implement this approach.

Alternative: Separate Datasets

If custom roles aren't available on your plan, you could create separate datasets (one public, one private), but this creates operational overhead - you'd need to manage content across multiple datasets and potentially duplicate shared content.

The single-dataset approach with custom roles is the recommended solution for most use cases involving mixed public/private content visibility.

Show original thread
9 replies
I found Spaces may help, create two datasets for public and private use.
Another question is, my public and private dataset have different schema, but Spaces seem share same schema even with different
projectId
and
dataset
.
A workaround is I can share the same schema in different datasets, but show a subset of documents that the current dataset needed in the navigation bar based on
process.env.SANITY_STUDIO_API_DATASET
.
Not sure it’s a good practice.
I’d look into IDs and paths :) https://www.sanity.io/docs/ids
user Y
So I can create private documents by providing a custom id like
contacts.${ID}
(only through API [1]), then the client (without token) can’t access them. Am I right?
[1]

The Sanity Studio automatically generates a random UUID  for new documents (e.g. 
189bc292-e41b-42a0-91b5-bfaa33a34af2
), and does not allow you to specify an ID yourself, but you are free to use your own ID scheme for documents that you create using the HTTP API.
Yup!
It works, thanks!
user Y
am I right in thinking then that this would be a secure solution to build your own shop storing customer data in Sanity?
(providing all orders / customer data must be created initially via Sanity Javascript Client)

That’s exciting!

Or is it safest to keep it a private dataset and proxy the API requests using serverless functions?
You are right in thinking that. It’s the same way that drafts and the system documents (containing the permissions) work 🙂
Ahh! Thanks
user Y
– never clocked that this is why drafts only show up in authenticated requests. Amazing! Very excited to start making some lightweight shops in Sanity 🙂

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?