How can I implement footnotes?
Footnotes in Sanity are typically implemented using Portable Text annotations, which allow you to attach structured data to specific text spans. Here's how to set it up:
Schema Setup
First, define a custom annotation type for footnotes in your schema:
defineField({
title: 'Footnote',
name: 'footnote',
type: 'object',
icon: DocumentTextIcon, // or any icon you prefer
fields: [
{
title: 'Note',
name: 'note',
type: 'text',
description: 'The footnote content'
}
]
})Then add it to your block content's annotations array:
defineField({
name: 'body',
type: 'array',
of: [
{
type: 'block',
marks: {
annotations: [
{
name: 'footnote',
type: 'footnote',
},
// ... other annotations
],
},
},
],
})Frontend Rendering
When rendering on the frontend, you'll need a custom serializer. For React using @portabletext/react:
import {PortableText} from '@portabletext/react'
const components = {
marks: {
footnote: ({children, value}) => {
return (
<span>
{children}
<sup className="footnote-ref">*</sup>
<span className="footnote-content">{value.note}</span>
</span>
)
}
}
}
<PortableText value={content} components={components} />You can get more creative with the rendering - display footnotes as tooltips, collect them at the bottom of the page with numbered references, or show them in a sidebar. The ultimate guide for customising Portable Text has more examples of customizing how annotations appear.
The key advantage of this approach is that your footnote data is structured and portable - you can render it differently across web, mobile, or other platforms while keeping the same content structure in Sanity.
Show original thread5 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.