stitch-react-components について
Stitchのデザイン、ローカルHTML、URLを、Viteや通常のReactプロジェクト向けのモジュール化されたコンポーネントに変換するスキルです。デザイントークンの抽出、テーマ設定、構成を案内し、Next.jsは対象外です。
主な機能
- 01HTMLデザインをReactコンポーネントに変換
- 02Stitch、ローカルファイル、URLに対応
- 03デザイントークン抽出とダークモード対応
- 04コンポーネント、データ、共有型を整理
- 05HTMLダウンロード用スクリプトを提供
活用シーン
- 01ViteのReactアプリでStitch画面を再構築
- 02ローカルHTMLデザインをReactコンポーネントに変換
- 03ウェブページのデザインを通常のReactプロジェクトに移植
MCP 対応
Stitch画面を入力にする場合、Stitch MCPで関連ツールを探し、画面のメタデータを取得します。それ以外のHTMLソースではStitch MCPは不要です。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ gabelul/ stitch-kit --skill stitch-react-componentsインストール後、Claude Code で/stitch-react-componentsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/tailwind-to-react.mdresources/architecture-checklist.mdcomponent-template.tsxscripts/fetch-stitch.sh詳細
Stitch → Vite / React コンポーネント
制約: ユーザーが「Stitch」とReact(Vite、CRA、またはNext.jsを使わない「React app」)に明示的に言及した場合のみ、このスキルを使用してください。
Stitchのモバイル/デスクトップデザインを、Vite + TypeScriptを使用したクリーンでモジュール化されたReactコンポーネントに変換するフロントエンドエンジニアです。このスキルの対象は通常のReactアプリであり、Next.js App Routerは対象外です。Next.jsの場合は、代わりにstitch-nextjs-componentsを使用してください。
このスキルとNext.jsの使い分け
| シナリオ | 使用するもの |
|---|---|
| ユーザーが「React app」「Vite」「CRA」と言う | stitch-react-components |
| ユーザーが「Next.js」「App Router」「SSR」と言う | stitch-nextjs-components |
| ユーザーが後からshadcn/uiコンポーネントの追加を希望する | stitch-react-components → 続けてstitch-shadcn-ui |
| ユーザーがサーバーサイドレンダリングまたはファイルベースのルーティングを希望する | stitch-nextjs-components |
前提条件
HTMLソース。以下のいずれかを使用できます。
- Stitchの画面 — Stitch MCPへのアクセスと、生成済みの画面が必要です
- ローカルHTMLファイル — Stitchアカウントは不要です
- URL — Stitchアカウントは不要です
また、以下が必要です。
- Node.js + npm/pnpm
- Vite + Reactプロジェクトの初期化:
npm create vite@latest my-app -- --template react-ts
ステップ1:ソースを解決する
以降の処理では、すべて1つのファイルtemp/source.htmlを読み込みます。ユーザーから渡されたものに合う方法でHTMLをそこに取得してから、ステップ2に進んでください。マークアップの取得元にかかわらず、このスキルの残りの手順は同じです。
Stitchの画面から取得する場合:
- 名前空間を確認する —
list_toolsを使ってStitch MCPのプレフィックスを見つけます - メタデータを取得する — 数値の
projectIdとscreenIdを指定して[prefix]:get_screenを呼び出します - HTMLをダウンロードする — GCS URLには、信頼性の高いダウンローダーが必要です。
bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/source.html" - 見た目を確認する — 書き換える前に
screenshot.downloadUrlを確認してください。フル解像度で取得するには、そのURLに=s0を追加します。URLをそのまま使うと、APIが報告するwidth/heightに関係なく、512pxのサムネイルが返されます。
ローカルHTMLファイルから取得する場合:
mkdir -p temp && cp "path/to/design.html" temp/source.html
URLから取得する場合:
bash scripts/fetch-stitch.sh "https://example.com/page" "temp/source.html"
スクリプトの名前にかかわらず、これは汎用の堅牢なダウンローダーです。リダイレクトに従い、一時的なエラーを再試行し、gzipを処理し、結果が空の場合は明確に失敗します。URLがStitchを指しているかどうかは問いません。
スクリーンショットから取得する場合: アップロードする方法はありません。Stitch MCP APIには画像アップロード用のツールがありません。stitch-mcp-generate-screen-from-textを使ってテキストプロンプトからデザインを再現するか、HTMLを手動で記述して上記のローカルファイルの方法を使ってください。
APIキーが必要なのはStitch経由の場合のみです。ローカルファイルまたはURLの変換には、Googleアカウントは必要ありません。
ステップ2:プロジェクト構成
src/
├── components/ ← One file per component
│ └── [Name].tsx
├── data/
│ └── mockData.ts ← Static content (never in components)
├── theme/
│ ├── tokens.ts ← Design token constants
│ └── useTheme.ts ← Dark mode hook
├── types/
│ └── index.ts ← Shared TypeScript types
├── App.tsx ← Root component
└── main.tsx ← Entry point
ステップ3:デザイントークンを抽出する
HTMLに実際に含まれている情報をもとに、以下の順序でトークンを特定します。
<head>内のインラインtailwind.config(Stitchが出力するもの)— 存在する場合はそのまま使用します。- CSSカスタムプロパティ(
:root { --color-primary: ... })— 手書きHTMLやテンプレートHTMLでよく使われます。 - リンクされた、またはインラインのスタイルシート — 宣言された色、フォントファミリー、角丸、間隔を解析します。
- 最後の手段 — マークアップ内で最も頻繁に使われる計算済みの値(背景の基調色、テキスト色、アクセントカラー、見出し/本文のフォント、角丸)からトークンを導き出し、推定した内容をユーザーに伝えて修正できるようにします。
URL経由の方法では、単一のHTMLレスポンスだけをダウンロードします。外部リンクされたスタイルシートは取得できないことがあります。上記の方法でトークンを特定できない場合は、配色を作り出すのではなく、その旨を伝えてください。
// src/theme/tokens.ts
export const lightTokens = {
background: '#FFFFFF',
surface: '#F4F4F5',
primary: '#6366F1',
primaryFg: '#FFFFFF',
text: '#09090B',
textMuted: '#71717A',
border: '#E4E4E7',
} as const
export const darkTokens = {
background: '#09090B',
surface: '#18181B',
primary: '#818CF8',
primaryFg: '#09090B',
text: '#FAFAFA',
textMuted: '#A1A1AA',
border: '#27272A',
} as const
export type ThemeTokens = typeof lightTokens
// src/theme/useTheme.ts
import { useEffect, useState } from 'react'
import { lightTokens, darkTokens, type ThemeTokens } from './tokens'
/**
* Returns current theme tokens based on system color scheme.
* Listens for system-level dark/light mode changes.
*/
export function useTheme(): ThemeTokens {
const [isDark, setIsDark] = useState(
() => window.matchMedia('(prefers-color-scheme: dark)').matches
)
useEffect(() => {
const mq = window.matchMedia('(prefers-color-scheme: dark)')
const handler = (e: MediaQueryListEvent) => setIsDark(e.matches)
mq.addEventListener('change', handler)
return () => mq.removeEventListener('change', handler)
}, [])
return isDark ? darkTokens : lightTokens
}
ステップ4:コンポーネント変換ルール
レイアウトのマッピング
| HTML/CSS | → React / Tailwind |
|---|---|
display:flex; flex-direction:column | <div className="flex flex-col gap-4"> |
display:flex; flex-direction:row | <div className="flex items-center gap-2"> |
justify-content:space-between | <div className="flex justify-between"> |
display:grid; grid-template-columns:1fr 1fr | <div className="grid grid-cols-2 gap-4"> |
overflow-y:scroll | <div className="overflow-y-auto"> |
| 長いリスト | items.map(item => <Card key={item.id} {...item} />) |
<img> | <img src="..." alt="..." className="object-cover"> |
Tailwind クラスのマッピング
カスタムトークンを参照しない場合は、ソース HTML の Tailwind クラスを JSX で直接使用します。カスタムトークンは CSS 変数にマッピングします。
// Source HTML: bg-primary → CSS variable → Tailwind arbitrary value
// OR: use inline style with token value
// Option A — Tailwind arbitrary value (if custom tokens in tailwind.config)
<div className="bg-[--color-primary] text-[--color-primaryFg]">
// Option B — inline style with useTheme()
const theme = useTheme()
<div style={{ backgroundColor: theme.primary, color: theme.primaryFg }}>
コンポーネントのテンプレート
// src/components/StitchComponent.tsx
/**
* Props for StitchComponent — all data via props, never fetched inside.
*/
interface StitchComponentProps {
/** Primary heading text */
title: string
/** Supporting description — optional */
description?: string
/** Primary action callback */
onAction?: () => void
}
/**
* StitchComponent — [describe purpose in one sentence]
*/
export function StitchComponent({
title,
description,
onAction,
}: Readonly<StitchComponentProps>) {
const theme = useTheme()
return (
<div
className="rounded-xl border p-4 gap-2 flex flex-col"
style={{
backgroundColor: theme.surface,
borderColor: theme.border,
}}
>
<h3 className="text-base font-semibold" style={{ color: theme.text }}>
{title}
</h3>
{description ? (
<p className="text-sm" style={{ color: theme.textMuted }}>
{description}
</p>
) : null}
{onAction ? (
<button
onClick={onAction}
className="rounded-lg px-4 py-2 text-sm font-medium transition-opacity hover:opacity-90"
style={{ backgroundColor: theme.primary, color: theme.primaryFg }}
type="button"
>
Action
</button>
) : null}
</div>
)
}
ステップ 5:アーキテクチャのルール
- ファイルごとにコンポーネントを 1 つ — 単一ファイルにコードを詰め込まない
- 静的データは
src/data/mockData.tsに配置 — JSX にハードコードしない - 共有型は
src/types/index.tsに配置 - すべてのコンポーネントに
Readonly<ComponentNameProps>インターフェースを用意する - 16 進数カラーをハードコードしない —
useTheme()または CSS 変数を使用する any型を使用しない
ステップ 6:shadcn/ui との統合
デザインを基本的な React コンポーネントに変換した後、shadcn/ui を重ねて適用できます。
npx shadcn@latest init # Set up shadcn in your Vite project
npx shadcn@latest add button card input dialog
次に、stitch-shadcn-ui スキルを使用して、デザイントークンを維持しながら生の HTML 要素を shadcn コンポーネントに置き換えます。
トラブルシューティング
| 問題 | 解決方法 |
|---|---|
| Tailwind クラスが適用されない | tailwind.config.js の content に ./src/**/*.{ts,tsx} が含まれているか確認します |
| ダークモードが切り替わらない | useTheme() がコンポーネントのレベルで呼び出されており、外部に引き上げられていないことを確認します |
| 画像が表示されない | 明示的に width と height を追加するか、className="w-full h-auto" を使用します |
| props の型エラー | Readonly<> でラップされていること、および必須の props がすべて指定されていることを確認します |
参考資料
resources/component-template.tsx— コンポーネントのひな形resources/architecture-checklist.md— リリース前のチェックリストreferences/tailwind-to-react.md— トークンとクラスのマッピングガイド(ソース HTML → React/Tailwind)scripts/fetch-stitch.sh— GCS HTML を確実にダウンロードするスクリプトstitch-shadcn-ui— 基本変換後に shadcn/ui コンポーネントを追加するdocs/tailwind-reference.md— Tailwind ユーティリティクラスの検索