Sanity Pioneers: Get early access to betas, extra AI credits, and a direct line to the engineering team. Apply now

Sanity Plugin STL Table

This plugin helps create advanced tables in Sanity without the complexities of nested schemas. Users can add buttons, links, and text to cells, and also include headers, footers, and index columns. The plugin also allows the use of attributes such as colSpan, rowSpan, and align for cell content.

By Yashraj Yadav

Install command

npm i sanity-plugin-stl-table

Sanity Plugin: Structured Table (STL)

A Sanity Studio plugin for creating advanced, structured tables using the Structured Table Language (STL).

STL Banner

This plugin empowers your content creators to build complex tables with features like row/column spanning, headers, and rich styling, effectively overcoming the limitations of standard portable text tables.

Full documentation: stl-table.vercel.app — covers STL syntax, renderer setup, frontend integration, and Sanity Studio usage.

🆕 Updates/Changelog

Check our change log file for version-based updates and more details Check Change Log File

✨ Features

  • STL Editor: A dedicated input component for writing and managing Structured Table Language (STL).
  • Live Preview: Real-time preview of your table within the Sanity Studio.
  • Dual Storage: Stores both the raw STL string (stlString) and a pre-parsed JSON snapshot (stlParsed) — enabling faster frontend rendering without re-parsing.
  • Advanced Layouts: Support for colspans, rowspans, and complex header structures.
  • SSR Friendly: Designed to work seamlessly with Server-Side Rendering (especially Next.js) via the core structured-table package.

📦 Installation

1. Install the Plugin

npm install sanity-plugin-stl-table
# or
yarn add sanity-plugin-stl-table
# or
pnpm add sanity-plugin-stl-table

Note: This plugin requires react >= 18 and sanity >= 3.0.0 (Supports Sanity v3, v4, and v5).

2. Setup Table Render Components (Required for Studio Preview)

To enable the interactive table preview within Sanity Studio, install the CLI and add the React renderer components using structured-table-cli.

npm install structured-table-cli

Then run the following command to download the pre-built React table components:

npx stl-cli add react

Optional: Specify a custom path for the components:

npx stl-cli add react --path ./schemaTypes/components

3. Register Components in Sanity Config

After generating the components, register them in your sanity.config.ts. Import the register file (found in the folder where components were installed) at the top of your config.

For example, if installed in schemaTypes/components:

// sanity.config.ts
import './schemaTypes/components/register' // Base path depends on where you installed it
import { defineConfig } from 'sanity'
import { stlTableBlock } from 'sanity-plugin-stl-table'

export default defineConfig({
  // ... configuration
})

🚀 Sanity Studio Implementation

1. Import the Schema

Import the stlTableBlock schema definition and add it to your Sanity Studio configuration types array.

// sanity.config.ts
import { defineConfig } from 'sanity'
import { stlTableBlock } from 'sanity-plugin-stl-table'

export default defineConfig({
  // ...
  schema: {
    types: [
      // ... other types
      stlTableBlock,
    ],
  },
})

2. Use in Portable Text or as a Field

In Portable Text:

// schemas/blockContent.ts (or similar)
export default {
  title: 'Block Content',
  name: 'blockContent',
  type: 'array',
  of: [
    { type: 'block' },
    { type: 'stlTableBlock' },
  ],
}

As a Field:

export default {
  name: 'productSpecification',
  title: 'Product Specification',
  type: 'document',
  fields: [
    {
      name: 'title',
      type: 'string',
    },
    {
      name: 'specsTable',
      title: 'Specifications Table',
      type: 'stlTableBlock',
    },
  ],
}

3. Studio Usage

Restart your Sanity dev server. You will now see an input field where you can paste or write your STL code.

Check the following video to learn how to use the block inside Sanity Studio.

How to use block inside Sanity Studio

The table preview updates automatically as you type, giving you immediate feedback on your table structure and content.

4. Create a Table in STL Language

Use our interactive live table editor at stl-table.vercel.app/playground to build your entire table visually and export it in STL format.

💻 Frontend Implementation

To render the structured tables on your frontend (e.g., Next.js, Remix), follow these steps.

Full integration guide: stl-table.vercel.app/docs

1. Install Dependencies

npm install structured-table
npm install structured-table-cli

Add the React renderer to your project (replace react with vue for Vue projects):

npx stl-cli add react

2. Render in Portable Text

The plugin stores two fields in Sanity for each table block:

FieldTypePurpose
stlStringstringRaw STL source written by the editor
stlParsedstring (JSON)Pre-parsed SanityTable object — use JSON.parse() to consume
captionstringOptional table caption

Recommended pattern — use stlParsed when available (no re-parsing), fall back to STL.parse(stlString) for older documents:

import * as STLReact from './components/react' // Path to your generated components
import { STL, SanityTable } from 'structured-table'

const myPortableTextComponents = {
  types: {
    stlTableBlock: ({ value }: {
      value: {
        _key: string;
        _type: string;
        stlString?: string;
        stlParsed?: string;  // JSON.stringify(SanityTable) — use JSON.parse() to consume
        caption?: string;
      }
    }) => {
      // Fast path: use pre-parsed JSON snapshot; fall back to parsing stlString
      let tableData: SanityTable | null = null;
      try {
        if (value.stlParsed) {
          tableData = JSON.parse(value.stlParsed) as SanityTable;
        } else if (value.stlString) {
          tableData = STL.parse(value.stlString);
        }
      } catch {
        return null;
      }

      if (!tableData) return null;

      // Override caption if set in Sanity
      if (value.caption) {
        tableData.caption = value.caption;
      }

      return <STLReact.Table data={tableData} className='border' />
    }
  }
}

// Usage in your PortableText component
// <PortableText value={data.body} components={myPortableTextComponents} />

stlParsed is available on documents saved with plugin version > 0.3.0. For older documents it will be undefined, and the fallback STL.parse(stlString) handles them transparently.

🛠 How it Works

  1. Dual Storage: When an editor types STL, the plugin stores the raw string in stlString and simultaneously stores a pre-parsed JSON snapshot in stlParsed. This means your frontend never needs to run the parser at request time.
  2. Input Component: The custom TableInput interface lets editors write STL directly, with a live preview updating in real time. Caption is managed inline as a separate text field.
  3. Migration Layer: The input reads stlParsed first (fast path). If absent (older documents), it falls back to STL.parse(stlString). No manual migration is required.
  4. Preview: Inside the Studio, a TablePreview component renders the table so editors see exactly what it will look like without leaving the CMS.
  5. Frontend Rendering: On your frontend, consume stlParsed directly with JSON.parse(). This avoids the parsing step entirely and works with SSR.

💡 What is it used for?

Standard Sanity tables are great for simple key-value pairs or basic grids. However, they often struggle with:

  • Merged Cells: Row spans and column spans.
  • Complex Headers: Multi-level headers, column headers, or non-standard grid layouts.
  • Rich Styling: Specific alignment, button cells, or complex formatting.

Sanity Plugin Structured Table solves this by leveraging STL, letting you define table structures as flexibly as HTML tables but with a syntax designed for data entry and maintainability.

For the full STL syntax reference and more integration examples, visit stl-table.vercel.app/docs.

📄 License

MIT © Yashraj Yadav