Build with Sanity MCP in Replit. Prizes up for grabs! Submit by June 14

How to refresh custom document list in Sanity desk structure when new documents are created?

4 repliesLast updated: Nov 29, 2025

Hey all! I've got a question about desk structure. I'm trying to create a list of documents without the top-level "add new document" and "menu" items (working around i18n not working for
documentID
for one-off content types). I've got it working querying for the content type I want and building, but it doesn't refresh when a new document that matches that criteria is created. Here's a snippet of the code:
const microcopy = await context
    .getClient({ apiVersion: '2023-08-24' })
    .fetch('*[_type == "microcopy"]');
Later, in the desk builder:

S.list().items(microcopy.map((item) =>
      S.documentListItem().id(item._id).schemaType(type))
AI Update

The issue you're running into is a common gotcha with Structure Builder: when you fetch documents at configuration time using context.getClient().fetch(), that query runs once when the structure is built, not dynamically as content changes. The structure configuration is essentially static once it's created, so new documents won't appear until you refresh the entire Studio.

The solution is to use S.documentTypeList() or S.documentList() instead of manually fetching and mapping documents. These methods create dynamic lists that automatically refresh when documents are created, updated, or deleted.

Here's how to refactor your code:

S.list()
  .title('Microcopy')
  .items([
    S.listItem()
      .title('All Microcopy')
      .child(
        S.documentList()
          .title('Microcopy')
          .filter('_type == "microcopy"')
          .menuItems([]) // Removes the "Create new" menu item
      )
  ])

Or even simpler, if you just want a filtered list without the top-level menu:

S.documentList()
  .title('Microcopy')
  .filter('_type == "microcopy"')
  .menuItems([]) // This removes the top-level menu items
  .canHandleIntent(() => false) // Optional: prevents this list from handling create intents

The key differences:

If you need more complex filtering or grouping, you can still use GROQ filters with S.documentList() - they'll be evaluated dynamically. For example:

S.documentList()
  .filter('_type == "microcopy" && defined(key)')
  .params({}) // Add params here if using variables in your filter

The Structure Builder guide has more examples of creating filtered and grouped lists that update dynamically, including how to organize documents by date, status, or other properties.

Show original thread
4 replies

Was this answer helpful?

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.

Related contributions