Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/BaselAshraf81/holystitch/llms.txt

Use this file to discover all available pages before exploring further.

The parser module (pipeline/parser.ts) reads a raw Stitch HTML document and extracts everything the pipeline needs to generate a React project: font links, custom CSS, the Tailwind theme config, and a full hierarchical component tree built from HTML comment markers.

parseStitchHtml

function parseStitchHtml(html: string): StitchParseResult
The main parser entry point. Accepts a full Stitch HTML document and returns a StitchParseResult.

Component extraction algorithm

Stitch embeds <!-- ComponentName --> comment markers throughout the HTML at every level of nesting. The parser uses htmlparser2 with character position tracking to locate these markers and build a component tree:
  1. Scan sibling nodes for uppercase HTML comments (<!-- TopNavBar -->, <!-- HeroSection -->, etc.).
  2. Each comment “claims” the next sibling block element as its component body.
  3. After claiming an element, the parser recurses into it to find nested sub-components — producing a tree, not just a flat list.
  4. Only root components (depth 0, no parent) appear in pageBodyHtml. Structural wrappers like <main> and <section> that don’t have a comment marker are preserved in the page file.
Label normalisation — raw comment text is normalised to a valid PascalCase component name before use:
Raw commentNormalized name
TopNavBar from JSON mappingTopNavBar
Entry 1: LatestEntry1
Bold Footer CTABoldFooterCta
HeroSection - darkHeroSection
A normalised name must be at least 3 characters and start with an uppercase letter, or the comment is ignored. Content threshold — elements that have no child elements and are under 300 characters are skipped as decorative. This prevents tiny <div> spacers from becoming empty components.

Return type: StitchParseResult

interface StitchParseResult {
  head: HeadAssets;
  tailwindConfig: ExtractedTailwindConfig | null;
  components: ParsedComponent[];
  pageBodyHtml: string;
  pageBodyComponentNames: string[];
  bodyHtml: string;
}
head
HeadAssets
Font links and custom CSS extracted from the <head>.
tailwindConfig
ExtractedTailwindConfig | null
The Tailwind configuration extracted from a <script id="tailwind-config"> block or any <script> containing tailwind.config. Returns null if no config script is found.
components
ParsedComponent[]
All components extracted from the HTML, in tree order (parent before children). Each component has its direct child components replaced by <ChildName /> placeholders in its html field.
pageBodyHtml
string
The page body HTML with all root components replaced by <ComponentName /> placeholders. Structural wrappers (<main>, <nav>, etc.) that wrap components without their own comment marker are preserved. This becomes the JSX inside the page file’s return statement.
pageBodyComponentNames
string[]
Names of root-level components only. These are the names the page file imports — child components are imported by their parent component files instead.
bodyHtml
string
Raw <body> content, unmodified. Used as a fallback when no comment markers are found — the entire body becomes a single component named after the screen.

extractGoogleFonts

function extractGoogleFonts(html: string): GoogleFontSpec[]
Scans a full HTML document for Google Fonts URLs — both in <link href="..."> tags and in @import url(...) statements — and returns structured font specifications for use with next/font/google. The function deduplicates by font family name, so a font referenced via both a <link> tag and a CSS @import is returned only once.

Return type: GoogleFontSpec[]

interface GoogleFontSpec {
  family: string;
  weights: string[];
  subsets: string[];
  variable: string;
}
family
string
Human-readable font family name with spaces, e.g. "Inter", "JetBrains Mono", "Roboto Condensed". Spaces are decoded from + in the Google Fonts URL.
weights
string[]
Array of weight strings to pass to next/font/google. If the URL uses a variable weight range (e.g. wght@100..900), the weights default to ["400", "500", "600", "700", "800"]. If specific weights are listed (e.g. wght@400;700), those are used directly. If no weight spec is present, defaults to ["400"].
subsets
string[]
Always ["latin"]. Stitch designs target Latin character sets.
variable
string
camelCase identifier derived from the family name — used as the variable name in the generated layout.tsx import. The first character is lowercased and spaces are converted to camelCase:
FamilyVariable
Interinter
JetBrains MonojetBrainsMono
Roboto CondensedrobotoCondensed
DM SansdMSans

Icon font handling

Font families in the Material Symbols and Material Icons families ("Material Symbols Outlined", "Material Icons", etc.) are excluded from GoogleFontSpec results. These fonts cannot be loaded via next/font/google and must remain as CDN @import links in globals.css. The pipeline filters them out before calling extractGoogleFonts for the next/font/google optimization path.

Example

import { extractGoogleFonts } from './pipeline/parser';

const html = `
  <head>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400..700&display=swap" rel="stylesheet">
  </head>
`;

const fonts = extractGoogleFonts(html);
// [
//   { family: "Inter", weights: ["400", "500", "700"], subsets: ["latin"], variable: "inter" },
//   { family: "JetBrains Mono", weights: ["400", "500", "600", "700", "800"], subsets: ["latin"], variable: "jetBrainsMono" }
// ]
The pipeline uses these specs to generate next/font/google imports in app/layout.tsx:
import { Inter, JetBrains_Mono } from 'next/font/google';
const interFont = Inter({ subsets: ["latin"], weight: ["400", "500", "700"], display: "swap" });
const jetBrainsMonoFont = JetBrains_Mono({ subsets: ["latin"], weight: ["400", "500", "600", "700", "800"], display: "swap" });
The next/font/google optimization path replaces @import url(...) Google Fonts calls in globals.css entirely. The original <link> tags from the Stitch HTML are not written to the output HTML — Next.js inlines the optimized font during build instead.

Build docs developers (and LLMs) love