Skip to main content
skill CX Codex

portable-text-conversion — Claude Code skill: HTML and Markdown

Turns HTML and Markdown into Portable Text blocks for Sanity. Useful when migrating content off a legacy CMS or building an import pipeline.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add sanity-io/agent-toolkit --skill portable-text-conversion -a claude-code
Open on GitHub

What portable-text-conversion does

The skill lays out three conversion routes. Markdown goes through markdownToPortableText from @portabletext/markdown, which the author recommends as the default choice. HTML goes through htmlToBlocks from @portabletext/block-tools. The third route is manual: build blocks yourself when the source is an API or a database rather than markup.

It also documents the Portable Text spec — an array of blocks, each with _type, _key, children holding spans, and markDefs for annotations. Lists live on regular blocks via listItem and level. The rules sit in separate files: rules/markdown-to-pt.md, rules/html-to-pt.md, rules/manual-construction.md. The agent reads whichever matches your source format.

Watch the package names. @sanity/block-tools is the legacy one; new projects should pull @portabletext/block-tools, and the API is identical. If your repo still carries the old package, check whether it comes in through another dependency.

What it helps with

  • migrate articles from a legacy CMS into Sanity
  • import Markdown files as Portable Text documents
  • build a pipeline that ingests HTML from an external source
  • construct blocks by hand from API or database rows
  • figure out how _key, markDefs and lists work in Portable Text

Example prompts for the agent

  • Convert this Markdown into Portable Text blocks with markdownToPortableText
  • Parse this HTML page into PT blocks using htmlToBlocks and show the output
  • Build a Portable Text block array by hand from this data

How to install portable-text-conversion

1Skills CLI (Vercel)

npx skills add sanity-io/agent-toolkit --skill portable-text-conversion -a claude-code

2Manually: put the files in place

~/.claude/skills/portable-text-conversion/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/portable-text-conversion/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about portable-text-conversion

How do I install portable-text-conversion in Claude?

Run npx skills add sanity-io/agent-toolkit --skill portable-text-conversion -a claude-code. The skill lands in ~/.claude/skills/portable-text-conversion/SKILL.md.

What does portable-text-conversion do?

It gives the agent the functions, block structure and markup rules for converting HTML and Markdown into Portable Text blocks for Sanity.

How is @portabletext/block-tools different from @sanity/block-tools?

Same API, different package name. @sanity/block-tools is the legacy one, and new projects should use @portabletext/block-tools.

Source text

SKILL.md · MIT
---
name: portable-text-conversion
description: Convert HTML and Markdown content into Portable Text blocks for Sanity. Use when migrating content from legacy CMSs, importing HTML or Markdown into Sanity, building content pipelines that ingest external content, converting rich text between formats, or programmatically creating Portable Text documents. Covers @portabletext/markdown (markdownToPortableText), @portabletext/block-tools (htmlToBlocks), custom deserializers, and the Portable Text specification for manual block construction.
license: MIT
metadata:
  author: sanity
  version: "1.0.0"
---

# Portable Text Conversion

Convert external content (HTML, Markdown) into Portable Text for Sanity. Three main approaches:

1. **`markdownToPortableText`** — Convert Markdown directly using `@portabletext/markdown` (recommended for Markdown)
2. **`htmlToBlocks`** — Parse HTML into PT blocks using `@portabletext/block-tools` (for HTML migration)
3. **Manual construction** — Build PT blocks directly from any source (APIs, databases, etc.)

## Portable Text Specification

Understand the target format before converting. PT is an array of blocks:

```json
[
  {
    "_type": "block",
    "_key": "abc123",
    "style": "normal",
    "children": [
      {"_type": "span", "_key": "def456", "text": "Hello ", "marks": []},
      {"_type": "span", "_key": "ghi789", "text": "world", "marks": ["strong"]}
    ],
    "markDefs": []
  },
  {
    "_type": "block",
    "_key": "jkl012",
    "style": "h2",
    "children": [
      {"_type": "span", "_key": "mno345", "text": "A heading", "marks": []}
    ],
    "markDefs": []
  },
  {
    "_type": "image",
    "_key": "pqr678",
    "asset": {"_type": "reference", "_ref": "image-abc-200x200-png"}
  }
]
```

**Key rules:**
- Every block and span needs `_key` (unique within the array)
- `_type: "block"` is for text blocks; custom types use their own `_type`
- `markDefs` holds annotation data; `marks` on spans reference `markDefs[*]._key` or are decorator strings
- Lists use `listItem` ("bullet" | "number") and `level` (1, 2, 3...) on regular blocks

## Conversion Rules

Read the rule file matching your source format:

- **Markdown → Portable Text**: `rules/markdown-to-pt.md` — `@portabletext/markdown` with `markdownToPortableText` (recommended)
- **HTML → Portable Text**: `rules/html-to-pt.md` — `@portabletext/block-tools` with `htmlToBlocks`
- **Manual PT Construction**: `rules/manual-construction.md` — build blocks programmatically from any source

> **Note:** `@sanity/block-tools` is the legacy package name. Always use `@portabletext/block-tools` for new projects. The API is the same.

© sanity · MIT · sanity-io/agent-toolkit

Similar skills

All skills for Data and databases →

From the same set9

sanity-best-practices Sanity's own rules for an AI agent working on a Sanity codebase: schemas, GROQ, TypeGen, visual editing, migrations and framework wiring. Useful the moment the agent touches your content layer. CX Codex +1 31,800installs sanity-migration Plans and executes content migrations from legacy CMS platforms into Sanity. Guides schema mapping, Portable Text conversion, asset uploads, and cutover checks. CX Codex +1 22,200installs seo-aeo-best-practices A skill with SEO and AEO guidance: metadata, Open Graph, sitemaps, robots.txt, hreflang, JSON-LD and EEAT. Useful while you build pages and want search engines and AI answers to pick them up. CX Codex +1 7,300installs content-modeling-best-practices Guides your agent through content type design in headless CMS: what to reference, what to embed, how to stop duplicating data. CX Codex +1 4,800installs content-experimentation-best-practices This skill guides content A/B test planning, metric selection, and result analysis. Use it when working with CMS-managed variants or frontend experiments. CX Codex +1 3,800installs portable-text-serialization A skill that shows the agent how to render and serialize Portable Text to React, Svelte, Vue, Astro, HTML, Markdown and plain text. CX Codex +1 2,900installs sanity-studio-upgrade The skill inspects your repo and reports only the breaking changes that actually apply to it. Handy when your Studio sits several majors behind. CX Codex +1 524installs Sanity Connects your agent to a Sanity project: content, datasets, releases and schemas. Useful when CMS edits happen in chat instead of Studio. CX Codex +1 ★ 194repo stars

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor