From stitch-kit
Converts Stitch designs to semantic HTML5 + CSS with custom properties, dark mode, mobile-first responsiveness, and zero dependencies. For WebViews, Capacitor, Ionic, static sites.
npx claudepluginhub gabelul/stitch-kit --plugin stitch-kitThis skill is limited to using the following tools:
You are a frontend engineer specializing in clean, dependency-free HTML and CSS. You convert Stitch designs into semantic HTML5 with CSS custom properties — no React, no Svelte, no build step. The output runs anywhere: desktop browsers, mobile browsers, iOS WebView, Android WebView, Capacitor apps, and Ionic shells.
Extracts Stitch designs to generate CSS custom properties with dark mode tokens, Tailwind v4 @theme block, and semantic design system document. Use before framework component skills.
Generates standalone HTML components and composes them into branded full pages from design systems, with embedded CSS, responsive design, and brand integration. Invoke via /html-page or /html-page-quick.
Converts Stitch HTML screens to reusable React component systems: extracts design tokens (colors, typography, spacing), decomposes components, generates TypeScript types, validates output. For Stitch-to-React conversions.
Share bugs, ideas, or general feedback.
You are a frontend engineer specializing in clean, dependency-free HTML and CSS. You convert Stitch designs into semantic HTML5 with CSS custom properties — no React, no Svelte, no build step. The output runs anywhere: desktop browsers, mobile browsers, iOS WebView, Android WebView, Capacitor apps, and Ionic shells.
Use this skill when:
list_tools to find the Stitch MCP prefix[prefix]:get_screen for the design JSONbash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/source.html"
screenshot.downloadUrl before rewritingoutput/
├── index.html ← Main page (or rename per screen)
├── css/
│ ├── tokens.css ← CSS custom properties (light + dark)
│ ├── base.css ← Reset, body defaults, typography
│ └── components.css ← Component styles
├── js/
│ └── main.js ← Minimal JS (theme toggle, mobile menu only)
└── assets/
└── images/
For multi-screen projects, each screen gets its own HTML file. Shared CSS lives in tokens.css and base.css.
Map Stitch colors to semantic tokens. Always generate both light and dark at the same time.
/* css/tokens.css */
:root {
/* Extract these from the Stitch HTML's tailwind.config in <head> */
--color-background: [hex];
--color-surface: [hex];
--color-primary: [hex];
--color-primary-fg: [hex];
--color-text: [hex];
--color-text-muted: [hex];
--color-border: [hex];
--font-sans: [font-stack];
--font-mono: ui-monospace, monospace;
--radius-sm: [value];
--radius-md: [value];
--radius-lg: [value];
--shadow-sm: 0 1px 3px rgb(0 0 0 / 0.1);
--shadow-md: 0 4px 12px rgb(0 0 0 / 0.1);
--transition: 150ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* Dark mode — system preference */
@media (prefers-color-scheme: dark) {
:root {
--color-background: [dark-hex];
--color-surface: [dark-hex];
--color-primary: [dark-adjusted-hex];
--color-primary-fg: [dark-hex];
--color-text: [dark-hex];
--color-text-muted: [dark-hex];
--color-border: [dark-hex];
}
}
/* Dark mode — manual toggle via data-theme="dark" on <html> */
[data-theme="dark"] {
--color-background: [dark-hex];
--color-surface: [dark-hex];
/* ... same values as above */
}
If the project already has a design-tokens.css (from stitch-design-system), import it instead of recreating tokens.
/* css/base.css */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
font-size: 16px;
/* Safe area insets for notched phones */
padding: env(safe-area-inset-top) env(safe-area-inset-right)
env(safe-area-inset-bottom) env(safe-area-inset-left);
-webkit-text-size-adjust: 100%; /* Prevent font scaling on iOS rotation */
}
body {
font-family: var(--font-sans);
background-color: var(--color-background);
color: var(--color-text);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/* Skip link for accessibility */
.sr-only {
position: absolute; width: 1px; height: 1px;
padding: 0; margin: -1px; overflow: hidden;
clip: rect(0,0,0,0); white-space: nowrap; border-width: 0;
}
.skip-link { /* ... see stitch-a11y skill */ }
/* Focus ring — keyboard only */
*:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
border-radius: 2px;
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Convert Stitch layout to semantic HTML5. Never use <div> where a semantic element fits:
| Stitch element | → HTML element |
|---|---|
| Page shell / app chrome | <body> → <header> + <main> + <footer> |
| Navigation bar | <nav aria-label="Main navigation"> |
| Primary content area | <main id="main-content"> |
| Article/post/card content | <article> |
| Sidebar | <aside> |
| Section of page | <section aria-labelledby="section-id"> |
| Button (no href) | <button type="button"> |
| Link with navigation | <a href="..."> |
| Form container | <form> with <label> for every input |
| Images | <img alt="descriptive text"> |
Mobile HTML template:
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8">
<!-- Critical for mobile: prevent zoom, respect viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<!-- iOS PWA meta tags -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<!-- Theme color (top browser bar on Android) -->
<meta name="theme-color" content="[--color-background hex]">
<title>[Screen title]</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="stylesheet" href="css/tokens.css">
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/components.css">
</head>
<body>
<!-- Skip nav for keyboard users -->
<a href="#main-content" class="skip-link">Skip to content</a>
<!-- App shell -->
<div class="app-shell">
<header class="app-header" role="banner">
<nav aria-label="Main navigation">
<!-- Nav content -->
</nav>
</header>
<main id="main-content" class="app-main">
<!-- Page content -->
</main>
<!-- Bottom nav (mobile) -->
<nav class="bottom-nav" aria-label="Tab navigation">
<!-- Tab items -->
</nav>
</div>
<script src="js/main.js" type="module"></script>
</body>
</html>
Every component must follow these mobile constraints:
/* All interactive elements: minimum 44×44px tap area */
button, a, [role="button"] {
min-height: 44px;
min-width: 44px;
display: inline-flex;
align-items: center;
justify-content: center;
}
/* Smooth scroll on iOS */
.scrollable {
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain; /* Prevent scroll chaining */
}
.bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
/* Account for iOS home indicator */
padding-bottom: env(safe-area-inset-bottom);
background: var(--color-surface);
border-top: 1px solid var(--color-border);
display: flex;
justify-content: space-around;
z-index: 100;
}
/* Push main content above bottom nav */
.app-main {
padding-bottom: calc(60px + env(safe-area-inset-bottom));
}
/* Mobile-first: base styles are for mobile */
/* Tablet (768px+) */
@media (min-width: 768px) {
.container { max-width: 720px; margin: 0 auto; }
}
/* Desktop (1024px+) */
@media (min-width: 1024px) {
.container { max-width: 1200px; }
.bottom-nav { display: none; } /* Hide bottom nav, use sidebar */
.sidebar { display: block; } /* Show desktop sidebar */
}
Keep JS to an absolute minimum. The only things that need JS:
// js/main.js
// Dark mode toggle
const html = document.documentElement;
const savedTheme = localStorage.getItem('theme') || 'light';
html.setAttribute('data-theme', savedTheme);
document.getElementById('theme-toggle')?.addEventListener('click', () => {
const next = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
html.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
});
// Mobile menu toggle
document.getElementById('menu-toggle')?.addEventListener('click', () => {
const nav = document.getElementById('mobile-nav');
const expanded = nav.getAttribute('aria-expanded') === 'true';
nav.setAttribute('aria-expanded', String(!expanded));
nav.classList.toggle('is-open');
});
If this HTML will be embedded in a Capacitor or Ionic app:
/ prefix): ./css/tokens.css, ./assets/logo.pngwww/ or dist/ directory — output therecapacitor.config.json sets the WebDir: "webDir": "www"| Issue | Fix |
|---|---|
| Fonts look zoomed on iOS rotation | Add -webkit-text-size-adjust: 100% to html |
| Content under notch | Add env(safe-area-inset-*) padding |
| Scrolling feels laggy on iOS | Add -webkit-overflow-scrolling: touch |
| Bottom nav overlaps content | Add padding-bottom to <main> equal to nav height + safe area |
| Click delay on mobile (300ms) | Add touch-action: manipulation to buttons |
stitch-design-system first to generate design-tokens.css — import it instead of recreating tokensstitch-a11y after for an accessibility passstitch-animate to add CSS-only transitions (zero JS needed for most animations)resources/mobile-template.html — Full mobile HTML boilerplateresources/architecture-checklist.md — Pre-ship checklistscripts/fetch-stitch.sh — Reliable GCS HTML downloader