$cd/webstacks/dev>ls-la>blog/DEV BLOG/Why We Chose GROQD Over G...

Why We Chose GROQD Over GROQ: A Frontend Developer's Perspective

Friday, March 21st, 2025

As a frontend developer at a web agency, I know how crucial it is to choose the right tools for querying our Sanity.io content. Sanity provides multiple ways to access data in their Content Lake—including GraphQL and REST—but their primary method is their own query language, GROQ (Graph-Relational Object Queries). While GROQ has been Sanity's standard query language, we've made the strategic decision to adopt GROQD. Here's why.

Understanding GROQ: The Foundation

First, I would like to dive into what GROQ is. GROQ (Graph-Relational Object Queries) is Sanity's open-source query language designed specifically for filtering, projecting, and joining content in real-time. It's similar to SQL in some ways, but optimized for JSON documents and content trees.
Here's a simple GROQ query that fetches all blog posts with their titles and authors:
javascript
1
2
3
4
*[_type == "post"] {
  title,
  "author": author->name
}
GROQ becomes more powerful when you need to filter and join related content. Here's a more complex example that gets all posts from 2024, includes their categories, and limits the result to 5 posts:
javascript
1
2
3
4
5
6
*[_type == "post" && dateTime(publishedAt) >= dateTime('2024-01-01') && dateTime(publishedAt) <= dateTime('2024-12-31')] {
  title,
  "author": author->name,
  "categories": categories[]->title,
  publishedAt
} | order(publishedAt desc) [0...5]
While GROQ is powerful and flexible, it lacks native TypeScript support - which is where GROQD comes in. Since GROQ queries are just strings, they can be prone to subtle syntax errors like misplaced dots, arrows (->), or brackets that TypeScript won't catch until runtime. The queries above would work in both GROQ and GROQD, but GROQD adds the crucial type safety layer that modern development demands.

Enter Zod: The Type Validation Powerhouse

GROQD leverages Zod, a TypeScript-first schema validation library, as its foundation for type safety. This integration is what gives GROQD its robust type checking capabilities and runtime validation features.
Zod acts as a bridge between your GROQ queries and TypeScript's type system. When you write a GROQD query, you're essentially creating a Zod schema that defines both the shape and validation rules for your data. Here's why this matters:
  • Runtime Type Checking: Zod doesn't just provide compile-time type safety; it also validates data at runtime, catching potential issues that TypeScript alone might miss.
  • Schema Composition: You can build complex data schemas by combining simpler ones, making it easier to maintain and reuse validation logic across your codebase.
  • Automatic Type Inference: Zod schemas automatically generate TypeScript types, eliminating the need to maintain separate type definitions.
Here's a practical example of how GROQD uses Zod under the hood:
typescript
1
2
3
4
5
6
7
8
const postSchema = q.star.filterByType('post').project({
  title: z.string(),
  publishedAt: z.string().datetime(),
  author: z.object({
    name: z.string(),
    email: z.string().email()
  })
})
In this example, Zod ensures that:
  • The title is always a string
  • The publishedAt field is a valid datetime string
  • The author object has the correct shape with valid email format
This combination of GROQ's querying power and Zod's validation capabilities makes GROQD an exceptionally reliable tool for working with Sanity's Content Lake.
For example, if we write the query incorrectly like this:
typescript
1
2
3
4
const postSchema = q.star.filterByType('post').project({
  title: z.number(), // title is not of type number
  ...
})
We would get this runtime error:
shell
1
2
ValidationErrors: 1 Parsing Error:
result[0].title: Expected number, received string
This error occurs because we tried to validate the title field as a number when it's actually a string in our content model. GROQD's runtime validation caught this type mismatch, preventing potential issues in our application.
This integration becomes particularly powerful when dealing with complex data structures. For example, when querying nested references or handling arrays of mixed content types, GROQD's type inference ensures that our frontend components receive exactly the data shape they expect.

Addressing the Learning Curve Challenge

While we've discussed the benefits of GROQD, it's important to acknowledge that there is a learning curve when transitioning from GROQ. Here's what developers should expect:
  • Initially, developers need to understand both GROQ syntax and Zod's type validation patterns
  • The builder pattern approach in GROQD may feel unfamiliar to those used to writing raw GROQ queries
  • Teams need to adapt to thinking in terms of type-safe schemas rather than just query results
However, our experience shows that these challenges are temporary and manageable:
  • Most developers become comfortable with GROQD within their first week of usage
  • The improved IDE support and type hints actually accelerate the learning process
  • The investment in learning GROQD pays off quickly through reduced debugging time and fewer runtime errors
To ease the transition, we recommend:
  • Starting with simple queries and gradually moving to more complex ones
  • Taking advantage of GROQD's documentation and examples
  • Pairing experienced GROQD users with newcomers during the initial phase
The learning curve shouldn't be seen as a barrier but rather as an investment in better code quality and developer productivity.

GROQD at Webstacks: Our Experience

Since implementing GROQD across our Sanity-powered projects at Webstacks, we've observed several tangible benefits that have improved our development workflow:
  • Faster project deliveries: Type safety has significantly reduced the time spent debugging type-related issues, allowing us to meet client deadlines more efficiently.
  • Improved code quality: The combination of compile-time checks and runtime validation has resulted in more robust codebases with fewer production bugs.
  • Enhanced team collaboration: New team members can onboard faster due to better type inference and IDE support, making it easier to understand and work with existing code.
  • Client satisfaction: More reliable applications and quicker turnaround times have led to increased client satisfaction and stronger relationships.
Our frontend team has especially appreciated GROQD's builder pattern approach, which has made complex queries more readable and maintainable. This has proven invaluable when returning to projects months later for updates or expansions.

Conclusion

For Webstacks, GROQD represents a significant improvement over standard GROQ. The enhanced type safety, improved developer experience, and streamlined query building make it an invaluable tool in our development stack. While GROQ remains a solid choice, GROQD's additional features make it the clear winner for TypeScript-based projects where type safety and developer experience are priorities.
The decision to use GROQD aligns perfectly with our Webstacks' commitment to using modern, type-safe tools that improve code quality and developer productivity. As we continue to build complex web applications for our clients, having GROQD in our toolkit gives us confidence that we deliver more reliable and maintainable solutions.

Posted by

Portrait of Curtis Cartier

Curtis Cartier

[>]HIGHLIGHTS
  • Understanding GROQ: The Foundation
  • Enter Zod: The Type Validation Powerhouse
  • Addressing the Learning Curve Challenge
  • GROQD at Webstacks: Our Experience
  • Conclusion