For the longest time, CMSes have stored rich text as HTML or Markdown. It works for rendering a webpage. It falls apart when you need that same content in a mobile app, a PDF, a search index, or an AI pipeline. You end up parsing markup instead of working with data. Not fun!
Portable Text is an open specification for block content as structured JSON. It's also an editor for authoring that content. Two projects, one ecosystem.
The spec:
→ Block content stored as an array of typed JSON objects. Text, images, code blocks, or any custom type you define
→ Annotations and inline objects carry structured data, not markup
→ Queryable. Filter by block type, extract all links, transform for any output
→ Render in any language. Serializer packages for React, Vue, Svelte, Astro, HTML, Markdown, plus community libraries in C#, Python, PHP, Ruby, Go, Flutter, and Hugo
The editor:
→ Schema-driven. Define your content model, the editor enforces it
→ Headless. No built-in UI. Full control over toolbar, rendering, and interaction
→ Behavior API for custom keyboard shortcuts, paste handling, and input rules
→ Nine official plugins. Testing infrastructure with Gherkin specs and Vitest
Portable Text has been in production since 2017. It powers Sanity Studio and Canvas and has been adopted by projects like Hugo (built into the binary). 50+ packages across eight languages.
We just shipped a major docs overhaul. Per-framework rendering guides, custom blocks walkthrough, conversion to/from HTML/Markdown, editor behavior recipes, and an ecosystem catalog covering every package and plugin we could find.
We're currently working on improving support for editing tables and more complex block types. You can build them today with custom blocks, but we want to make it cleaner.
https://lnkd.in/g5JBzuC7