Advertisement · 728 × 90

Posts by knut

A Sanity Studio with conference content in it with a Telegram window in front showing a chat where a panel has been rescheduled and an announcement has been made about it.

A Sanity Studio with conference content in it with a Telegram window in front showing a chat where a panel has been rescheduled and an announcement has been made about it.

Conferences are filled to the brim with content ops. Talks, CFPs, schedules, FAQs, announcements. Usually spread across systems that don't work on your phone.

So I built a conference OS on Sanity with agents in Telegram. Text it to move a panel or accept a CFP.

Writeup next week.

2 days ago 0 0 0 0
Video

"Can Portable Text handle complex data visualizations beyond text and images?"

Yes. Here's a live editor with charts, inline sparklines, metric badges, and tables. All as structured JSON that any platform can render.

Demo: portable-text-data-demo.sanity.dev
Docs: portabletext.org

1 week ago 2 0 0 0

Yes, it's an inherently complex problem. We solve this at @sanity.io with schemas and custom types that can be reused in the structure. Works pretty well!

1 week ago 1 0 0 0

And @hamburger.cloud is actively work on improved support for editing nested structures in the editor too!

1 week ago 0 0 1 0
<aside class="callout callout-warning">
  <strong><p>Breaking change</p></strong>
  <p>
    The <code>createEditor</code> API changed in
    <code class="version-badge">@portabletext/editor@6.0.0</code>.
    See the migration guide.
  </p>
</aside>

<aside class="callout callout-warning"> <strong><p>Breaking change</p></strong> <p> The <code>createEditor</code> API changed in <code class="version-badge">@portabletext/editor@6.0.0</code>. See the migration guide. </p> </aside>

You're right that the spec document focuses on the flat array (we should make this clearer). We just shipped a custom blocks guide for the editor that covers the nesting pattern: portabletext.org/editor/guides/custom-blocks/

1 week ago 1 0 1 0
import {PortableText} from '@portabletext/react'

const components = {
  types: {
    // Custom block: callout with nested PT fields
    callout: ({value}) => (
      <aside className={`callout callout-${value.style}`}>
        <strong>
          <PortableText value={value.title} />
        </strong>
        <PortableText value={value.body} components={components} />
      </aside>
    ),

    // Inline object: version badge inside text flow
    versionBadge: ({value}) => (
      <code className="version-badge">
        {value.package}@{value.version}
      </code>
    ),
  },
}

<PortableText value={content} components={components} />

import {PortableText} from '@portabletext/react' const components = { types: { // Custom block: callout with nested PT fields callout: ({value}) => ( <aside className={`callout callout-${value.style}`}> <strong> <PortableText value={value.title} /> </strong> <PortableText value={value.body} components={components} /> </aside> ), // Inline object: version badge inside text flow versionBadge: ({value}) => ( <code className="version-badge"> {value.package}@{value.version} </code> ), }, } <PortableText value={content} components={components} />

The serializer targets everything cleanly. Call `<PortableText>` recursively on nested fields, and inline objects use the same types map. Pass components down so custom renderers work at any depth.

1 week ago 0 0 1 0
[
  {
    "_type": "callout",
    "_key": "c1",
    "style": "warning",
    "title": [
      {
        "_type": "block",
        "_key": "t1",
        "children": [
          {"_type": "span", "text": "Breaking change"}
        ],
        "markDefs": []
      }
    ],
    "body": [
      {
        "_type": "block",
        "_key": "b1",
        "children": [
          {"_type": "span", "text": "The "},
          {"_type": "span", "text": "createEditor", "marks": ["code"]},
          {"_type": "span", "text": " API changed in "},
          {
            "_type": "versionBadge",
            "_key": "v1",
            "package": "@portabletext/editor",
            "version": "6.0.0"
          },
          {"_type": "span", "text": ". See the migration guide."}
        ],
        "markDefs": []
      }
    ]
  }
]

[ { "_type": "callout", "_key": "c1", "style": "warning", "title": [ { "_type": "block", "_key": "t1", "children": [ {"_type": "span", "text": "Breaking change"} ], "markDefs": [] } ], "body": [ { "_type": "block", "_key": "b1", "children": [ {"_type": "span", "text": "The "}, {"_type": "span", "text": "createEditor", "marks": ["code"]}, {"_type": "span", "text": " API changed in "}, { "_type": "versionBadge", "_key": "v1", "package": "@portabletext/editor", "version": "6.0.0" }, {"_type": "span", "text": ". See the migration guide."} ], "markDefs": [] } ] } ]

Here's a callout block with nested rich text in both title and body. The body has bold, code marks, and an inline object (versionBadge) sitting right in the text flow alongside spans.

1 week ago 0 0 1 0

Great question! PT handles this through custom block types. A callout can have title and body fields that are each full Portable Text arrays: nested rich text with marks, inline objects, etc. This works for annotations too. Top-level is always an array of objects though.

1 week ago 0 0 1 0
Advertisement
Preview
Portable Text A JSON-based specification for structured block content

Portable Text is a spec for block content as structured JSON.

It's also an editor for authoring it. In production since 2017. Open spec.

The docs at portabletext.org just got a major overhaul →

1 week ago 20 5 1 0

So The Pitt is basically The Bear, but for ER.

1 week ago 3 0 0 0

@weratedogs.com integration when? 👀

1 week ago 1 1 0 0
Video

Ken built a dog adoption app where you skip the filters & toggles and just type "fluffy, will love the stray kittens, won't destroy my small apartment." Sanity Agent Context does the rest.

www.sanity.io/blog/better-...

1 week ago 4 2 1 0

S1: THE P I TT
S2: T H E P I T T

1 week ago 0 0 0 0
Preview
The 10 laws of developer experience for content management systems These ten laws are a checklist for CMS developer experience in a world where humans and agents both need to build on top of your content system.

Wrote down the 10 things I look for when evaluating a CMS, after watching the @emdashcms.com / @wordpress.org conversation focus on hosting and Gutenberg.

What we're not talking about is what a CMS is for, and it's not serving HTML from your preferred cloud/Raspberryπ.

www.knut.fyi/blog/2026-04...

1 week ago 2 0 0 0
Video

I'm having so much fun with the @sanity.io Content Agent API.

Building a "conference management system" - imagine being able to just update your conference rig via chat?

2 weeks ago 3 1 0 0

awesome to hear!

2 weeks ago 1 0 0 0

A month ago I was bemoaning the state of @sanity.io - I was wrong.

I’ve just spent the past couple of days setting up a new site & getting to grips with all the new features. Sanity haven’t spread themselves thin. They’ve made an epic platform to build… ANYTHING! 🥰 🤓 🧑‍💻

2 weeks ago 9 3 2 0
Preview
Agentic developer experience starts with your system, not your prompts The new 'time to hello world' isn't determined by a developer reading your getting started guide. It's someone typing a naive prompt into an agent. How should we think about that?

Skills files and llms.txt are signage. Your API design is the hallway. With well-designed hallways, you don't have to think about where to go.

I wrote up a framework for developer tools teams who wants to improve agentic developer experience.

www.knut.fyi/blog/2026-03...

2 weeks ago 1 0 0 0
Advertisement
A Day in the Life of an Ensh*ttificator
A Day in the Life of an Ensh*ttificator YouTube video by Forbrukerrådet - Norwegian Consumer Council

is it just me, or have we seen that SNL UK budger sketch before?

ah yes, the norwegian consumer council did it a month ago (and better if you ask me)

www.youtube.com/watch?v=T4Up...
www.youtube.com/watch?v=YQYt...

3 weeks ago 2 0 0 1

Turns out that bringing your humanities degree to agent design might be a pretty good (and valuable) idea.

1 month ago 0 1 0 1
Post image Post image

1 month ago 1 1 0 0
Video

Content Agent now works in Slack.

It reads the thread, looks at screenshots, understands what your team decided, and does the work. Fixes the typo buried three components deep, translates your launch page, catches the SEO fields you forgot. Saves edits as drafts.

www.sanity.io/blog/content...

1 month ago 5 2 1 0
Video

buying a domain that just asks for a C&D?
asking users to plop their API keys into a random website?
using AI to make prose from your networks logs?

you should not do this, but i did for the lolz

claudeflare.app

1 month ago 0 0 0 0
Claudeflare Claude analyzes your Cloudflare traffic with genuine fascination, unnecessary caveats, and philosophical concern for your 404s.

i made a silly pun site. claudeflare.app

1 month ago 1 0 0 0
Preview
Structure Powers Intelligence | Sanity AI agents need structured content, not scattered docs. Learn why content infrastructure is the foundation for reliable AI—and how to build it right.

"The model wasn't broken. The context was."

Our CEO Magnus Hillestad on why AI agents need structured content, not bigger context windows.

Structure powers intelligence.

sanity.io/blog/structure-powers-intelligence

1 month ago 12 3 0 0

let me know if you have questions!

1 month ago 0 0 0 0
Advertisement

The compacting loading bar of dread.

1 month ago 0 0 0 0
Preview
Portable Text Editor Fully customizable authoring of rich text and block content

have you looked into portabletext.org? (battle tested for 8 years now). i'm sure @hamburger.cloud is happy to answer questions you might have.

1 month ago 1 0 0 0

Fun detail: @gruber.foo shipped a .text suffix to view markdown source in 2004. Serving the same content in a different format isn't new. But "the reader" is.

1 month ago 0 0 0 0

The field guide covers the full spectrum from "do nothing" to MCP integration. Including why dumping your entire corpus into llms-full.txt is probably counterproductive (e.g. Cloudflare's is nearly 50MB).

1 month ago 0 0 1 0