`slug` is `undefined` when I track mark and children from internalLink
The issue you're experiencing is that you're looking at the annotation object itself (which only contains the reference ID), but you need to resolve the reference to get the actual document data including the slug.
When you see reference: { _ref: "6230af03-9c14-4316-aa6f-ba7903d72c51" }, that's just a pointer to another document. The slug lives in the referenced document, not in the annotation object.
The Solution: Use GROQ to Expand References
You need to use GROQ's reference expansion operator (->) to fetch the actual document data. Here's how:
*[_type == "yourDocType"] {
content[] {
...,
markDefs[] {
...,
_type == "internalLink" => {
...,
"slug": reference->slug.current,
"title": reference->title
}
}
}
}This tells GROQ to follow the reference and grab the slug from the referenced document.
If You're Rendering on the Frontend
If you're working with already-fetched data and need to resolve references client-side, you have a few options:
Option 1: Fetch with proper projection (recommended) Make sure your initial GROQ query expands the reference as shown above.
Option 2: Custom serializer with additional fetch
If you're using @portabletext/react or similar, you can create a custom mark component that fetches the referenced document:
const components = {
marks: {
internalLink: ({value, children}) => {
// value.reference._ref exists, but you need to fetch the document
// OR better yet, ensure your GROQ query already expanded it
const href = value.slug || '#'
return <a href={href}>{children}</a>
}
}
}Why This Happens
Sanity uses references to avoid data duplication and maintain referential integrity. The annotations documentation shows that internal link annotations store a reference object, not the full document data. You must explicitly tell GROQ to expand that reference using the -> operator.
The key takeaway: references are pointers, not the actual data. Always use -> in your GROQ queries to dereference them!
Show original thread4 replies
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.