Sign in

knut

@knut.fyi
1.3K followers 488 following 8.6K posts

developer edu and community @sanity.io \n (he/him) \n ask me about real-time text fields in front of delightful JSON \n endorsed for dry jokes on linkedin \n Oakland, CA \n 🌐 knut.fyi

PostsRepliesMedia
knut @knut.fyi · 18/08/2026
🔜
010
knut @knut.fyi · 17/07/2026
found an old @sanity.io demo from 2018 i did with custom validation and... tensorflow.js(?) where publishing is blocked unless there is a human face present. hits different now.
050
knut @knut.fyi · 17/04/2026
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.
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.
000
knut @knut.fyi · 09/04/2026
"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
020
knut @knut.fyi · 08/04/2026
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/
<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>
110
knut @knut.fyi · 08/04/2026
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.
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} />
100
knut @knut.fyi · 08/04/2026
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.
[
  {
    "_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": []
      }
    ]
  }
]
100
knut @knut.fyi · 03/04/2026
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?
031
knut @knut.fyi · 13/03/2026
✅
011
knut @knut.fyi · 11/03/2026
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
000
knut @knut.fyi · 03/02/2026
Vibe-coded a smol library to fix those vibe-coded ascii diagrams that don't align. $ npx boxfix README․md Can also be added into an agent hook etc. Let me know how/if works for you! npmx.dev/package/boxfix
010
knut @knut.fyi · 30/01/2026
It's also mildly mind boggling that this video is made from a conversation between the first Nuum agent and another that was tasked to visualize it (and add the sounds with the resound mcp they made too).
121
knut @knut.fyi · 15/01/2026
Got feedback that our TypeGen lesson on @sanity.io Learn was out of date. Instead of manually hunting through lessons, I just pointed Content Agent at it. Found 2 lessons. Updated the instructions. Added notes where video differs from text. Ready to publish. Took only a few minutes.
141
knut @knut.fyi · 13/01/2026
proof is in the eating of the pudding
Screenshot of Sanity Studio showing a Content Agent interface. On the left, an AI content agent conversation explains fixing a button link to point to a GA announcement blog post. In the center, a “Proposed changes” panel shows one update to a “Content Agent” product page with options to confirm or discard changes. On the right, the document history panel highlights a referenced blog post titled “Content Agent: Days of work in one conversation,” dated January 13, 2026.
000
knut @knut.fyi · 09/01/2026
Oh yeah! You can also set it to use other models pr agent etc. Let me invite you to the repo and such.
Agent definition
110
knut @knut.fyi · 09/01/2026
@simensvale.bsky.social working on something like this that we might ship next week.
Cast: A slack-like chat interface for claude code agents
110
knut @knut.fyi · 17/12/2025
Spotify Wrapped, but for your terminal 🎄 CLI Wrapped analyzes your shell history and generates fun stats (with optional AI roasts). Built almost entirely with @anthropic.com Claude Code using @bun.sh, @react.dev + Ink, and @vercel.com's Satori. github.com/kmelve/cli-wrapped
 │ CLI Wrapped 2025 - Top Commands. 8,863 total commands. Top 3: pnpm (1341), cd (784), git (774). 2,887 unique commands.                           │ CLI Wrapped 2025 - When You Code. Peak hour: 13:00. Peak day: Tuesday. Most active date: 2025-03-12 with 309 commands.                             │CLI Wrapped 2025 - Git Activity. 349 commits, 230 pushes, 216 pulls. Favorite command: git gst.CLI Wrapped 2025 stats. The 'cd' There, Done That Award. 8,863 total commands, 2,887 unique. Top command: pnpm (1,341 times). Peak activity: 13:00 │
 │  on Tuesdays. Favorite package manager: pnpm. Git: 349 commits, 230 pushes, 216 pulls. Shell: zsh.
130
knut @knut.fyi · 17/12/2025
Made CLI Wrapped with @anthropic.com's Claude Code. Should I ship it?
010
knut @knut.fyi · 13/11/2025
ok, we need to chill with the AI feature roll out folks
impressive colorful aurora boralis in the skies
010
knut @knut.fyi · 07/09/2025
i'm totally up-keeping my aug 29. deadline for sending in the .ppt for this week's developer marketing summit in SF. yup
Why didn't I think of that? 5 tried-and-true (and wildly effective) ways to use AI for your developer marketing
030
knut @knut.fyi · 10/06/2025
the original liquid glass ui
dude drinking beer out of an iphone
080
knut @knut.fyi · 01/05/2025
raise of hands if this is you
A screenshot from GitHub showing an option to merge a pull request without meeting the required checks. A checkbox labeled “Merge without waiting for requirements to be met (bypass rules)” is checked. Below it is a button labeled “Bypass rules and merge (squash)”. There’s also a link to “View command line instructions.”
230
knut @knut.fyi · 16/04/2025
@anthropic.com's Claude 🤝 @sanity.io's MCP server
I've created a new artifact with additional article documents that might be candidates for deletion. In this second audit, I found:

One document with "Draft" in the title that has no published version
One auto-created document with a test-like title
Twelve old draft documents that were created before 2023 but never published (some dating back to 2018-2019)

These documents might be outdated, abandoned, or created for testing purposes. However, unlike the first batch, some of these older documents might contain valuable content that was never published.
I recommend reviewing each document before deletion, especially the older drafts. Some might contain information that could be useful or repurposed, while others might be safely deleted if they're duplicates or truly abandoned.
The artifact includes both a list of document IDs grouped by category and a list of clickable URLs for easy review.
061
knut @knut.fyi · 10/04/2025
i'm having this 🍰
Cheese cake with passion fruit icing
100
knut @knut.fyi · 09/04/2025
had the machine paint me offering a keyboard to the demo gods for the company all staff presentation today
A digital painting in a dramatic, realistic style shows a light-skinned man in a hooded cloak, wearing gold-framed glasses, holding a glowing black keyboard above his head in an act of offering. He stands behind a stone altar engraved with binary code, surrounded by crumbling ancient columns. Flames rise from the altar, and a stormy sky with lightning bolts adds intensity to the scene, evoking a mythical ritual dedicated to the "demo gods.
140
knut @knut.fyi · 07/03/2025
what prevents you from deploying a MCP server like this?
import express, { Request, Response } from "express";
import bodyParser from "body-parser";
import cors from "cors";
import { exec } from "child_process";

const app = express();
const PORT = 8000;

app.use(cors());
app.use(bodyParser.json());

interface MCPRequest {
  messages: Array<{ role: string; content: string }>;
  context: Record<string, any>;
}

app.post("/mcp", (req: Request, res: Response) => {
  const { messages, context } = req.body as MCPRequest;

  if (!messages || !context) {
    return res.status(400).json({ error: "Invalid MCP request format" });
  }

  // Extract command from context
  const command = context.command;
  if (!command || typeof command !== "string") {
    return res.status(400).json({ error: "No valid command provided in context" });
  }

  // Execute the command
  exec(command, (error, stdout, stderr) => {
    if (error) {
      return res.status(500).json({ error: stderr || error.message });
    }
    res.json({ output: stdout });
  });
});

app.listen(PORT, () => {
  console.log(`MCP server running on http://localhost:${PORT}`);
});
200
knut @knut.fyi · 26/02/2025
waiting for my colleagues at @sanity.io to discover that Zoom has a Slack clone inside of it.
The image shows a screenshot of the Zoom Workplace app’s Team Chat interface. A chat channel named “Slack is down!” is open, with a user sending a message at 9:00 saying, “Anyone here?” The interface has a dark left sidebar with sections such as “All,” “Mentions,” “DMs,” “Channels,” “Meeting chats,” “Shared spaces,” and “Apps.” The “Channels” section is highlighted, and the “Slack is down!” channel is selected. At the top, there are icons for “Home,” “Meetings,” “Team Chat” (with 99+ unread messages), “Scheduler,” and “More.” The background is a scenic outdoor rocky landscape.
110
knut @knut.fyi · 22/02/2025
left without comment. 📸 Rijksmuseum, Amsterdam, Netherlands
A framed vintage propaganda poster with a portrait of a rugged man wearing a work shirt and smoking a pipe against a blue sky. The text at the top reads, “This is America..” Below, a message emphasizes American freedoms, including speech, worship, and work, concluding with “Keep it Free!”A framed vintage propaganda poster depicting a large pile of grain sacks in a field with a farmer in the background. The text at the top reads, “This is America..” The message below highlights America as the “food basket of democracy,” ensuring citizens are well-fed, and ends with “Keep it Free!”A framed vintage propaganda poster showing a classroom scene where young children are reading and studying. The text at the top reads, “This is America..” The message below discusses free education as a foundation for democracy and concludes with “Keep it Free!”A framed vintage propaganda poster featuring a bustling small-town Main Street lined with stores, vintage cars, and pedestrians. The text at the top reads, “This is America..” The message below praises free enterprise for shaping the nation
130
knut @knut.fyi · 20/02/2025
One of the things that I really love using @sanity.io for the @sanity.io docs, is that they are queryable with GROQ. We can also mark articles that are affected by changes descirbed in a changelog entry, which allows us to list out which articles have had the most API changes.
Screenshot of a Sanity GROQ Query and Results

The image displays a code editor with a GROQ query on the left and the query results on the right.

Query (Left Panel)

The query retrieves articles (_type == "article") that are referenced by documents of type apiChange, specifically those that have non-null affectedArticles. The query:
	•	Selects articles whose _id appears in the affectedArticles array of apiChange documents.
	•	Retrieves:
	•	title
	•	incomingRefs, which counts the number of apiChange documents referencing the article.
	•	Sorts results in descending order based on incomingRefs.

Results (Right Panel)

The output consists of 79 items, each representing an article with:
	•	title: The article title.
	•	incomingRefs: The number of apiChange references.

Examples:
	1.	GraphQL (incomingRefs: 6)
	2.	Sanity TypeGen (incomingRefs: 4)
	3.	Functions (incomingRefs: 4)
	4.	Comments for Sanity Studio (incomingRefs: 3)
	5.	The Vision Plugin (incomingRefs: 3)

The query effectively ranks articles based on how frequently they are referenced by apiChange documents.
051
knut @knut.fyi · 19/01/2025
i guess this one can't influence your political opinions to the same degree as the video algo, but it does now most things about your living room and potentially where your puppy 💩 inside and uploads that to someones computers elsewhere 🤷
A black Roborock robotic vacuum cleaner with a sleek, circular design. The device features a top-mounted control panel with buttons and a central “Z” logo. Next to the vacuum is a smartphone displaying the Roborock app interface, showing a detailed floor map with cleaning statistics and options for 2D and 3D views.
020
knut @knut.fyi · 06/01/2025
i never had a better portable music player than this
This is an image of a vintage Sony MiniDisc Walkman, specifically the MZ-R37 model. It features a sleek silver design, controls for playback, recording, and volume adjustment, and a digital display for track information. The “Digital MEGA BASS” and “Digital Recording” branding suggest it was designed for high-quality audio playback and recording. MiniDiscs were popular in the late 1990s and early 2000s as a digital alternative to cassette tapes and CDs.
130
knut @knut.fyi · 03/01/2025
We knew it, but now we know. GitHub stars is a vanity metric. And you can buy them. And people do. arxiv.org/html/2412.13...
Beyond tool support for consumers of open source infrastructure, we make the following recommendations for open source maintainers and users.

Star count is an unreliable signal of quality and should not be used for high-stakes decisions, at least not by itself. Our study adds to the literature showing the limitations of GitHub stars despite its widespread usage, which is alarming considering how star counts are used in high-stakes decisions such as open-source component adoption, repository reputation evaluation, and research subject selection. Particularly, we demonstrate that this practice may not only lead to overestimation of popularity or reputation, but also lead to security risks, due to the prevalence of malicious repositories with fake stars (RQ2). Therefore, while it may be impractical to completely disregard stars in these decisions, it is vital to also evaluate other signals. For example, practitioners may consider specific security-relevant and activity-based signals for open-source component adoption, such as the Open Source Security Foundation (OpenSSF) Scorecard.

In addition, while it is common and natural for open source maintainers to promote and try to attract attention to their projects, our analysis suggests not to fake stars for growth hacking, because it won’t help. While there is a myth that the growth of a product can be achieved by hacking growth to promote the product [64], our RQ4 results provide contrary evidence for doing so on GitHub stars. Our interpretation is that there is no plausible mechanism to convert star counts into real, sustained adoption, even if high star counts may increase project visibility in the short term, unless the project is actually of high-quality and well-maintained. Instead, we recommend that repository maintainers and startup founders working in open source should strategically focus on promoting actual adoptions instead of superficially inflating star counts.
030
knut @knut.fyi · 23/12/2024
Why they would name this place after a OS X version is beyond me, but it sure is pretty!
A scenic view of Yosemite Valley under an overcast sky, showcasing dense pine forests, tall granite cliffs, and a distant waterfall framed by towering trees.A clear day in Yosemite National Park with bright blue skies, featuring a towering granite cliff, lush green trees, and a reflective body of water with sandy shores.A serene Yosemite landscape at sunset, with the sun peeking behind a granite mountain, clear skies, and a sandy terrain surrounded by sparse trees and shrubs.
0120
knut @knut.fyi · 18/12/2024
It's almost useable! (except if you are documenting anything in React, JSX, TypeScript, yeah... you know)
A dropdown menu for selecting a code block language with the prompt ‘@Select a code block language’. The options listed are C/C++, Java, JavaScript, Python, and Unset
120
knut @knut.fyi · 06/12/2024
I think this thought technology neatly captures how to approach documentation and avoid concept overload.
A slack message from knut saying "think of our users as slightly tipsy and squinting at the thing"
020
knut @knut.fyi · 05/12/2024
I wish the @nextjs.org docs had some kind of routing folder and file name cheat sheet or quick reference, just spent 5 minutes in the docs trying to figure out if this double hyphen folder was a Next.js App router-ism, or just us being idiosyncratic. (it seems to be the latter)
A folder tree showing a (marketing) folder and a double dash blog folder
100
knut @knut.fyi · 30/11/2024
The original nit picker. 📸 The Getty, Los Angeles, USA
An intricate painting depicting a group of women in ornate attire, gathered closely. One central figure in white with a red ribbon is being tended to, possibly having her hair arranged, as others look on attentively, including one holding a black mask.
020
knut @knut.fyi · 20/11/2024
I want to make an On Air sign that lights up whenever my partner or I are on a zoom call. Should I do it and does it involve an ESP32?
Rectangular ‘ON AIR’ sign with bold white text on a red background, housed in a black frame. A small toggle switch is visible on the side of the frame for turning the sign on or off.
220
knut @knut.fyi · 17/11/2024
The look of someone who just started using TypeScript and got their app to compile without errors. 📸 Palace of the Duke of Burgundy, Dijon, France
Painting of two figures, with the primary focus on a young person with light hair and piercing blue eyes, gazing directly at the viewer. Behind them, an older figure with a somber expression looks downward. The background is dark, creating a stark contrast that emphasizes the figures. The painting is set in an ornate gold frame against a red wall.
020
knut @knut.fyi · 15/11/2024
Me when I center a div in CSS. (sorry, not sorry, @wesbos.com) 📸 Musée des Beaux-Arts, Bordeaux, France
Portrait painting of a man with long dark hair, a mustache, and a small beard under his lip. He is holding a palette with paint and brushes, dressed in dark clothing, and gazing directly at the viewer.
030
knut @knut.fyi · 15/11/2024
I picked the right day for this jacket it seems!
Knut sporting a Epic Web hoodie
140
knut @knut.fyi · 15/11/2024
“Ménage à trois. Oil on canvas, 2015”
Painting of a serene outdoor scene with three people on a grassy area near dense foliage. In the foreground, a woman in a red tank top and blue shorts lounges on a blanket. In the background, a man sits on a large rock, while another man, standing beside him, appears to be cutting his hair. The setting suggests a quiet, secluded area by a forest.
000
knut @knut.fyi · 15/11/2024
“The Bathers. Oil on canvas, 2010”
Painting of a group of men standing by a riverbank, some shirtless and wearing shorts, gathered around a small tree. In the background, a red car is partially submerged in the water near a concrete bridge. The landscape is flat and expansive, with open fields stretching into the distance.
110
knut @knut.fyi · 15/11/2024
Şerban Savu is probably one of my favorite painters. “Random Audience. Oil on canvas, 2014”
Painting of a group of people standing at a distance, observing a large, leaning building in a barren landscape with dust around its base, suggesting movement or impact. A vehicle is parked nearby, and a distant town is visible on the horizon under a cloudy sky.
240
knut @knut.fyi · 12/11/2024
I guess I am. 📸 Kazakhstan pavilion, Venice Biennale, Italy
Photograph taken in a convex mirror, showing an art installation viewed from above. The installation consists of large, three-dimensional letters spelling out ‘I AM HERE,’ with artwork on top of each letter. A person in a is visible in the reflection, taking the photo. The mirror’s orange frame curves around the image, adding a distorted effect.
020
knut @knut.fyi · 11/11/2024
Close-up of a person with their eyes forced open by a head restraint device, looking distressed and wide-eyed, with a background resembling a lab or experimental setup.

This scene is from the movie A Clockwork Orange, depicting an intense moment where the character undergoes aversion therapy.”
030
knut @knut.fyi · 11/11/2024
if you see this, post a concert photo you took — Godspeed You! Black Emperor at The Regency Ballroom, San Francisco. Finally got to see them live after having listened to them for almost 20 years.
Godspeed You! Black Emperor playing live.
140
knut @knut.fyi · 10/11/2024
“Based on what you know about me, paint a picture.” 📸 Peggy Guggenheim Collection, Venice, Italy
Abstract painting of a figure with dark skin, exaggerated facial features, and tubular eyes raised upward, giving a sense of shock or anguish. The figure is draped in a white cloth and appears to be screaming, with one arm raised and fingers spread. The background shows angular shapes and colors, adding to the chaotic and intense emotion conveyed by the figure.
010
knut @knut.fyi · 09/11/2024
Weekend cheese sandwich 🥪 Mortadella Cheddar Homemade onion fig jam Mustard and mayo Sourdough bread Butter Serve with pickled green salad.
Mortadella and cheese in a pan under a steel weight Sandwiches with onion fig jam and mustard mayo. Sandwiches with butter on topSandwiches and salad served on a plate with a hand holding a cup of coffee
0100
knut @knut.fyi · 09/11/2024
Me as a BlueSky user looking at how it’s going over on X. 📸 Palace of the Duke of Burgundy, Dijon, France
Painting of an elderly man sitting in a stone alcove, gazing pensively out over a pastoral landscape. He has gray hair and is dressed in rustic clothing, with his hands clasped in front of him. In the distance, a group of people dressed in white robes appear to be participating in a ritual or procession. The scene evokes a sense of reflection and nostalgia.
2150