Skip to main content

How Conversion Works

MigrateKit automatically converts HTML from Webflow’s rich text fields into Sanity’s Portable Text format during migration. This process:
  1. Parses HTML - Reads your Webflow HTML structure
  2. Maps tags to blocks - Converts HTML tags to Portable Text blocks and marks
  3. Preserves semantics - Maintains meaning, not just visual appearance
  4. Handles edge cases - Wraps unsupported content as code blocks

Supported HTML Tags

MigrateKit handles most common HTML tags from Webflow:

Headings

HTMLPortable TextUsage
<h1>style: "h1"Top-level headings
<h2>style: "h2"Section headings
<h3>style: "h3"Subsection headings
<h4>style: "h4"Minor headings
<h5>style: "h5"Rarely used
<h6>style: "h6"Rarely used

Paragraphs & Line Breaks

  • <p>style: "normal" block
  • <br> → New line within block
  • Multiple <br> → New blocks

Text Formatting

HTMLPortable Text MarkVisual
<strong>marks: ["strong"]Bold
<b>marks: ["strong"]Bold
<em>marks: ["em"]Italic
<i>marks: ["em"]Italic
<u>marks: ["underline"]Underlined
<s>, <del>marks: ["strike-through"]Strikethrough
<code>marks: ["code"]Inline code

Lists

Unordered lists:
<ul>
  <li>First item</li>
  <li>Second item</li>
</ul>
Becomes:
[
  {"_type": "block", "listItem": "bullet", "children": [...]},
  {"_type": "block", "listItem": "bullet", "children": [...]}
]
Ordered lists:
<ol>
  <li>First step</li>
  <li>Second step</li>
</ol>
Becomes:
[
  {"_type": "block", "listItem": "number", "children": [...]},
  {"_type": "block", "listItem": "number", "children": [...]}
]
Nested lists are supported with proper indentation levels.
<a href="https://example.com">Click here</a>
Becomes:
{
  "_type": "span",
  "text": "Click here",
  "marks": [{
    "_type": "link",
    "href": "https://example.com"
  }]
}
Link attributes:
  • href - Preserved as href
  • target="_blank" - Preserved as blank: true
  • rel - Preserved if present

Images (Inline)

Images within rich text are converted to image blocks:
<p>Here's an image: <img src="/image.jpg" alt="Description"></p>
Becomes separate blocks:
[
  {"_type": "block", "children": [{"text": "Here's an image:"}]},
  {"_type": "image", "asset": {...}, "alt": "Description"}
]

Handled with Warnings

Some HTML requires special handling:

Tables

Limited SupportBasic tables (<table>, <tr>, <td>) are converted to Portable Text, but complex tables with merged cells or nested tables may not convert perfectly.Recommendation: Review tables in Sanity Studio after import and adjust formatting if needed.

Inline Styles

<span style="color: red;">Red text</span>
Inline style attributes are stripped during conversion. Portable Text doesn’t preserve inline CSS. Why? Portable Text separates content from presentation. You style content in your frontend, not in the CMS.

Custom Classes

<div class="custom-webflow-class">Content</div>
Class names are not preserved. Portable Text has no concept of CSS classes. Solution: Use custom Portable Text blocks in Sanity for special formatting needs.

Unsupported Content

Content that can’t safely convert becomes code blocks:

Scripts & Embeds

<script>alert('hello');</script>
Becomes:
{
  "_type": "code",
  "language": "javascript",
  "code": "alert('hello');"
}
Scripts appear as code blocks in Sanity—they won’t execute. This is a safety feature. Review and replace with Sanity-compatible alternatives.

Iframes

<iframe src="https://youtube.com/embed/abc123"></iframe>
Becomes:
{
  "_type": "code",
  "language": "html",
  "code": "<iframe src=\"https://youtube.com/embed/abc123\"></iframe>"
}
Recommendation: Replace with Sanity’s YouTube embed plugin or custom embed block.

Custom Webflow Elements

Webflow’s custom elements (interactions, animations, CMS-bound elements) become code blocks:
{
  "_type": "code",
  "language": "html",
  "code": "<!-- Original Webflow HTML -->"
}
Review these in Sanity Studio and replace with Sanity-native components.

Conversion Examples

  • Basic Formatting
  • Lists
  • Complex Nesting
HTML:
<h2>My Blog Post</h2>
<p>This is <strong>bold</strong> and <em>italic</em> text.</p>
<p>Here's a <a href="/link">link</a>.</p>
Portable Text:
[
  {
    "_type": "block",
    "style": "h2",
    "children": [{"text": "My Blog Post"}]
  },
  {
    "_type": "block",
    "children": [
      {"text": "This is "},
      {"text": "bold", "marks": ["strong"]},
      {"text": " and "},
      {"text": "italic", "marks": ["em"]},
      {"text": " text."}
    ]
  },
  {
    "_type": "block",
    "children": [
      {"text": "Here's a "},
      {"text": "link", "marks": [{"_type": "link", "href": "/link"}]},
      {"text": "."}
    ]
  }
]

Best Practices

Before Migration

1

Clean up Webflow content

Remove unnecessary HTML before exporting:
  • Delete empty <div> and <span> tags
  • Remove inline styles you don’t need
  • Simplify complex nested structures
2

Identify custom elements

Note any Webflow-specific elements that will need replacement:
  • Custom interactions
  • Dynamic embeds
  • Complex grids or layouts
3

Test with small sample

Export a small collection first to see how your HTML converts

After Migration

1

Review code blocks

Check all code blocks in Sanity Studio:
  • Replace scripts with Sanity-safe alternatives
  • Convert iframes to proper embeds
  • Remove unnecessary preserved HTML
2

Fix formatting issues

Adjust any conversion quirks:
  • Incorrect heading levels
  • Lost spacing
  • Misinterpreted formatting
3

Add semantic improvements

Enhance content with Portable Text features:
  • Custom block types
  • Better link handling
  • Responsive embeds

Common Issues

Cause: Multiple <br> tags or <p> tags with empty content.Fix: Manually add paragraph breaks in Sanity Studio where needed.
Cause: Inline styles or classes were stripped during conversion.Fix: Portable Text separates content from styling. Style your content in your frontend rendering, not in the CMS.
Cause: Images didn’t upload (network error, quota exceeded).Fix: Check the import report for asset failures and manually upload missing images.
Expected: MigrateKit preserves unknown HTML as code blocks for safety.Fix: Review code blocks and replace with Sanity-compatible alternatives.

Learn More