How to create nested posts with ordered sub-posts in Sanity schema?

10 replies
Last updated: Jan 28, 2026
Hello everyone 👋 I'm pretty new to Sanity and its schema architecture and I've been trying to find any solution regarding my query but couldn't.Basically, I'm trying to make a blog platform similar to
Buildspace where there are "posts" and within those posts, there are "sub posts". How would I go about creating a schema that makes this possible? My initial thought was to have a sub post array in the Post schema that references another schema of SubPost, but I also want to have control over the order of sub posts within a post, and would also like to structure sub posts nicely for scalability purposes.
What would be the most straightforward solution for this? I've attached a picture regarding the type of thing I'm trying to build. Any help would be immensely helpful!
AI Update

Looking at your question about creating a blog platform with posts and sub-posts (similar to Buildspace), you have a couple of solid approaches in Sanity. Let me walk you through the most straightforward solution that gives you ordering control and good scalability.

Based on your needs, I'd recommend using an array of references in your Post schema. This is the pattern that works best for your use case because:

  1. Built-in ordering: Arrays in Sanity are inherently orderable with drag-and-drop functionality, so you get ordering control out of the box
  2. Scalability: Sub-posts remain independent documents that can be reused or managed separately
  3. Clean queries: Easy to fetch and traverse with GROQ

Here's how to structure it:

// schemas/post.ts
export default defineType({
  name: 'post',
  type: 'document',
  title: 'Post',
  fields: [
    defineField({
      name: 'title',
      type: 'string',
      title: 'Title'
    }),
    defineField({
      name: 'subPosts',
      type: 'array',
      title: 'Sub Posts',
      of: [{
        type: 'reference',
        to: [{type: 'subPost'}]
      }]
    })
  ]
})

// schemas/subPost.ts
export default defineType({
  name: 'subPost',
  type: 'document',
  title: 'Sub Post',
  fields: [
    defineField({
      name: 'title',
      type: 'string',
      title: 'Title'
    }),
    defineField({
      name: 'content',
      type: 'array',
      of: [{type: 'block'}]
    })
  ]
})

Querying the Data

To fetch posts with their ordered sub-posts, use this GROQ query:

*[_type == "post"] {
  _id,
  title,
  subPosts[]-> {
    _id,
    title,
    content
  }
}

The []-> syntax dereferences the array of references, fetching the full sub-post documents while maintaining the order you set in the Studio.

Why This Works Well

  • Ordering: The array maintains order via drag-and-drop in the Studio. Each item has a _key property that Sanity uses internally to track position
  • Scalability: Sub-posts are separate documents, so you can:
    • Query them independently if needed
    • Potentially reuse them across multiple posts (if that makes sense for your use case)
    • Keep your data normalized
  • Studio UX: You get a clean interface where you can select existing sub-posts or create new ones inline

Alternative: Inline Objects

If sub-posts will never be reused and are truly just components of a parent post, you could use inline objects instead:

defineField({
  name: 'subPosts',
  type: 'array',
  of: [{
    type: 'object',
    fields: [
      {name: 'title', type: 'string'},
      {name: 'content', type: 'array', of: [{type: 'block'}]}
    ]
  }]
})

This is simpler but less flexible—sub-posts can't exist independently or be queried separately.

The Pattern in Action

The approach I'm recommending is actually a common Sanity pattern for creating ordered collections. As one Sanity team member explained: "The usual approach is to make an 'order' document that holds an array of references to the document type you want to order."

In your case, the Post document serves as that ordering container for SubPosts. This gives you the best of both worlds: the independence of separate documents with the ordering control of arrays.

Good luck with your blog platform! Feel free to ask if you need help with querying or displaying this structure.

Show original thread
10 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?