GROQ Readability Helper 🤓
Less is more - We're breaking down some of the core helpers we use when building our websites
This can help you extend your groq pretty easy 😌
export const refExtend = (
name: string,
isArray = false,
ext: Array<string> = [],
) => groq`
defined(${name})=>{
${name}${isArray ? '[]->' : '->'}{
...,
${ext.join(',')}
}
}
`;
export const extent = (
name: string,
isArray = false,
ext: Array<string> = [],
) =>
groq`defined(${name})=>{
${name}${isArray ? '[]' : ''}{
...,
${ext.join(',')}
}
}`;
Creating fragments with above functions are neat 😉
export const internal = groq`internal->{${slug}}`;
export const checkBrokenLink = groq`"isBroken":select(
defined(internal)=>false,
defined(external)=>false,
true
),
`;
export const extractLink = groq`"href": select(
defined(internal)=>internal->slug.current,
defined(external)=>external,
null
)`;
export const link = extent('link', false, [internal]);
export const customLink = extent('customLink', false, [
internal,
extractLink,
checkBrokenLink,
]);
export const markDefs = extent('markDefs', true, [customLink]);
export const button = extent('url', false, [
internal,
extractLink,
checkBrokenLink,
]);
export const buttons = extent('buttons', true, [button]);
export const richText = extent('richText', true, [
markDefs,
buttons
]);
export const spotLight = refExtend('spotlight', false, []);
export const faqs = refExtend('faqs', true);
export const category = refExtend('categories', true);
export const pageBuilder = extent('pageBuilder', true, [
richText,
buttons,
category,
faqs,
videoEmbed,
link,
]);
export const author = refExtend('author');
This is the end goal making the query more readable and clean 😏
// author , category, richText,
// pageBuilder, link
// are fragments for the articles
export const articleQuery = groq`*[_type == "article"
&& defined(slug.current)
&& slug.current == $slug][0]{
...,
${[
author,
category,
richText,
pageBuilder,
link
].join(',')}
}`;
Before and After query 👀
// Before Cleaning
const pageQuery = groq`*[_type == "page"
&& slug.current == $slug][0]{
...,
pageBuilder[]{
...,
buttons[]{
...,
url{
...,
internal->{
slug
}
}
},
categories->{ title },
richText[]{
...,
markDefs[]{
...,
customLink{
...,
internal->{
slug
}
}
}
},
link{
...,
internal->{
slug
}
}
}
}`;
// After Cleaning
export const articleQuery = groq`*[_type == "article"
&& defined(slug.current)
&& slug.current == $slug][0]{
...,
${[author, category, richText, pageBuilder, link].join(',')}
}`;One issue that is often discussed with GROQ is that its syntax can become unwieldy and difficult to manage as queries become more complex, especially when using long and repetitive fragments. This can reduce the code's readability and maintainability, making it difficult for developers to modify and update their queries efficiently. This issue emphasizes the importance of using best practices and effective coding techniques when using GROQ to keep queries manageable and easy to understand even as they become more complex.
Any more questions?
We're always trying to improve knowledge around Sanity, GROQ & Next.js. We've tried to collate a bunch of questions we wanted answers to when we first started working with the composable content cloud. If you have any more questions you'd like answers to, ☎️ Get a meeting booked in or drop us an email at
Contributors

Hrithik Prasad
Technical Lead at Roboto Studio
India

Roboto Studio
The best editorial experiences on the web
