# Querying content

## Popular ways to query content from CMS

Representational State Transfer (REST) APIs, GraphQL, and Graph-Relational Object Queries (GROQ) are the most popular ways to query document data.&#x20;

* REST APIs are standard for building web APIs that use HTTP requests to retrieve data. You can retrieve all the data or predefined data structures based on the available APIs.
* GraphQL allows you to retrieve the data that you need instead of retrieving all the data. However, you can't query data if you don't know the exact shape of the data you want.
* GROQ is an open-source query language developed by [Sanity](https://www.sanity.io/guides/graphql-vs-rest-api-comparison) that was designed specifically for querying structured content. GROQ allows you to query for any shape of data, providing more flexibility when working with dynamic CMS data.&#x20;

|                               | REST API | GraphQL | GROQ |
| ----------------------------- | -------- | ------- | ---- |
| Query specific data shapes    | ❌        | ✅       | ✅    |
| Query data with unknown shape | ❌        | ❌       | ✅    |

{% hint style="info" %}
GROQ's flexibility is particularly valuable when working with dynamic data, as it eliminates the need to hard code queries at the outset. For example, when selecting components on a page, GraphQL requires you to specify them ahead of time, whereas GROQ allows you to query all available data or a specific shape of data.&#x20;
{% endhint %}

### How it looks in action

Let's say we want to retrieve data related to a movie from an API. Here's how the query will look using REST API:

```javascript
GET http://fictitious-example.com/movies/11
```

GraphQL:

```graphql
http://fictitious-example.com/movies/

query {
  movie(id: 11) {
    _id
    title
    releaseYear
  }
}
```

and GROQ:

```javascript
*[_id == 11]{
  _id, title, releaseYear
}
```

## Types of content to query

No matter which method you use to query data and which CMS platform you use, the kinds of data we need are typically the same. Let's take a deeper look at each of them and how they fit into generating the front end.

### Page paths

Despite having a lot of different content models, the only models we need to fetch in order to determine the page paths are the page templates. We will need to generate a page path for every unique page that exists in the CMS data. We usually don't need the entire content of the page in order to generate the paths, so we want only to return a subset of the page information (most likely only the `slug`) if it's possible with the query method you are using.

**GROQ query:**

```javascript
*[_type == Page]{
  slug
}
```

**GraphQL query:**

```javascript
http://another-example.com/pages/

query {
  Page() {
    slug
  }
}
```

The CMS data can then be used to generate your static paths. Here's an example of what that could look like in Next.js:

{% code title="\[...slug].js" %}

```javascript
export async function getStaticPaths() {
  const allPages = await getAllDocSlugs('Page')

  return {
    paths:
      allPages?.map((page) => {
        const slug = page.slug.split('/').filter(Boolean)

        return {
          params: {
            slug: slug
          }
        }
      }) || [],
    fallback: false
  }
}
```

{% endcode %}

### Page data

Once the page paths are constructed, we can work on populating the page with content.&#x20;

Typically, we need to return **all** the data associated with the page. This is challenging with GraphQL because it forces you to predefine the shape of your data.&#x20;

If you have any non-templated pages, you cannot predetermine what the content authors will decide to put on the page. Rest APIs and GROQ are therefore easier and more flexible to work with in this context.&#x20;

We can typically fetch a single page's data by referencing the page `slug` or `id` in the query.

**GROQ query:**

```javascript
*[_type == Page && slug == "/about-us"]{
  ... // This will return all page data
}
```

```javascript
*[_type == Page && slug == "/about-us"]{
  // Pick the fields you need
  title,
  description,
  heroModule,
  modules[] // This returns all your dynamic modules
}
```

**Rest API:**

```javascript
GET http://another-example.com/page/189bc292-e41b-42a0-91b5-bfaa33a34af2
```

Here's an example of how we can pass this data to a front-end template with Next.js:

<pre class="language-javascript"><code class="lang-javascript">export async function getStaticProps({ params }) {
  return {
    props: {
      data: await getPageData(params.slug.join('/'))
    }
  }
<strong>}
</strong></code></pre>

### **References**

References can be hard to work with because its content is usually returned as a `referenceId` or sometimes not returned at all.&#x20;

There are many differences between CMS platforms in how they pass reference data to the user. Some will require you to define the depth of reference you would like to resolve, and others will require you to indicate specific references. Some platforms will have an option to resolve all references, but this is less common since returning large datasets will impact performance.

### **Global data**

Some content that makes up the page should be managed globally (e.g., navigation, footer) and won't be available on your page template JSON data. You can fetch these global data elements separately and combine them with your page template data.

Here's what this could look like in Next.js:

```javascript
export async function getStaticProps({ params }) {
  return {
    props: {
      data: {
        page: await getPageData(params.slug.join('/')),
        navigation: await getDataByType('navigation'),
        footer: await getDataByType('footer')
      }
    }
  }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tbw.rangle.io/headless-cms-playbook/content-modelling/querying-content.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
