
Stitch Prompt Engineer
- 10 installs
- 22 repo stars
- Updated May 28, 2026
- acedergren/agentic-tools
stitch-prompt-engineer is a Claude Code skill that enhances and fixes Google Stitch UI-generation prompts with UI/UX vocabulary and hex-coded design tokens.
About
This skill enhances and fixes prompts used to generate UI in Google Stitch. It adds UI/UX vocabulary, injects design-system tokens, structures page hierarchy, and enforces hex color formatting. A developer uses it to turn a vague Stitch request into a precise prompt that produces consistent output. For multi-page projects it requires a DESIGN.md so tokens stay consistent across screens.
- Enhances Stitch UI-generation prompts with UI/UX vocabulary and hex-coded tokens
- Enforces DESIGN.md consistency for multi-page projects
- Vocabulary-upgrade table turning vague requests into precise UI language
Stitch Prompt Engineer by the numbers
- 10 all-time installs (skills.sh)
- Ranked #1,450 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
stitch-prompt-engineer capabilities & compatibility
- Capabilities
- prompt engineering · ui generation · design tokens
- Use cases
- ui design · web design · copywriting
- Pricing
- Free
What stitch-prompt-engineer says it does
**NEVER output colors as names** ("blue", "green") — always `Descriptive Name (#hexcode) for role`
**NEVER skip DESIGN.md for multi-page projects** — consistency requires explicit tokens across screens
npx skills add https://github.com/acedergren/agentic-tools --skill stitch-prompt-engineerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 10 |
|---|---|
| repo stars | ★ 22 |
| Last updated | May 28, 2026 |
| Repository | acedergren/agentic-tools ↗ |
What it does
Rewrite a Stitch UI-generation prompt with precise UI vocabulary and hex-coded design tokens.
Who is it for?
Rewriting vague Stitch prompts into structured prompts with precise UI vocabulary and design tokens.
Skip if: Extracting a design system (use stitch-design-system) or converting output to code (use stitch-to-react).
When should I use this skill?
When enhancing, polishing, or fixing Stitch UI generation prompts.
What you get
Prompts carry precise UI vocabulary, hex-coded tokens, and page structure for consistent Stitch output.
- Enhanced Stitch prompt
- Design-system block
- Structured page hierarchy
By the numbers
- 6-row assessment checklist
- 8-row vocabulary-upgrade table
Files
Enhance Prompt for Stitch
NEVER
- NEVER output colors as names ("blue", "green") — always
Descriptive Name (#hexcode) for role - NEVER skip DESIGN.md for multi-page projects — consistency requires explicit tokens across screens
- NEVER bundle unrelated enhancements in one pass — layout changes and color changes are separate asks
- NEVER ignore an outdated DESIGN.md — surface the conflict to the user before proceeding
- NEVER enhance without understanding intent — vague prompt often means unclear goal, not just poor wording
- NEVER assume platform — if "web" vs "mobile" isn't clear, ask
Decision: Single Screen vs Multi-Page
Working on multiple screens?
│
├─ YES → Find DESIGN.md in project root
│ ├─ Found → Read it; include design system block as "DESIGN SYSTEM (REQUIRED)"
│ └─ Not found → Create it with `stitch-design-system` skill first
│
└─ NO → Skip DESIGN.md; proceed directly to enhancementAssessment Checklist
Before enhancing, identify what's missing:
| Element | If missing... |
|---|---|
| Platform | Ask or infer from context |
| Page type | Infer ("landing page", "form", etc.) |
| Structure | Add numbered sections |
| Visual style | Add mood adjectives |
| Colors | Add hex-coded design tokens |
| Components | Replace vague nouns with UI vocabulary |
Vocabulary Upgrades
| Vague | Enhanced |
|---|---|
| "menu at the top" | "navigation bar with logo and menu items" |
| "button" | "primary call-to-action button" |
| "list of items" | "card grid layout" or "vertical list with thumbnails" |
| "form" | "form with labeled input fields and submit button" |
| "picture area" | "hero section with full-width image" |
| "modern" | "clean, minimal, with generous whitespace" |
| "professional" | "sophisticated, trustworthy, with subtle shadows" |
| "dark mode" | "dark theme with high-contrast accents on deep backgrounds" |
Output Structure
[One-line description of page purpose and vibe]
**DESIGN SYSTEM (REQUIRED):**
- Platform: [Web/Mobile], [Desktop/Mobile]-first
- Theme: [Light/Dark], [style descriptors]
- Background: [Name] (#hex)
- Primary Accent: [Name] (#hex) for [role]
- Text Primary: [Name] (#hex)
- Buttons: [corner radius], [width behavior]
- Cards: [corner radius], [elevation style]
**Page Structure:**
1. **[Section]:** [description]
2. **[Section]:** [description]For targeted edits (not full-page prompts), include:
- Exact location in UI
- Style spec with hex codes
"Context: This is a targeted edit. Make only this change."
Troubleshooting
| Symptom | Fix |
|---|---|
| Output doesn't match prompt | Add numbered section structure for visual hierarchy |
| Colors apply inconsistently | Create/reference DESIGN.md with explicit hex tokens |
| Layout breaks across screens | Add "mobile-first" or "desktop-first" explicitly |
| Components look generic | Replace "modern" with specific mood adjectives |
| Still poor results after enhance | Return to DESIGN.md and validate consistency first |
Output Format
Return enhanced prompt as text by default. If user requests file output: write next-prompt.md (for use with stitch-loop skill).
import { test } from 'node:test';
import { strict as assert } from 'node:assert';
import { readFileSync } from 'node:fs';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const skillFile = resolve(__dirname, 'SKILL.md');
// ============================================================================
// Spec: Validate stitch-prompt-engineer skill against skill-judge 120-pt rubric
// ============================================================================
// Parse SKILL.md with no imports for bootstrapping
function parseFrontmatter(content) {
const match = content.match(/^---\n([\s\S]*?)\n---\n/);
if (!match) return null;
const frontmatter = match[1];
const fields = {};
for (const line of frontmatter.split('\n')) {
const [key, ...valueParts] = line.split(':');
if (key && valueParts.length > 0) {
fields[key.trim()] = valueParts.join(':').trim().replace(/^"(.*)\"$/, '$1');
}
}
return fields;
}
function countLines(content) {
return content.split('\n').length;
}
function extractSection(content, startPattern) {
// Escape special regex characters in startPattern
const escapedPattern = startPattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// Match header and all content until next ## heading or end of file
// Use \Z instead of $ because $ matches before newlines in multiline mode
const match = content.match(new RegExp(`^${escapedPattern}[\\s\\S]*?(?=^##|\\Z)`, 'm'));
return match ? match[0] : '';
}
// ============================================================================
// STEP 4: RED PHASE TESTS (These fail initially, drive implementation)
// ============================================================================
test('bootstrap: parse SKILL.md frontmatter', () => {
const content = readFileSync(skillFile, 'utf8');
const match = content.match(/^---\n([\s\S]*?)\n---\n/);
assert.ok(match, 'SKILL.md should have YAML frontmatter');
const frontmatter = match[1];
assert.ok(frontmatter.includes('name:'), 'frontmatter should include name field');
assert.ok(frontmatter.includes('description:'), 'frontmatter should include description field');
const nameMatch = frontmatter.match(/name:\s*(.+)/);
assert.ok(nameMatch, 'name field should be present');
const name = nameMatch[1].trim();
assert.equal(name, 'stitch-prompt-engineer', `name should be 'stitch-prompt-engineer', got '${name}'`);
});
// D4: Specification Compliance (15 pts) — Focus on description quality
test('D4.1: Frontmatter has name field', () => {
const content = readFileSync(skillFile, 'utf8');
const fields = parseFrontmatter(content);
assert.ok(fields.name, 'name field must exist');
assert.equal(fields.name, 'stitch-prompt-engineer', 'name must match skill directory');
});
test('D4.2: Frontmatter has description field', () => {
const content = readFileSync(skillFile, 'utf8');
const fields = parseFrontmatter(content);
assert.ok(fields.description, 'description field must exist');
assert.ok(fields.description.length > 50, 'description must be substantive (>50 chars)');
});
test('D4.3: Description answers WHAT (capability keywords)', () => {
const content = readFileSync(skillFile, 'utf8');
const fields = parseFrontmatter(content);
const desc = fields.description.toLowerCase();
// Should mention core capabilities
assert.ok(
desc.includes('prompt') || desc.includes('stitch') || desc.includes('generate'),
'description must mention what skill does (prompt, generate, etc.)'
);
});
test('D4.4: Description answers WHEN (trigger scenarios)', () => {
const content = readFileSync(skillFile, 'utf8');
const fields = parseFrontmatter(content);
const desc = fields.description.toLowerCase();
assert.ok(
desc.includes('when') || desc.includes('designing') || desc.includes('creating'),
'description must explain WHEN to use'
);
});
test('D4.5: Description includes searchable keywords', () => {
const content = readFileSync(skillFile, 'utf8');
const fields = parseFrontmatter(content);
const desc = fields.description;
const keywords = ['stitch', 'prompt', 'design', 'screen', 'generation'];
const found = keywords.filter(kw => desc.toLowerCase().includes(kw));
assert.ok(found.length >= 3, `description should include 3+ domain keywords. Found: ${found.join(', ')}`);
});
// D5: Progressive Disclosure (15 pts) — SKILL.md line count
test('D5.1: SKILL.md is under 500 lines (ideal <300)', () => {
const content = readFileSync(skillFile, 'utf8');
const lines = countLines(content);
assert.ok(lines < 500, `SKILL.md has ${lines} lines, should be <500 (ideal <300)`);
});
test('D5.2: SKILL.md has structured sections', () => {
const content = readFileSync(skillFile, 'utf8');
const sections = [
'## When to Use',
'## Overview',
'## Prerequisites',
'## Prompting Strategy',
'## Output Format',
'## Best Practices'
];
for (const section of sections) {
assert.ok(
content.includes(section),
`SKILL.md should have section: "${section}"`
);
}
});
// D3: Anti-Pattern Quality (15 pts)
test('D3.1: Has anti-patterns section with NEVER list', () => {
const content = readFileSync(skillFile, 'utf8');
assert.ok(content.includes('## Anti-Patterns'), 'must have Anti-Patterns section');
assert.ok(content.includes('NEVER'), 'must have explicit NEVER list');
});
test('D3.2: Anti-patterns are specific with reasoning', () => {
const content = readFileSync(skillFile, 'utf8');
const antiSection = extractSection(content, '## Anti-Patterns to Avoid');
const neverItems = antiSection.split('\n').filter(line => line.includes('NEVER'));
assert.ok(neverItems.length >= 3, `must have 3+ NEVER items, found ${neverItems.length}`);
// Each NEVER should have explanation (contains reason words)
const reasonWords = ['without', 'because', 'always', 'only', 'must', 'ignore'];
for (const item of neverItems.slice(0, 1)) {
const hasReasoning = reasonWords.some(word => item.includes(word));
assert.ok(hasReasoning || item.length > 60, 'NEVER item should include reasoning');
}
});
// D1: Knowledge Delta (20 pts) — No basic tutorial content
test('D1.1: No "What is" tutorial content for basics', () => {
const content = readFileSync(skillFile, 'utf8');
const basicPatterns = [
/What is a prompt/i,
/What is Stitch/i,
/What is prompt engineering/i,
/How to write a prompt/i,
/How to generate text/i
];
for (const pattern of basicPatterns) {
assert.ok(
!pattern.test(content),
`SKILL.md should not explain basic concepts like "${pattern.source}"`
);
}
});
test('D1.2: Has expert decision trees or trade-offs', () => {
const content = readFileSync(skillFile, 'utf8');
assert.ok(
content.includes('specificity') ||
content.includes('accuracy') ||
content.includes('clarity') ||
content.includes('trade-off'),
'should include expert prompt engineering decisions/trade-offs'
);
});
// D2: Mindset + Procedures (15 pts)
test('D2.1: Has thinking frameworks ("ask yourself", "consider", "evaluate")', () => {
const content = readFileSync(skillFile, 'utf8');
const thinkingKeywords = ['ask yourself', 'evaluate', 'consider', 'purpose', 'refine'];
const found = thinkingKeywords.filter(kw => content.toLowerCase().includes(kw));
assert.ok(found.length >= 1, 'should include expert thinking frameworks');
});
test('D2.2: Has domain-specific procedures Claude might not know', () => {
const content = readFileSync(skillFile, 'utf8');
// Prompt engineering skills should have specific prompting procedures
assert.ok(
content.includes('Iterate') || content.includes('Refine') || content.includes('Optimize'),
'should explain how to craft and refine Stitch prompts'
);
});
// D6: Freedom Calibration (15 pts)
test('D6.1: Appropriate freedom level for creative prompt task', () => {
const content = readFileSync(skillFile, 'utf8');
// Prompt engineering is creative: should have HIGH freedom (principles, not rigid steps)
assert.ok(
content.includes('principles') || content.includes('guidance') || content.includes('approach'),
'should emphasize principles and guidance over rigid procedures'
);
});
// D7: Pattern Recognition (10 pts)
test('D7.1: Follows a recognized skill pattern', () => {
const content = readFileSync(skillFile, 'utf8');
// Prompt engineering is typically a Mindset or Philosophy pattern
const hasMindset = content.includes('Mindset');
const hasFramework = content.includes('Framework');
const hasStrategy = content.includes('Strategy');
assert.ok(hasMindset || hasFramework || hasStrategy, 'should follow clear pattern with framework/strategy/mindset');
});
// D8: Practical Usability (15 pts)
test('D8.1: Has actionable step-by-step workflow', () => {
const content = readFileSync(skillFile, 'utf8');
const stepCount = (content.match(/### Step |\d\.\s|^\d+\./gm) || []).length;
assert.ok(stepCount >= 3, `should have 3+ numbered steps/workflow items, found ${stepCount}`);
});
test('D8.2: Has example output format', () => {
const content = readFileSync(skillFile, 'utf8');
assert.ok(
content.includes('```') || content.includes('Example') || content.includes('Output'),
'should show example prompts or output formats'
);
});
test('D8.3: Includes error handling or edge cases', () => {
const content = readFileSync(skillFile, 'utf8');
assert.ok(
content.toLowerCase().includes('error') ||
content.toLowerCase().includes('issue') ||
content.includes('Tips') ||
content.toLowerCase().includes('fallback'),
'should address common prompt failures or edge cases'
);
});
Related skills
FAQ
How should colors be written in a Stitch prompt?
Always as 'Descriptive Name (#hexcode) for role', never as bare color names like 'blue'.
When is a DESIGN.md required?
For multi-page projects, since consistency requires explicit design tokens shared across screens.