From cc8c56e42de18cd9a3e0849183d47dd57d499576 Mon Sep 17 00:00:00 2001
From: Srivats Venkataraman <42980667+srivats22@users.noreply.github.com>
Date: Mon, 26 Jan 2026 15:11:48 -0500
Subject: [PATCH] Stitch to flutter component
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is my first Attempt at creating a Skill... wasnt sure how to test it but happy for pointers...
Thanks in advance for reviewing š
---
skills/flutter-components/README.md | 36 +++++++++
skills/flutter-components/SKILL.md | 44 +++++++++++
skills/flutter-components/package.json | 12 +++
.../resources/architecture-checklist.md | 18 +++++
.../resources/component-template.dart | 22 ++++++
.../scripts/fetch-stitch.sh | 30 ++++++++
skills/flutter-components/scripts/validate.js | 77 +++++++++++++++++++
7 files changed, 239 insertions(+)
create mode 100644 skills/flutter-components/README.md
create mode 100644 skills/flutter-components/SKILL.md
create mode 100644 skills/flutter-components/package.json
create mode 100644 skills/flutter-components/resources/architecture-checklist.md
create mode 100644 skills/flutter-components/resources/component-template.dart
create mode 100644 skills/flutter-components/scripts/fetch-stitch.sh
create mode 100644 skills/flutter-components/scripts/validate.js
diff --git a/skills/flutter-components/README.md b/skills/flutter-components/README.md
new file mode 100644
index 0000000..030cba7
--- /dev/null
+++ b/skills/flutter-components/README.md
@@ -0,0 +1,36 @@
+# Stitch to Flutter Skill
+
+## Install
+
+```bash
+npx add-skill google-labs-code/stitch-skills --skill flutter:components --global
+```
+
+## Example Prompt
+
+```text
+Convert my Landing Page screen in my Podcast Stitch Project to a Flutter Page.
+```
+
+## Skill Structure
+
+This repository follows the **Agent Skills** open standard. Each skill is self-contained with its own logic, validation scripts, and design tokens.
+
+```text
+skills/flutter-components/
+āāā SKILL.md ā Core instructions & workflow
+āāā package.json ā Validator dependencies
+āāā scripts/ ā Networking & AST validation
+āāā resources/ ā Style guides & API references
+āāā examples/ ā Gold-standard code samples
+```
+
+## How 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 11-point architecture checklist.
diff --git a/skills/flutter-components/SKILL.md b/skills/flutter-components/SKILL.md
new file mode 100644
index 0000000..4a28f39
--- /dev/null
+++ b/skills/flutter-components/SKILL.md
@@ -0,0 +1,44 @@
+---
+name: flutter:components
+description: Converts Stitch designs into a flutter Screen/Widget using system-level networking and logic-based validation.
+allowed-tools:
+ - "stitch*:*"
+ - "run_command"
+ - "view_file"
+ - "write_to_file"
+ - "read_url_content"
+---
+
+# Stitch to Flutter Components
+
+You are a Flutter frontend engineer focused on transforming designs into clean Flutter & Dart code. You follow a Single-file 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. **High-reliability download**: Internal AI fetch tools can sometimes fail on specific domains.
+ - Use the `run_command` tool to run: `bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/source.html"`.
+ - This script handles the necessary redirects and security handshakes.
+4. **Visual audit**: Check `screenshot.downloadUrl` to confirm the design intent and layout details.
+
+## Architectural rules
+* **Single file**: Generate a single .dart file for the component. This file should always be a `StatefulWidget`.
+* **Logic isolation**: Logic should be encapsulated in its own functions with proper comments within the State class.
+* **Project specific**: Focus on the target project's needs and constraints. Ensure the code is production-ready for the Flutter SDK.
+* **Style mapping**:
+ * Extract the `tailwind.config` from the HTML `
`.
+ * Map these styles to Flutter's `ThemeData` or custom constants.
+ * Use Material 3 components by default.
+
+## Execution steps
+1. **Environment setup**: If `node_modules` is missing in the skill directory, run `npm install` to enable validation tools.
+2. **Data layer**: Create `lib/component.dart` based on the design content.
+3. **Component drafting**: Use `resources/component-template.dart` as a base. Find and replace all instances of `StitchPage` and `StitchPageState` with the actual name of your component.
+4. **Application wiring**: Update the project entry point (like `main.dart`) to render the new component.
+5. **Quality check**:
+ * Run `npm run validate ` for each component.
+ * Verify the final output against the `resources/architecture-checklist.md`.
+
+## Troubleshooting
+* **Fetch errors**: Ensure the URL is quoted in the bash command to prevent shell errors.
+* **Validation errors**: Review the validation report and fix any missing constructors or hardcoded hex colors.
\ No newline at end of file
diff --git a/skills/flutter-components/package.json b/skills/flutter-components/package.json
new file mode 100644
index 0000000..b5e61ff
--- /dev/null
+++ b/skills/flutter-components/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "flutter-components",
+ "version": "1.0.0",
+ "description": "Validation for Flutter components",
+ "type": "module",
+ "scripts": {
+ "validate": "node scripts/validate.js"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+}
diff --git a/skills/flutter-components/resources/architecture-checklist.md b/skills/flutter-components/resources/architecture-checklist.md
new file mode 100644
index 0000000..b6b062e
--- /dev/null
+++ b/skills/flutter-components/resources/architecture-checklist.md
@@ -0,0 +1,18 @@
+# Flutter Component Architecture Checklist
+
+## State Management
+- [ ] Component extends `StatefulWidget`.
+- [ ] Logic is isolated into helper methods within the `State` class.
+- [ ] Proper use of `setState` for UI updates.
+
+## UI & Styling
+- [ ] No hardcoded hex color codes (use `Theme.of(context)` where possible).
+- [ ] Responsive layout using `LayoutBuilder` or `MediaQuery` if needed.
+- [ ] Material 3 design principles followed.
+- [ ] Typography extracted from Design JSON.
+
+## Code Quality
+- [ ] All TODOs resolved.
+- [ ] Proper indentation and formatting.
+- [ ] Public constructor with optional parameters.
+- [ ] No unused imports.
diff --git a/skills/flutter-components/resources/component-template.dart b/skills/flutter-components/resources/component-template.dart
new file mode 100644
index 0000000..f23574e
--- /dev/null
+++ b/skills/flutter-components/resources/component-template.dart
@@ -0,0 +1,22 @@
+import 'package:flutter/material.dart';
+
+class StitchPage extends StatefulWidget {
+ const StitchPage({super.key});
+
+ @override
+ State createState() => _StitchPageState();
+}
+
+class _StitchPageState extends State {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Stitch Component'),
+ ),
+ body: const Center(
+ child: Text('Generate content here'),
+ ),
+ );
+ }
+}
diff --git a/skills/flutter-components/scripts/fetch-stitch.sh b/skills/flutter-components/scripts/fetch-stitch.sh
new file mode 100644
index 0000000..4472144
--- /dev/null
+++ b/skills/flutter-components/scripts/fetch-stitch.sh
@@ -0,0 +1,30 @@
+#!/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 "
+ 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
diff --git a/skills/flutter-components/scripts/validate.js b/skills/flutter-components/scripts/validate.js
new file mode 100644
index 0000000..693e18f
--- /dev/null
+++ b/skills/flutter-components/scripts/validate.js
@@ -0,0 +1,77 @@
+/**
+ * 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 fs from 'node:fs';
+import path from 'node:path';
+
+async function validateFlutterComponent(filePath) {
+ const code = fs.readFileSync(filePath, 'utf-8');
+ const filename = path.basename(filePath);
+
+ console.log(`š Scanning Flutter Component: ${filename}...`);
+
+ let issues = [];
+
+ // 1. Check for StatefulWidget requirement (from SKILL.md)
+ const isStateful = /extends\s+StatefulWidget/.test(code);
+
+ // 2. Check for "Props" (Constructor with parameters)
+ // In Flutter, we look for a constructor that isn't just the default one.
+ const hasConstructorWithParams = /[\w]+\(\{[\s\S]*?\}\)/.test(code);
+
+ // 3. Check for hardcoded hex colors
+ // Matches: 0xFFRRGGBB, 0xRRGGBB, #RRGGBB
+ const hexPattern = /0x([0-9A-Fa-f]{6,8})|#([0-9A-Fa-f]{6})/g;
+ let match;
+ let hexIssues = [];
+ while ((match = hexPattern.exec(code)) !== null) {
+ hexIssues.push(match[0]);
+ }
+
+ console.log(`--- Validation for: ${filename} ---`);
+
+ if (isStateful) {
+ console.log("ā
Component is a StatefulWidget.");
+ } else {
+ console.error("ā MISSING: Must be a StatefulWidget (as per SKILL.md).");
+ issues.push("Not a StatefulWidget");
+ }
+
+ if (hasConstructorWithParams) {
+ console.log("ā
Constructor with parameters found (Props equivalent).");
+ } else {
+ console.error("ā MISSING: Constructor with parameters (Props).");
+ issues.push("Missing constructor parameters");
+ }
+
+ if (hexIssues.length === 0) {
+ console.log("ā
No hardcoded hex values found.");
+ } else {
+ console.error(`ā STYLE: Found ${hexIssues.length} hardcoded hex codes.`);
+ hexIssues.forEach(hex => console.error(` - ${hex}`));
+ issues.push("Hardcoded hex codes");
+ }
+
+ if (issues.length === 0) {
+ console.log("\n⨠FLUTTER COMPONENT VALID.");
+ process.exit(0);
+ } else {
+ console.error("\nš« VALIDATION FAILED.");
+ process.exit(1);
+ }
+}
+
+validateFlutterComponent(process.argv[2]);