If you are just starting with Sanity development, the first thing you will meet is GROQ, Sanity's query language. It looks unusual at first, but a handful of patterns cover most of what you will build. Here are eight to learn first.

You can try every query below in the Vision tool inside Sanity Studio, which lets you run GROQ and see the results instantly.

1. Get every document of one type

*[_type == "post"] 

* means "all documents," and the square brackets filter them. This returns every document whose type is post.

2. Pick only the fields you need

*[_type == "post"]{ title, publishedAt } 

The curly braces are a projection. Ask only for what the page needs, and your responses stay small and fast.

3. Filter by a field

*[_type == "post" && featured == true] 

Combine conditions with &&. This example assumes your post type has a boolean field called featured.

4. Fetch a single document by slug

*[_type == "post" && slug.current == $slug][0] 

The [0] at the end returns one document instead of a list. $slug is a parameter, so you never build queries by gluing strings together:

const post = await client.fetch( `*[_type == "post" && slug.current == $slug][0]`, { slug: 'my-first-post' } ) 

5. Sort your results

*[_type == "post"] | order(publishedAt desc) 

The pipe | sends the results into order(). Use desc for newest first and asc for oldest first.

6. Limit and paginate

*[_type == "post"] | order(publishedAt desc)[0...5] 

The slice [0...5] returns the first five items. For pagination, use parameters such as [$start...$end].

7. Follow a reference

*[_type == "post"]{ title, "authorName": author->name } 

The arrow -> follows a reference to another document and lets you read its fields. The quoted name on the left creates a new field in the result.

8. Count documents

count(*[_type == "post"]) 

Handy for dashboards, pagination totals and quick checks.

Bonus patterns

*[_type == "post" && defined(publishedAt)] *[_type == "post" && title match "sanity*"] *[_type == "post" && references($authorId)] 
  • defined() checks that a field has a value, which is useful for hiding unfinished drafts.
  • match does simple text matching.
  • references() finds every document that points to a given document.

Final thoughts

GROQ rewards a small amount of practice. Start with filters and projections, add ordering and slicing, then move on to references. Keep your queries lean, ask only for the fields you need, and your pages will stay fast as your content grows.

What GROQ pattern do you reach for most? Share it in the comments.