How AI is powering better personalization in e-commerce [with Vercel]. Sign up now

How to slugify or transform string values inside GROQ queries?

6 repliesLast updated: Nov 30, 2025

Hey all, is it possible to transform the output of a string (inside GROQ)? I’m building a nav schema which is an array of parent, child references. Parent references are optional and I’m falling back to the title specified as the base “slug” for children.
Trying to achieve something like this…


  *[_type == "navigation"] {
    items[] {
      // Can I "slugify" the "title"?
      "slug": coalesce(page->slug.current, title),
      children[] {
        "slug": page->slug.current,
      }
    }
  }
Happy to “slugify” the value returned for slug but was just wondering about the possibility of doing this inside GROQ itself
AI Update

Yes, GROQ has string manipulation functions that can help you transform strings, though there isn't a built-in slugify() function. You can achieve some string transformations using the available string namespace functions.

Basic string transformations in GROQ

GROQ provides several string functions in the string:: namespace:

Creating a slug-like transformation

While there's no native slugify() function, you can combine these functions for basic transformations:

*[_type == "navigation"] {
  items[] {
    // Convert to lowercase
    "slug": coalesce(
      page->slug.current, 
      lower(title)
    ),
    children[] {
      "slug": page->slug.current,
    }
  }
}

You could also use string::split() and array::join() to replace spaces with hyphens:

*[_type == "navigation"] {
  items[] {
    "slug": coalesce(
      page->slug.current, 
      array::join(string::split(lower(title), " "), "-")
    ),
    children[] {
      "slug": page->slug.current,
    }
  }
}

However, GROQ has limitations for complex string manipulation:

Better approach: Transform after fetching

For proper slugification (handling special characters, accents, multiple spaces, etc.), I'd recommend doing the transformation in your application code after fetching the data:

import slugify from 'slugify' // or your preferred slugify library

const data = await client.fetch(`
  *[_type == "navigation"] {
    items[] {
      "slug": coalesce(page->slug.current, title),
      children[] {
        "slug": page->slug.current,
      }
    }
  }
`)

// Transform the slugs that need it
const processed = data.map(nav => ({
  ...nav,
  items: nav.items.map(item => ({
    ...item,
    slug: item.slug?.includes?.('/') ? item.slug : slugify(item.slug, {lower: true})
  }))
}))

This gives you much more control and handles edge cases like special characters, accents, and proper URL encoding that GROQ can't easily handle on its own. The string namespace functions are great for simple transformations, but complex string manipulation is better handled in your application layer.

Show original thread
6 replies

Was this answer helpful?

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Related contributions