I'm hoping for a bit of schema setup/structure guidance.
Based on what you're describing, you're on the right track! This is a classic page builder pattern in Sanity, and there are a couple of ways to structure it depending on your needs.
The Two Main Approaches
You have two architectural options for connecting components to pages:
1. Inline Objects (Most Common)
Define your components as object types and embed them directly in the page's array. This is like having the component data live "inside" the page document:
// Component schemas (objects, not documents)
export const hero = {
name: 'hero',
type: 'object',
fields: [
{name: 'heading', type: 'string'},
{name: 'image', type: 'image'},
{name: 'cta', type: 'object', fields: [...]},
]
}
// Page schema
export const page = {
name: 'page',
type: 'document',
fields: [
{name: 'title', type: 'string'},
{
name: 'content',
type: 'array',
of: [
{type: 'hero'},
{type: 'features'},
{type: 'faq'},
// ... other component types
]
}
]
}Pros: Simpler queries, content stays with the page, easier to manage
Cons: Can't reuse the exact same hero instance across multiple pages
2. References to Documents
Make your components actual documents and reference them:
// Component as document
export const hero = {
name: 'hero',
type: 'document',
fields: [...]
}
// Page references components
export const page = {
name: 'page',
type: 'document',
fields: [
{
name: 'content',
type: 'array',
of: [{type: 'reference', to: [{type: 'hero'}, {type: 'features'}]}]
}
]
}Pros: Can reuse exact component instances across pages
Cons: More complex queries (need to resolve references), more documents to manage
Recommendation
For most page builders, go with inline objects (approach #1). This matches your "instance of a component" mental model from relational databases - each time you add a hero to a page, you're creating a new instance with its own data.
The Sanity page building course covers this exact pattern in detail and shows how to structure your component schemas, add custom previews so editors see what they're building, and handle rendering on the frontend.
Only use references if you specifically need to share the exact same content across multiple pages (like a global announcement banner that should update everywhere when changed).
Additional Tips
- Give each component type a good
titleandpreviewconfiguration so content editors can easily identify blocks - Consider adding an
iconproperty to each component type for better visual scanning in the Studio - You can mix both approaches - some components as objects, others as references - if that fits your use case
The beauty of this approach is that adding a new component type just means adding it to the of array, and it immediately becomes available to all pages!
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.