Annotations vs Blocks for WordPress-like inline shortcode functionality in Sanity

22 replies
Last updated: Jan 28, 2026
I’m looking to re-produce something similar to the Wordpress short code functionality so my client can make page content dynamic (more on use case in 🧵). Should I use “Annotations” or a “Block” for this? I like how the Annotations are inline by default, which I’ll need. However, a “short code” block would be similar to the Gutenberg Short Code Block. However, I’ve never seen a block be placed inline with a paragraph (hence the name block).
AI Update

For creating WordPress-like shortcode functionality in Sanity, you should use inline blocks (also called inline objects) rather than annotations. Here's why:

Inline Blocks vs Annotations

Inline blocks are the better choice for shortcode-like functionality because:

  • They appear inline within text (like you want)
  • They can contain complex data structures and references
  • They're stored as actual objects in the children array alongside text spans
  • They can reference other documents or contain custom data

Annotations are designed for marking up text with metadata (like links, citations, or highlighting) and work differently - they use markDefs and apply marks to text spans.

How Inline Blocks Work

You add inline blocks by including an of property in your block type definition:

import { defineType } from 'sanity'

export default defineType({ 
  name: 'blockContent', 
  type: 'array', 
  of: [ 
    { 
      type: 'block', 
      of: [ 
        {
          name: 'productPrice', 
          type: 'object',
          fields: [
            {name: 'productId', type: 'string'},
            {name: 'region', type: 'string'}
          ]
        } 
      ] 
    } 
  ] 
})

This creates a button in the Portable Text Editor toolbar that lets editors insert your inline block directly into paragraphs - just like WordPress shortcodes!

The Output Structure

Inline blocks appear in the JSON output alongside text spans in the children array:

"children": [
  {
    "_type": "span",
    "text": "This product costs "
  },
  {
    "_type": "productPrice",
    "productId": "abc123",
    "region": "US"
  },
  {
    "_type": "span",
    "text": " in your region."
  }
]

Rendering on the Frontend

When you query and render this content, you'll need to resolve any references in your GROQ query and create custom serializers for your inline blocks in your Portable Text renderer (using @portabletext/react or similar).

The key difference from Gutenberg's shortcode block: Sanity's inline blocks can truly be inline within a paragraph, not just standalone blocks. This gives you the WordPress shortcode experience where dynamic content flows naturally within text.

For more details on implementation, check out the guide on adding inline blocks to Portable Text.

Show original thread
22 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.

Was this answer helpful?