Hrithik Prasad
Sr. Full Stack Developer at Roboto Studio
Less is more - We're breaking down some of the core helpers we use when building our websites
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(',')}
}
}`;
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');
// 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 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
Sr. Full Stack Developer at Roboto Studio
Founder @ Roboto Studio - The Sanity & Next.js experts
The Sanity & Next.js experts
Thinking about getting started with AI? Well we're just going to share our latest and greatest prompt so you don't have to do the hard work
Go to Cursor PromptOn the fly form generation with Sanity & Formspark
Go to Sanity & Formspark Form GeneratorIf you're looking to mockup portable text in Storybook without a Sanity backend, this is the schema you're looking for
Go to Portable Text Mock ContentOkay, well it might be at least in the top 3. Using getDimensions and optimising the hell out of your images, check out this snippet
Go to The best Next.js & Sanity <Image/> Component