# Query content with GROQ https://www.sanity.io/learn/course/content-driven-web-application-foundations/writing-groq-queries.md Organize and author queries for your content with best-practice conventions. If you're new to Sanity, you're probably new to GROQ. It's an incredibly powerful way to query content, and thankfully, it's quick to get started with. You'll only need to know the basics of writing queries for now. However, it is beneficial to learn GROQ when working with Sanity as it powers queries, [GROQ-powered webhooks](https://www.sanity.io/learn/compute-and-ai/webhooks) and content permissions when configuring [Roles](https://www.sanity.io/learn/user-guides/roles). This lesson is focused on writing basic GROQ queries to serve our Next.js application. Future lessons will expand on these queries. 1. See [Between GROQ and a hard place](https://www.sanity.io/learn/course/between-groq-and-a-hard-place) for more thorough lessons on how to write expressive queries with GROQ. 2. The [Query Cheat Sheet - GROQ](https://www.sanity.io/learn/content-lake/query-cheat-sheet) is the most popular resource for quickly finding useful query examples. ## What about GraphQL? Sanity content is typically queried with GROQ queries from a configured Sanity Client. [Sanity also supports GraphQL](https://www.sanity.io/docs/graphql?utm_source=github&utm_medium=readme&utm_campaign=next-sanity). You may prefer to use GraphQL in your application, but these courses will focus on querying with Sanity Client and GROQ. ## GROQ basics You can break up most GROQ queries into three key parts. Consider this query: ```groq *[_type == "post"]{title} ``` * `*`: returns **all documents** in a dataset as an array * `[_type == "post"]` represents a **filter** where you narrow down the proceeding array * `{ title }` represents a **projection** where you define which **attributes** in those array items you want to return in the response ## Organizing GROQ queries `next-sanity` exports the `defineQuery` function which will give you syntax highlighting in VS Code with the Sanity extension installed. 1. **Install** the [Sanity VS Code extension](https://marketplace.visualstudio.com/items?itemName=sanity-io.vscode-sanity) if this is the IDE you are using. The `defineQuery` function also has another important role, [Sanity TypeGen](https://www.sanity.io/learn/apis-and-sdks/sanity-typegen) searches for variables that use it to generate Types for query results. For convenience and organization, you'll write all queries inside a dedicated file in your project. 1. **Create** a file to store two basic GROQ queries: ```typescript:src/sanity/lib/queries.ts import {defineQuery} from 'next-sanity' export const POSTS_QUERY = defineQuery(`*[_type == "post" && defined(slug.current)][0...12]{ _id, title, slug }`) export const POST_QUERY = defineQuery(`*[_type == "post" && slug.current == $slug][0]{ title, body, mainImage }`) ``` * `POSTS_QUERY` will return an array of up to 12 published documents of the type `post` that have a slug. From each document, it will return the `_id`, `title` and `slug` attributes. * This can be used on a "posts index" page to show the latest posts. * `POST_QUERY` filters down to `post` documents of the post type where the value the `slug` matches a passed-in variable `$slug`. Only one document is returned because of the `[0]` filter. From this one document, it will return the `title`, `body` and `mainImage` attributes. ### Testing GROQ queries Before using these queries in your front end, it's possible to test them at any time from within your Sanity Studio using the Vision tool. 1. **Open** [http://localhost:3000/studio/vision](http://localhost:3000/studio/vision), paste the `POSTS_QUERY` GROQ query string and click **Fetch** ```groq *[_type == "post" && defined(slug.current)][0...12]{ _id, title, slug } ``` You should see up to 12 items in the "result" panel. ![Vision tool in Sanity Studio showing a GROQ query and a response](https://cdn.sanity.io/images/3do82whm/next/3110d3eae0cfeac9e75f6f91aeb7c256ea56f88d-2144x1388.png) Queries fetched in Vision use the same user authentication that the Studio does. So it will return private documents when using the default perspective – `raw`. 1. In a **public** dataset, a document is private if it has a period "`.`" in the `_id`, such as `{ _id: "drafts.asdf-1234" }` and can only be queried by an authenticated request. In a **private** dataset all documents are private. The Sanity Client for your front end is not authenticated (unless you give it `token`) so it will only return publicly visible documents in a public dataset. 1. See [Datasets](https://www.sanity.io/learn/content-lake/datasets) for more information about Public and Private datasets. 2. [Perspectives for Content Lake](https://www.sanity.io/learn/content-lake/perspectives) determine whether published or draft documents are returned in the response. Now that you've proven that your GROQ queries get results, let's automatically generate TypeScript types for these responses.