feat: add Portable Text serialization and conversion skills#16
feat: add Portable Text serialization and conversion skills#16
Conversation
Add two new skills covering Portable Text workflows outside the editor: ## portable-text-serialization Render PT content across frameworks: - React / Next.js (@portabletext/react) - Svelte / SvelteKit (@portabletext/svelte) - Vue / Nuxt (@portabletext/vue) - HTML strings (@portabletext/to-html) - Plain text extraction (toPlainText) Each rule covers typed components, custom types/marks/blocks, performance patterns, and framework-specific idioms. ## portable-text-conversion Convert external content into PT blocks: - HTML → PT via @portabletext/block-tools (htmlToBlocks) - Markdown → PT via HTML intermediate or AST-based approach - Manual PT block construction for any data source Includes custom deserializer patterns, pre-processing, image upload during migration, and a validation checklist. Both skills pass `npm run validate` via skills-ref.
Major corrections based on thorough research of portabletext.org, the portabletext/editor monorepo, and all @portabletext/* packages: ## Key changes ### @portabletext/markdown — NEW - Added rules/markdown.md to serialization skill (PT → Markdown) - Rewrote rules/markdown-to-pt.md to use markdownToPortableText() as the primary approach instead of the MD→HTML→PT workaround - portableTextToMarkdown() and markdownToPortableText() are both covered, with custom renderer/matcher examples ### Astro support — NEW - Added rules/astro.md covering astro-portabletext (officially recommended by Sanity for Astro projects) ### Legacy package corrections - Clarified @sanity/block-tools is legacy, @portabletext/block-tools is current (same API) - Fixed Schema import in html-to-pt.md - Added deprecation notes throughout ### Ecosystem completeness - Added community serializer table (React Native, React PDF, Solid, Qwik, Liquid, PHP, Python, C#, Dart/Flutter) - Referenced portabletext.org and portabletext/editor monorepo - Listed editor plugins ecosystem All 6 skills pass npm run validate.
Markdown-to-PT (markdown-to-pt.md): - Fix matchers API: block/marks/types are top-level options, not nested under 'matchers' - Add @portabletext/sanity-bridge for using Sanity Studio schemas - Show matcher context props (context.schema, context.keyGenerator) PT-to-Markdown (serialization/markdown.md): - Add built-in DefaultCodeBlockRenderer, DefaultImageRenderer, etc. - Fix blockSpacing: takes a function ({current, next}), not a string - Document renderer prop signatures (value, children, index, isInline, etc.) sanity-migration.mdc: - Replace deprecated @sanity/block-content-to-markdown with @portabletext/markdown - Add markdownToPortableText example for direct conversion - Note @sanity/block-tools deprecation in favor of @portabletext/block-tools - html-to-pt: Add inline comment showing how JSDOM connects to parseHtml option - html-to-pt: Type client parameter as SanityClient with import - manual-construction: Replace broad sanity.io/docs link with specific @sanity/util repo link - html serialization: Explain why htm/vhtml is safer (auto-escapes attributes, prevents XSS)
| Thanks for the review, @jonahsnider! Pushed fixes for (almost) all your comments:
Re: the package.json validation pattern — agreed, but out of scope for this one. Re: static site generators — yeah, we have folks using Sanity with 11ty, Hugo etc. so that's a real use case. |
jonahsnider left a comment
There was a problem hiding this comment.
thanks for the quick turnaround on feedback - lgtm!
| | ||
| ## Custom Matchers | ||
| | ||
| Matchers are top-level options (not nested under a `matchers` key). Each receives `{context, value}` where `context.schema` lets you validate against the schema: |
There was a problem hiding this comment.
I'm not a skills expert so bear with me, but it sticks out to me that a lot of this is documentation that could go stale. What happens if we release breaking changes to some of these libraries? Would it be better and more future proof to briefly describe what libraries exist and what high level purpose they serve?
christianhg left a comment
There was a problem hiding this comment.
After thinking about #16 (comment) some more, I think the right move is to simply link to the respective repository READMEs. That way, the info doesn't go stale as the libraries progress.
christianhg left a comment
There was a problem hiding this comment.
We'll have to keep these up-to-date
Summary
Two new skills covering Portable Text workflows outside the editor — serialization to all supported frameworks and conversion from external formats.
portable-text-serializationRender PT content across frameworks. Each rule covers typed components, custom types/marks/blocks, performance patterns, and framework-specific idioms.
rules/react.md@portabletext/reactrules/svelte.md@portabletext/svelterules/vue.md@portabletext/vuerules/html.md@portabletext/to-htmlrules/plain-text.mdtoPlainText()SKILL.md includes the PT structure quick reference and the universal component mapping pattern.
portable-text-conversionConvert external content into PT blocks.
rules/html-to-pt.mdhtmlToBlocks+ JSDOM + custom deserializersrules/markdown-to-pt.mdrules/manual-construction.mdSKILL.md includes the full PT spec as a reference for manual construction.
Gap addressed
The existing toolkit had only
pte-custom-components.md(React-only rendering) andmigration-html-import.md(basic HTML import). These new skills cover the full ecosystem: Svelte, Vue, server-side HTML, plain text, Markdown→PT, and manual block construction.Validation