惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
美团技术团队
Microsoft Azure Blog
Microsoft Azure Blog
V
Visual Studio Blog
Jina AI
Jina AI
博客园_首页
M
MIT News - Artificial intelligence
D
DataBreaches.Net
L
LangChain Blog
宝玉的分享
宝玉的分享
F
Fortinet All Blogs
A
About on SuperTechFans
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
Google DeepMind News
Google DeepMind News
N
Netflix TechBlog - Medium
Y
Y Combinator Blog
腾讯CDC
Vercel News
Vercel News
雷峰网
雷峰网
GbyAI
GbyAI
aimingoo的专栏
aimingoo的专栏
阮一峰的网络日志
阮一峰的网络日志
博客园 - 【当耐特】

Sanity.io

A Board Game agent built using Sanity Context and Vercel's AI SDK | Sanity Build a prototype with Claude Code that your whole team can edit | Sanity What’s New - May 2026 | Sanity I built a London pub guide with v0 and the Sanity MCP in six hours. Here's what I learned. | Sanity Build a conference concierge with Agent Context and Anthropic | Sanity Build a content-aware Telegram agent with Vercel AI SDK and Chat SDK | Sanity How I used Agent API to generate photos for my family’s recipes | Sanity What’s New April - 2026 | Sanity Better context, better matches: An AI love story (for dogs) | Sanity How to write for an agent | Sanity Content Agent, meet Slack: AI content operations in your workflow | Sanity Structure powers intelligence | Sanity Your agent needs better content. Here's how to give it. | Sanity How to serve content to agents (a field guide) | Sanity Sanity TypeGen GA: Automatic TypeScript types for content and GROQ | Sanity Sanity is now available on the Vercel Marketplace | Sanity The logo soup problem (and how to solve it) | Sanity Content Releases: From scattered updates to coordinated publishing | Sanity What's New - February 2026 | Sanity How we solved the agent memory problem | Sanity v0 Builder Challenge: The winners | Sanity Introducing: Sanity Agent Skills | Sanity Content Agent: Days of work in one conversation | Sanity Our Sanity Values | Sanity Open Source Pledge 2025: Stepping up when it matters | Sanity v0 builder challenge: $3000 in prizes | Sanity Why AI Breaks Without Structured Content Operations | Sanity What’s New January - 2026 | Sanity BFCM 2025: What teams built when infrastructure stopped being the problem | Sanity How AI shaped holiday shopping and what it means for content in 2026 | Sanity
The final boss of front-end: block editors | Sanity
Simeon Griggs · 2025-02-07 · via Sanity.io

Code && Content Podcast

This is a recap of one episode of the Code && Content podcast, head to the show page to find out more and subscribe on YouTube or the podcast player of your choice.

Subscribe

Text editors are typically known as the final boss of front-end. There is so much built-in expectation from decades of experience of editors creating content. And content creation has only gotten more complex as we've moved from rich text editors in the past (TinyMCE, CKEditor etc) to the block content editors (Notion, Confluence, etc) of the present. Each of them work differently in small ways, and yet everybody brings the expectation that they must work.

The problem with simple rich text editors is that they store content as a string, like HTML or Markdown. Which is difficult to serialize and easy to break.

While many block editor applications typically lock down and store content in a proprietary format or cannot be embedded in your application.

If you've ever tried implementing a block editor into your applications, you're probably aware of the challenges of just trying to integrate something that is pre-built, let alone building your own block editor from scratch.

Christian Grøngaard, today's guest on the podcast has spent the last few months taking the Portable Text Editor—a customized version of the Slate.js block editor hard-coded into Sanity Studio—and extracting it into a reusable component. Now available as a standalone package to insert into any React application, distributed as the Portable Text Editor.

I've struggled in the past to implement existing block editors, but the Portable Text Editor the first block editing package which I have felt has a truly intuitive API.

It has a React-friendly declarative design to rendering text and components, setting and declaring schema types, as well as being able to set custom behaviours for events that happen. Events as simple as inserting text or complex as building your own "slash command," or opening a modal based on a character being typed.

I've built two demo apps already with different frontend libraries. One with the Tailwind CSS Headless UI library and another with shadcn/ui. In both cases, I'm able to have full control over how the editor looks while still relying on the Portable Text Editor package to handle all of the behaviors of content being generated.

It's only once you start implementing a block editor yourself you may begin to realize how many built-in expectations you have, which you've never thought twice about. Where should the toolbar be located? What should happen if I try to toggle bold using the spacebar? These are all concerns that need to be built into a block editor and need to have an accompanying test suite. That's what Christian has had to do to make sure that the Portable Text Editor is as reliable as possible.

There is also a whole world of block editor terminology and syntax that you may never have heard before. Maybe you know what your "caret" is, but have you ever thought about what a "collapsed selection" is? There's a whole world of front end behaviors and terminology you interact with every day you write content into a text input—you may just has never noticed.

Have you ever considered that if your caret is at the end of bold text and you keep typing, that it should be included in the bold text? But if your caret is at the end of more dynamic data, like a link, that link should probably not extend if you keep typing.

Along with open-sourcing the Portable Text Editor, the Portable Text specification is an open standard for describing rich text and block content in a way that separates presentation from its content. It is serializable to JSON and queryable with GROQ.

I really want to highlight how great the behvior API is ... to basically "open up" the editor. I can feel it myself when I work on it. I don't hard-code internal logic anymore. It's not only easier to do, it's easier to read, and it has fewer bugs!
— Christian Grøngaard

It was really great to speak with Christian about the challenges that he faced in extracting the editor from Sanity Studio and now releasing it as a standalone package. This was particularly interesting regarding the Behavior API and how it is not only a declarative API for users to interact with when using the package, but also the foundation for all of the core behaviors that ship with the Studio and a future where plugins will be able to interact with the package to extend the behavior in anybody's Portable Text Editor.

If there's anything you feel like we didn't cover in this episode or more you would like to know, reach out and let me know.