Skip to main content
HolyStitch converts your Stitch screens without spending a single AI token on the conversion itself. Everything from HTML fetching to file writing is deterministic code — no LLM calls, no guesswork.

Input and output

Input: RawScreen[] Each screen is a plain object with three fields:
Screens are either passed directly by the caller or fetched from the Stitch API via fetchScreens. Output: ConvertStitchOutput

The nine-step pipeline

1

Resolve screens

The Stitch SDK sometimes returns a signed download URL in the html field instead of raw HTML. The resolver detects this by checking whether the string starts with http:// or https://, then fetches the real content before any other step touches it.
All screens are resolved in parallel via Promise.all.
2

Parse HTML comment boundaries → component slices

parseStitchHtml reads the body HTML and scans for <!-- ComponentName --> markers using an AST built by htmlparser2. Each marker claims the next sibling block element as a named component slice, producing a full component tree.See Component extraction for the full algorithm.
3

Extract fonts and custom CSS from `<head>`

The parser scans the <head> for Google Fonts <link> tags and inline <style> blocks. Font links are split into two buckets:
  • Text fonts (Inter, JetBrains Mono, etc.) — eligible for next/font/google optimization in Next.js
  • Icon fonts (Material Symbols, Material Icons) — always loaded via CSS @import because next/font/google does not support them
Custom CSS from <style> blocks is accumulated across all screens and written into globals.css / src/index.css.
4

Extract Tailwind `theme.extend` config

Stitch embeds a tailwind.config object in a <script id="tailwind-config"> tag. The parser extracts theme.extend, plugins, and darkMode using balanced-bracket parsing (not JSON.parse — the config uses JS object syntax, not strict JSON).When multiple screens are processed, color token values are compared across screens. Conflicts are recorded as warnings:
5

Compile each component's HTML to JSX

compileHTMLToJSX applies a series of deterministic transforms to each component’s HTML slice:
  • Attributes renamed (class → className, for → htmlFor, etc.)
  • Event handlers camelCased (onclick → onClick)
  • Void elements self-closed (<img>, <br>, <input>, etc.)
  • Inline style strings converted to JS objects
  • Material Symbols icon-name text stripped
  • <pre><code> curly braces escaped as HTML entities
See HTML to JSX for the full transform reference.
6

Wrap each slice in a React component file

Each compiled JSX slice is wrapped in a .tsx / .jsx file with:
  • A 'use client'; directive if the component contains event handlers or <button> elements (Next.js only)
  • import statements for any child components
  • An empty typed interface ComponentNameProps {} with prop hints surfaced as comments
  • A named default export function
7

Generate page files and all framework config files

For each screen, a page file is generated that imports its root components and renders them. The page body uses pageBodyHtml — the original body HTML with root component blocks replaced by <ComponentName /> placeholders.Config files generated alongside components and pages:
For Vite projects, routing is hash-based (/#/route-name). src/App.tsx maps every route to its page component using a plain object lookup — no router library needed.
8

Write everything to disk

writeProjectFiles writes all accumulated ProjectFile objects to the output directory. It creates intermediate directories automatically and supports base64-encoded binary files.
The original Stitch HTML for each screen is also written to stitch-source/<screen-name>.html as a reference file for post-conversion AI work.
9

Write `project-context.md`

The final step writes project-context.md to the output directory. This file is designed to be read by an AI assistant in a follow-up session and contains:
  • A source map linking each route to its stitch-source/*.html reference file
  • A fix checklist (unclosed tags, style objects, routing, font token normalization)
  • A full component list with file paths
  • All structural warnings generated during conversion
project-context.md is the handoff point between HolyStitch and your AI assistant. Open it after conversion to understand exactly what was generated and what still needs attention.

Why no AI tokens are needed

Every transform in the pipeline is a deterministic algorithm:
  • Attribute renaming — a static lookup table (ATTR_MAP)
  • Style conversion — a balanced-bracket CSS parser
  • Component detection — an AST scan for uppercase HTML comments
  • Shared component deduplication — Jaccard similarity over token sets
  • Tailwind config extraction — balanced-bracket object parsing
  • File writing — fs.writeFile with directory creation
There are no calls to any LLM, no embedding lookups, and no probabilistic steps. The same input always produces the same output. If the generated JSX has issues (unclosed tags from malformed Stitch HTML, hardcoded href="#" links), project-context.md documents exactly what needs fixing and where to find the source HTML.

Shared component detection

When the same component name appears on multiple screens, HolyStitch computes Jaccard similarity over word tokens from both HTML strings:
  • Similarity ≥ 0.7 — the component is treated as shared; the existing file is reused
  • Similarity < 0.7 — the component is treated as a different widget that happens to share a name; a screen-scoped copy is created as ComponentName + PascalCasedScreenName, and a warning is emitted