diff --git a/README.md b/README.md index fedfd8a..47ac64c 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,13 @@ Converts Stitch screens to React component systems with automated validation and npx skills add google-labs-code/stitch-skills --skill react:components --global ``` +### vue-components +Converts Stitch screens to Vue component systems with automated validation and design token consistency. + +```bash +npx skills add google-labs-code/stitch-skills --skill vue:components --global +``` + ### remotion Generates walkthrough videos from Stitch projects using Remotion with smooth transitions, zooming, and text overlays to showcase app screens professionally. diff --git a/skills/vue-components/README.md b/skills/vue-components/README.md new file mode 100644 index 0000000..33da662 --- /dev/null +++ b/skills/vue-components/README.md @@ -0,0 +1,44 @@ +# vue:components + +Converts Stitch designs into modular **Vue 3** Single File Components using the Composition API (` + + + + + + + + + {{ props.username }} + + + + {{ props.action }} + + + in + + + {{ props.repoName }} + + + + + + + {{ props.timestamp }} + + + + diff --git a/skills/vue-components/package.json b/skills/vue-components/package.json new file mode 100644 index 0000000..359477d --- /dev/null +++ b/skills/vue-components/package.json @@ -0,0 +1,16 @@ +{ + "name": "vue-components", + "version": "1.0.0", + "description": "Design-to-code prompt to Vue 3 Composition API components for Stitch MCP", + "type": "module", + "scripts": { + "validate": "node scripts/validate.js", + "fetch": "bash scripts/fetch-stitch.sh" + }, + "dependencies": { + "@vue/compiler-sfc": "^3.4.0" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/skills/vue-components/resources/architecture-checklist.md b/skills/vue-components/resources/architecture-checklist.md new file mode 100644 index 0000000..0a2411b --- /dev/null +++ b/skills/vue-components/resources/architecture-checklist.md @@ -0,0 +1,21 @@ +# Architecture Quality Gate + +### Structural integrity +- [ ] Logic extracted to composables in `src/composables/` (prefixed with `use`). +- [ ] No monolithic files; strictly Atomic/Composite modularity. +- [ ] All static text/URLs moved to `src/data/mockData.ts`. + +### Type safety and syntax +- [ ] Props declared with `defineProps()` (typed generic, not runtime object). +- [ ] `withDefaults` used when any prop has a default value. +- [ ] Emits declared with `defineEmits<{ ... }>()` if the component emits events. +- [ ] File is syntactically valid Vue SFC (no parse errors). +- [ ] Placeholders from templates (e.g., `StitchComponent`) have been replaced with actual names. + +### Reactivity +- [ ] Props accessed via `props.x`, not destructured directly. +- [ ] Derived state uses `computed()`, not local `ref` copies of props. + +### Styling and theming +- [ ] Dark mode (`dark:`) applied to all color classes. +- [ ] No hardcoded hex values in template — use theme-mapped Tailwind classes. diff --git a/skills/vue-components/resources/component-template.vue b/skills/vue-components/resources/component-template.vue new file mode 100644 index 0000000..b28178c --- /dev/null +++ b/skills/vue-components/resources/component-template.vue @@ -0,0 +1,18 @@ + + + + + + + diff --git a/skills/vue-components/resources/style-guide.json b/skills/vue-components/resources/style-guide.json new file mode 100644 index 0000000..4cc0a52 --- /dev/null +++ b/skills/vue-components/resources/style-guide.json @@ -0,0 +1,27 @@ +{ + "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" + } + } +} diff --git a/skills/vue-components/scripts/fetch-stitch.sh b/skills/vue-components/scripts/fetch-stitch.sh new file mode 100644 index 0000000..4472144 --- /dev/null +++ b/skills/vue-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/vue-components/scripts/validate.js b/skills/vue-components/scripts/validate.js new file mode 100644 index 0000000..07abcb3 --- /dev/null +++ b/skills/vue-components/scripts/validate.js @@ -0,0 +1,69 @@ +/** + * Vue 3 SFC Validator + * Checks that a .vue component follows the skill's architectural rules: + * - Has a typed defineProps() declaration + * - Contains no hardcoded hex color values in the template + */ + +import { parse } from '@vue/compiler-sfc' +import fs from 'node:fs' +import path from 'node:path' + +const HEX_COLOR_REGEX = /#[0-9A-Fa-f]{6}/g + +async function validateComponent(filePath) { + if (!filePath) { + console.error('Usage: node scripts/validate.js ') + process.exit(1) + } + + const source = fs.readFileSync(filePath, 'utf-8') + const filename = path.basename(filePath) + + const { descriptor, errors } = parse(source, { filename }) + + if (errors.length > 0) { + console.error('❌ PARSE ERROR:', errors[0].message) + process.exit(1) + } + + const scriptContent = + descriptor.scriptSetup?.content ?? descriptor.script?.content ?? '' + const templateContent = descriptor.template?.content ?? '' + + // Check for typed defineProps + const hasDefineProps = /defineProps\s* m[0], + ) + + console.log('🔍 Scanning Vue SFC...') + console.log(`--- Validation for: ${filename} ---`) + + if (hasDefineProps) { + console.log('✅ defineProps() declaration found.') + } else { + console.error( + "❌ MISSING: Typed defineProps (use defineProps() pattern).", + ) + } + + if (hexMatches.length === 0) { + console.log('✅ No hardcoded hex values found in template.') + } else { + console.error(`❌ STYLE: Found ${hexMatches.length} hardcoded hex codes.`) + hexMatches.forEach((hex) => console.error(` - ${hex}`)) + } + + if (hasDefineProps && hexMatches.length === 0) { + console.log('\n✨ COMPONENT VALID.') + process.exit(0) + } else { + console.error('\n🚫 VALIDATION FAILED.') + process.exit(1) + } +} + +validateComponent(process.argv[2])
+ {{ props.timestamp }} +