
React:Components
- 50.5k installs
- 7.8k repo stars
- Updated July 21, 2026
- google-labs-code/stitch-skills
react:components is an agent skill that converts Stitch design files into modular Vite and React components using Stitch MCP networking.
About
react:components is a frontend engineering skill that transforms Stitch designs into clean, modular Vite and React components.
- Automated namespace discovery and Stitch MCP tool detection
- Metadata fetch via stitch:get_screen followed by conditional local cache check
- High-reliability download scripts that handle Google Cloud Storage edge cases
React:Components by the numbers
- 50,489 all-time installs (skills.sh)
- +57 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #15 of 2,277 Frontend Development skills by installs in the Skillselion catalog
- Security screen: HIGH risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
What react:components says it does
--- name: react:components description: Converts Stitch designs into modular Vite and React components using system-level networking and AST-based validation.
npx skills add https://github.com/google-labs-code/stitch-skills --skill reactcomponentsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 50.5k |
|---|---|
| repo stars | ★ 7.8k |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 21, 2026 |
| Repository | google-labs-code/stitch-skills ↗ |
How do you convert Stitch designs to React components?
Turn Stitch design files into production-ready, modular React and Vite components without manual translation.
Who is it for?
Frontend developers using Google Stitch designs who want automated, validated React component codegen.
Skip if: Projects without Stitch design sources or teams building UI purely by hand without a design-to-code pipeline.
When should I use this skill?
The user has Stitch designs and needs Vite/React components generated from screen metadata.
What you get
Modular Vite and React component files generated from Stitch screen metadata with AST validation.
- Modular React components
- Vite-compatible module files
- AST-validated component source
Files
Stitch to React Components
You are a frontend engineer focused on transforming designs into clean React code. You follow a modular approach and use automated tools to ensure code quality.
Retrieval and networking
1. Namespace discovery: Run list_tools to find the Stitch MCP prefix. Use this prefix (e.g., stitch:) for all subsequent calls. 2. Metadata fetch: Call [prefix]:get_screen to retrieve the design JSON. 3. Check for existing designs: Before downloading, check if .stitch/designs/{page}.html and .stitch/designs/{page}.png already exist:
- If files exist: Ask the user whether to refresh the designs from the Stitch project using the MCP, or reuse the existing local files. Only re-download if the user confirms.
- If files do not exist: Proceed to step 4.
4. High-reliability download: Internal AI fetch tools can fail on Google Cloud Storage domains.
- HTML:
bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" ".stitch/designs/{page}.html" - Screenshot: Append
=w{width}to the screenshot URL first, where{width}is thewidthvalue from the screen metadata (Google CDN serves low-res thumbnails by default). Then run:bash scripts/fetch-stitch.sh "[screenshot.downloadUrl]=w{width}" ".stitch/designs/{page}.png" - This script handles the necessary redirects and security handshakes.
5. Visual audit: Review the downloaded screenshot (.stitch/designs/{page}.png) to confirm design intent and layout details.
Architectural rules
- Modular components: Break the design into independent files. Avoid large, single-file outputs.
- Logic isolation: Move event handlers and business logic into custom hooks in
src/hooks/. - Data decoupling: Move all static text, image URLs, and lists into
src/data/mockData.ts. - Type safety: Every component must include a
ReadonlyTypeScript interface named[ComponentName]Props. - Project specific: Focus on the target project's needs and constraints. Leave Google license headers out of the generated React components.
- Style mapping:
- Extract the
tailwind.configfrom the HTML<head>. - Sync these values with
resources/style-guide.json. - Use theme-mapped Tailwind classes instead of arbitrary hex codes.
Execution steps
1. Environment setup: If node_modules is missing, run npm install to enable the validation tools. 2. Data layer: Create src/data/mockData.ts based on the design content. 3. Component drafting: Use resources/component-template.tsx as a base. Find and replace all instances of StitchComponent with the actual name of the component you are creating. 4. Application wiring: Update the project entry point (like App.tsx) to render the new components. 5. Quality check:
- Run
npm run validate <file_path>for each component. - Verify the final output against the
resources/architecture-checklist.md. - Start the dev server with
npm run devto verify the live result.
Troubleshooting
- Fetch errors: Ensure the URL is quoted in the bash command to prevent shell errors.
- Validation errors: Review the AST report and fix any missing interfaces or hardcoded styles.
import React from 'react';
// Note for Agent: The '@' alias refers to the target project's src directory.
// Ensure src/data/mockData.ts is created before generating this component.
import { cardData } from '../data/mockData';
/**
* Gold Standard: ActivityCard
* This file serves as the definitive reference for the agent.
*/
interface ActivityCardProps {
readonly id: string;
readonly username: string;
readonly action: 'MERGED' | 'COMMIT';
readonly timestamp: string;
readonly avatarUrl: string;
readonly repoName: string;
}
export const ActivityCard: React.FC<ActivityCardProps> = ({
username,
action,
timestamp,
avatarUrl,
repoName,
}) => {
const isMerged = action === 'MERGED';
return (
<div className="flex items-center justify-between gap-4 rounded-lg bg-surface-dark p-4 min-h-14 shadow-sm ring-1 ring-white/10">
<div className="flex items-center gap-4 overflow-hidden">
<div
className="aspect-square h-10 w-10 flex-shrink-0 rounded-full bg-cover bg-center bg-no-repeat"
style={{ backgroundImage: `url(${avatarUrl})` }}
aria-label={`Avatar for ${username}`}
/>
<div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-sm sm:text-base">
<a href="#" className="font-semibold text-primary hover:underline truncate">
{username}
</a>
<span className={`inline-block px-2 py-0.5 text-xs font-semibold rounded-full ${isMerged ? 'bg-purple-500/30 text-purple-300' : 'bg-primary/30 text-primary'
}`}>
{action}
</span>
<span className="text-white/60">in</span>
<a href="#" className="text-primary hover:underline truncate">
{repoName}
</a>
</div>
</div>
<div className="shrink-0">
<p className="text-sm font-normal leading-normal text-white/50">
{timestamp}
</p>
</div>
</div>
);
};
export default ActivityCard;{
"name": "stitch-to-react-pro",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "stitch-to-react-pro",
"version": "1.0.0",
"dependencies": {
"@swc/core": "^1.3.100"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@swc/core": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.8.tgz",
"integrity": "sha512-T8keoJjXaSUoVBCIjgL6wAnhADIb09GOELzKg10CjNg+vLX48P93SME6jTfte9MZIm5m+Il57H3rTSk/0kzDUw==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@swc/counter": "^0.1.3",
"@swc/types": "^0.1.25"
},
"engines": {
"node": ">=10"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/swc"
},
"optionalDependencies": {
"@swc/core-darwin-arm64": "1.15.8",
"@swc/core-darwin-x64": "1.15.8",
"@swc/core-linux-arm-gnueabihf": "1.15.8",
"@swc/core-linux-arm64-gnu": "1.15.8",
"@swc/core-linux-arm64-musl": "1.15.8",
"@swc/core-linux-x64-gnu": "1.15.8",
"@swc/core-linux-x64-musl": "1.15.8",
"@swc/core-win32-arm64-msvc": "1.15.8",
"@swc/core-win32-ia32-msvc": "1.15.8",
"@swc/core-win32-x64-msvc": "1.15.8"
},
"peerDependencies": {
"@swc/helpers": ">=0.5.17"
},
"peerDependenciesMeta": {
"@swc/helpers": {
"optional": true
}
}
},
"node_modules/@swc/core-darwin-arm64": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.8.tgz",
"integrity": "sha512-M9cK5GwyWWRkRGwwCbREuj6r8jKdES/haCZ3Xckgkl8MUQJZA3XB7IXXK1IXRNeLjg6m7cnoMICpXv1v1hlJOg==",
"cpu": [
"arm64"
],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-darwin-x64": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.8.tgz",
"integrity": "sha512-j47DasuOvXl80sKJHSi2X25l44CMc3VDhlJwA7oewC1nV1VsSzwX+KOwE5tLnfORvVJJyeiXgJORNYg4jeIjYQ==",
"cpu": [
"x64"
],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-linux-arm-gnueabihf": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.8.tgz",
"integrity": "sha512-siAzDENu2rUbwr9+fayWa26r5A9fol1iORG53HWxQL1J8ym4k7xt9eME0dMPXlYZDytK5r9sW8zEA10F2U3Xwg==",
"cpu": [
"arm"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-linux-arm64-gnu": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.8.tgz",
"integrity": "sha512-o+1y5u6k2FfPYbTRUPvurwzNt5qd0NTumCTFscCNuBksycloXY16J8L+SMW5QRX59n4Hp9EmFa3vpvNHRVv1+Q==",
"cpu": [
"arm64"
],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-linux-arm64-musl": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.8.tgz",
"integrity": "sha512-koiCqL09EwOP1S2RShCI7NbsQuG6r2brTqUYE7pV7kZm9O17wZ0LSz22m6gVibpwEnw8jI3IE1yYsQTVpluALw==",
"cpu": [
"arm64"
],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-linux-x64-gnu": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.8.tgz",
"integrity": "sha512-4p6lOMU3bC+Vd5ARtKJ/FxpIC5G8v3XLoPEZ5s7mLR8h7411HWC/LmTXDHcrSXRC55zvAVia1eldy6zDLz8iFQ==",
"cpu": [
"x64"
],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-linux-x64-musl": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.8.tgz",
"integrity": "sha512-z3XBnbrZAL+6xDGAhJoN4lOueIxC/8rGrJ9tg+fEaeqLEuAtHSW2QHDHxDwkxZMjuF/pZ6MUTjHjbp8wLbuRLA==",
"cpu": [
"x64"
],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-win32-arm64-msvc": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.8.tgz",
"integrity": "sha512-djQPJ9Rh9vP8GTS/Df3hcc6XP6xnG5c8qsngWId/BLA9oX6C7UzCPAn74BG/wGb9a6j4w3RINuoaieJB3t+7iQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-win32-ia32-msvc": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.8.tgz",
"integrity": "sha512-/wfAgxORg2VBaUoFdytcVBVCgf1isWZIEXB9MZEUty4wwK93M/PxAkjifOho9RN3WrM3inPLabICRCEgdHpKKQ==",
"cpu": [
"ia32"
],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-win32-x64-msvc": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.8.tgz",
"integrity": "sha512-GpMePrh9Sl4d61o4KAHOOv5is5+zt6BEXCOCgs/H0FLGeii7j9bWDE8ExvKFy2GRRZVNR1ugsnzaGWHKM6kuzA==",
"cpu": [
"x64"
],
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/counter": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
"license": "Apache-2.0"
},
"node_modules/@swc/types": {
"version": "0.1.25",
"resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz",
"integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==",
"license": "Apache-2.0",
"dependencies": {
"@swc/counter": "^0.1.3"
}
}
}
}
{
"name": "react-components",
"version": "1.0.0",
"description": "Design-to-code prompt to React components for Stitch MCP",
"type": "module",
"scripts": {
"validate": "node scripts/validate.js",
"fetch": "bash scripts/fetch-stitch.sh"
},
"dependencies": {
"@swc/core": "^1.3.100"
},
"engines": {
"node": ">=18.0.0"
}
}Stitch to React Components Skill
Install
npx skills add google-labs-code/stitch-skills --skill react:components --globalExample Prompt
Convert my Landing Page screen in my Podcast Stitch Project to a React component system.Skill Structure
This repository follows the Agent Skills open standard. Each skill is self-contained with its own logic, validation scripts, and design tokens.
skills/react-components/
├── SKILL.md — Core instructions & workflow
├── package.json — Validator dependencies
├── scripts/ — Networking & AST validation
├── resources/ — Style guides & API references
└── examples/ — Gold-standard code samplesHow it Works
When activated, the agent follows a high-fidelity engineering pipeline:
1. Retrieval: Uses a system-level curl script to bypass TLS/SNI issues on Google Cloud Storage. 2. Mapping: Cross-references Stitch metadata with the local style-guide.json to ensure token consistency. 3. Generation: Scaffolds components using a strict Atomic Design pattern. 4. Validation: Runs an automated AST check using @swc/core to prevent hardcoded hex values or missing interfaces. 5. Audit: Performs a final self-correction check against a 20-point architecture checklist.
Architecture Quality Gate
Structural integrity
- [ ] Logic extracted to custom hooks in
src/hooks/. - [ ] No monolithic files; strictly Atomic/Composite modularity.
- [ ] All static text/URLs moved to
src/data/mockData.ts.
Type safety and syntax
- [ ] Props use
Readonly<T>interfaces. - [ ] File is syntactically valid TypeScript (no red squiggles).
- [ ] Placeholders from templates (e.g.,
StitchComponent) have been replaced with actual names.
Styling and theming
- [ ] Dark mode (
dark:) applied to all color classes. - [ ] No hardcoded hex values; use theme-mapped Tailwind classes.
/**
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
// Use a valid identifier like 'StitchComponent' as the placeholder
interface StitchComponentProps {
readonly children?: React.ReactNode;
readonly className?: string;
}
export const StitchComponent: React.FC<StitchComponentProps> = ({
children,
className = '',
...props
}) => {
return (
<div className={`relative ${className}`} {...props}>
{children}
</div>
);
};
export default StitchComponent;Stitch API reference
This document describes the data structures returned by the Stitch MCP server to ensure accurate component mapping.
Metadata schema
When calling get_screen, the server returns a JSON object with these key properties:
- htmlCode: Contains a
downloadUrl. This is a signed URL that requires a system-level fetch (curl) to handle redirects and security handshakes. - screenshot: Includes a
downloadUrlfor the visual design. Use this to verify layout intent that might not be obvious in the raw HTML. - deviceType: Usually set to
DESKTOP. All generated components should prioritize the corresponding viewport (2560px width) as the base layout.
Technical mapping rules
1. Element tracking: Preserve data-stitch-id attributes as comments in the TSX to allow for future design synchronization. 2. Asset handling: Treat background images in the HTML as dynamic data. Extract the URLs into mockData.ts rather than hardcoding them into the component styles. 3. Style extraction: The HTML <head> contains a localized tailwind.config. This config must be merged with the local project theme to ensure colors like primary and background-dark render correctly.
{
"theme": {
"colors": {
"primary": "#19e66f",
"background": {
"light": "#f6f8f7",
"dark": "#112118",
"elevated": "#1A1A1A"
},
"accent": {
"purple": "#8A2BE2",
"lavender": "#D0A9F5"
}
},
"typography": {
"display": [
"Space Grotesk",
"sans-serif"
],
"icons": "Material Symbols Outlined"
},
"spacing": {
"header-h": "72px",
"container-max": "960px"
}
}
}#!/bin/bash
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
URL=$1
OUTPUT=$2
if [ -z "$URL" ] || [ -z "$OUTPUT" ]; then
echo "Usage: $0 <url> <output_path>"
exit 1
fi
echo "Initiating high-reliability fetch for Stitch HTML..."
curl -L -f -sS --connect-timeout 10 --compressed "$URL" -o "$OUTPUT"
if [ $? -eq 0 ]; then
echo "✅ Successfully retrieved HTML at: $OUTPUT"
exit 0
else
echo "❌ Error: Failed to retrieve content. Check TLS/SNI or URL expiration."
exit 1
fi
/**
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import swc from '@swc/core';
import fs from 'node:fs';
import path from 'node:path';
const HEX_COLOR_REGEX = /#[0-9A-Fa-f]{6}/;
async function validateComponent(filePath) {
const code = fs.readFileSync(filePath, 'utf-8');
const filename = path.basename(filePath);
try {
const ast = await swc.parse(code, { syntax: "typescript", tsx: true });
let hasInterface = false;
let tailwindIssues = [];
console.log("🔍 Scanning AST...");
const walk = (node) => {
if (!node) return;
if (node.type === 'TsInterfaceDeclaration' && node.id.value.endsWith('Props')) hasInterface = true;
if (node.type === 'JSXAttribute' && (node.name?.value === 'className' || node.name?.name === 'className')) {
if (node.value?.value && HEX_COLOR_REGEX.test(node.value.value)) tailwindIssues.push(node.value.value);
}
for (const key in node) { if (node[key] && typeof node[key] === 'object') walk(node[key]); }
};
walk(ast);
console.log(`--- Validation for: ${filename} ---`);
if (hasInterface) {
console.log("✅ Props declaration found.");
} else {
console.error("❌ MISSING: Props interface (must end in 'Props').");
}
if (tailwindIssues.length === 0) {
console.log("✅ No hardcoded hex values found.");
} else {
console.error(`❌ STYLE: Found ${tailwindIssues.length} hardcoded hex codes.`);
tailwindIssues.forEach(hex => console.error(` - ${hex}`));
}
if (hasInterface && tailwindIssues.length === 0) {
console.log("\n✨ COMPONENT VALID.");
process.exit(0);
} else {
console.error("\n🚫 VALIDATION FAILED.");
process.exit(1);
}
} catch (err) {
console.error("❌ PARSE ERROR:", err.message);
process.exit(1);
}
}
validateComponent(process.argv[2]);
Related skills
Forks & variants (1)
React:Components has 1 known copy in the catalog totaling 54 installs. They canonicalize to this original listing.
- leonxlnx - 54 installs
How it compares
Use react:components when the source of truth is Stitch design JSON; use hand-authored component skills when no Stitch MCP pipeline exists.
FAQ
What tools does react:components use?
react:components discovers the Stitch MCP prefix, calls get_screen for design JSON, and uses Bash, Read, Write alongside stitch*:* tools to emit validated Vite and React components.
How does react:components ensure code quality?
react:components applies AST-based validation after codegen so generated React modules follow project structure and remain composable.
Is React:Components safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.