How to make a reference inside an array of arrays in Slack thread
Preserving nested array structure in GROQ when dereferencing images is tricky because GROQ doesn't have a built-in "map" function that preserves two-dimensional arrays. The double bracket pattern (presentationSlides[].images[]) flattens everything into a single array, which you've already discovered.
Unfortunately, GROQ doesn't have native support for preserving array-of-arrays structure when you need to dereference or transform nested arrays. The [] projection operator always flattens when you chain it.
Here are your practical options:
Option 1: Handle the transformation client-side (Recommended)
Query the data in a queryable structure, then reshape it in your application code:
*[_type == 'presentation'][0]{
projects[]-> {
presentationSlides[]{
images[].asset->url
}
}
}Then in your JavaScript/TypeScript:
const result = await client.fetch(query);
const formatted = {
projects: result.projects.map(project => ({
presentationSlides: project.presentationSlides.map(slide => slide.images)
}))
};Option 2: Use GROQ's select() function with indices
If you have a known, fixed number of slides, you can manually construct the array structure:
*[_type == 'presentation'][0]{
projects[]-> {
'presentationSlides': [
presentationSlides[0].images[].asset->url,
presentationSlides[1].images[].asset->url,
presentationSlides[2].images[].asset->url
]
}
}This is verbose and only works when you know the exact number of items ahead of time.
Option 3: Restructure your schema
If this is a recurring pattern, consider whether your content model could be adjusted to make querying easier. For example, storing URLs directly or flattening the structure at the schema level.
Why the limitation exists:
According to the GROQ pipeline components documentation, array projections with [] iterate over elements and return a new array. When you nest these operations (array[].nestedArray[]), GROQ flattens the results into a single-dimensional array. There's no syntax that tells GROQ to "preserve the outer array structure while transforming the inner arrays."
The most practical approach for your use case is Option 1 - keep your GROQ query relatively simple and do the final array reshaping in your application code where you have full control over data structures.
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.