stitch-forge 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/.claude/skills/forge-build/SKILL.md +79 -0
  2. package/.claude/skills/forge-design/SKILL.md +64 -0
  3. package/.claude/skills/forge-discover/SKILL.md +139 -0
  4. package/.claude/skills/forge-generate/SKILL.md +77 -0
  5. package/.claude/skills/forge-preview/SKILL.md +26 -0
  6. package/.claude/skills/forge-research/SKILL.md +42 -0
  7. package/.claude/skills/forge-sync/SKILL.md +45 -0
  8. package/DESIGN.md +113 -0
  9. package/LICENSE +21 -0
  10. package/README.es.md +242 -0
  11. package/README.md +242 -0
  12. package/dist/adapters/astro.d.ts +8 -0
  13. package/dist/adapters/astro.js +24 -0
  14. package/dist/adapters/astro.js.map +1 -0
  15. package/dist/adapters/index.d.ts +3 -0
  16. package/dist/adapters/index.js +9 -0
  17. package/dist/adapters/index.js.map +1 -0
  18. package/dist/adapters/nextjs.d.ts +7 -0
  19. package/dist/adapters/nextjs.js +136 -0
  20. package/dist/adapters/nextjs.js.map +1 -0
  21. package/dist/adapters/static.d.ts +7 -0
  22. package/dist/adapters/static.js +43 -0
  23. package/dist/adapters/static.js.map +1 -0
  24. package/dist/adapters/types.d.ts +22 -0
  25. package/dist/adapters/types.js +6 -0
  26. package/dist/adapters/types.js.map +1 -0
  27. package/dist/commands/build.d.ts +7 -0
  28. package/dist/commands/build.js +98 -0
  29. package/dist/commands/build.js.map +1 -0
  30. package/dist/commands/design.d.ts +3 -0
  31. package/dist/commands/design.js +39 -0
  32. package/dist/commands/design.js.map +1 -0
  33. package/dist/commands/discover.d.ts +9 -0
  34. package/dist/commands/discover.js +91 -0
  35. package/dist/commands/discover.js.map +1 -0
  36. package/dist/commands/generate.d.ts +7 -0
  37. package/dist/commands/generate.js +105 -0
  38. package/dist/commands/generate.js.map +1 -0
  39. package/dist/commands/init.d.ts +1 -0
  40. package/dist/commands/init.js +99 -0
  41. package/dist/commands/init.js.map +1 -0
  42. package/dist/commands/preview.d.ts +5 -0
  43. package/dist/commands/preview.js +41 -0
  44. package/dist/commands/preview.js.map +1 -0
  45. package/dist/commands/research.d.ts +1 -0
  46. package/dist/commands/research.js +38 -0
  47. package/dist/commands/research.js.map +1 -0
  48. package/dist/commands/sync.d.ts +1 -0
  49. package/dist/commands/sync.js +53 -0
  50. package/dist/commands/sync.js.map +1 -0
  51. package/dist/commands/workflow.d.ts +1 -0
  52. package/dist/commands/workflow.js +38 -0
  53. package/dist/commands/workflow.js.map +1 -0
  54. package/dist/index.d.ts +2 -0
  55. package/dist/index.js +113 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/mcp/auth.d.ts +15 -0
  58. package/dist/mcp/auth.js +56 -0
  59. package/dist/mcp/auth.js.map +1 -0
  60. package/dist/mcp/client.d.ts +65 -0
  61. package/dist/mcp/client.js +302 -0
  62. package/dist/mcp/client.js.map +1 -0
  63. package/dist/mcp/tools.d.ts +26 -0
  64. package/dist/mcp/tools.js +46 -0
  65. package/dist/mcp/tools.js.map +1 -0
  66. package/dist/research/business-researcher.d.ts +41 -0
  67. package/dist/research/business-researcher.js +888 -0
  68. package/dist/research/business-researcher.js.map +1 -0
  69. package/dist/research/crawler.d.ts +11 -0
  70. package/dist/research/crawler.js +56 -0
  71. package/dist/research/crawler.js.map +1 -0
  72. package/dist/research/design-synthesizer.d.ts +46 -0
  73. package/dist/research/design-synthesizer.js +628 -0
  74. package/dist/research/design-synthesizer.js.map +1 -0
  75. package/dist/research/differ.d.ts +19 -0
  76. package/dist/research/differ.js +58 -0
  77. package/dist/research/differ.js.map +1 -0
  78. package/dist/research/known-state.json +68 -0
  79. package/dist/research/research-cache.d.ts +6 -0
  80. package/dist/research/research-cache.js +62 -0
  81. package/dist/research/research-cache.js.map +1 -0
  82. package/dist/research/types.d.ts +98 -0
  83. package/dist/research/types.js +6 -0
  84. package/dist/research/types.js.map +1 -0
  85. package/dist/research/updater.d.ts +5 -0
  86. package/dist/research/updater.js +43 -0
  87. package/dist/research/updater.js.map +1 -0
  88. package/dist/templates/design-md.d.ts +52 -0
  89. package/dist/templates/design-md.js +315 -0
  90. package/dist/templates/design-md.js.map +1 -0
  91. package/dist/templates/prompts.d.ts +31 -0
  92. package/dist/templates/prompts.js +39 -0
  93. package/dist/templates/prompts.js.map +1 -0
  94. package/dist/templates/workflows.d.ts +9 -0
  95. package/dist/templates/workflows.js +21 -0
  96. package/dist/templates/workflows.js.map +1 -0
  97. package/dist/tui/App.d.ts +1 -0
  98. package/dist/tui/App.js +87 -0
  99. package/dist/tui/App.js.map +1 -0
  100. package/dist/tui/Dashboard.d.ts +5 -0
  101. package/dist/tui/Dashboard.js +23 -0
  102. package/dist/tui/Dashboard.js.map +1 -0
  103. package/dist/tui/DesignEditor.d.ts +6 -0
  104. package/dist/tui/DesignEditor.js +76 -0
  105. package/dist/tui/DesignEditor.js.map +1 -0
  106. package/dist/tui/PromptBuilder.d.ts +5 -0
  107. package/dist/tui/PromptBuilder.js +102 -0
  108. package/dist/tui/PromptBuilder.js.map +1 -0
  109. package/dist/tui/components/QuotaMeter.d.ts +8 -0
  110. package/dist/tui/components/QuotaMeter.js +10 -0
  111. package/dist/tui/components/QuotaMeter.js.map +1 -0
  112. package/dist/tui/components/ScreenCard.d.ts +7 -0
  113. package/dist/tui/components/ScreenCard.js +6 -0
  114. package/dist/tui/components/ScreenCard.js.map +1 -0
  115. package/dist/tui/components/Spinner.d.ts +5 -0
  116. package/dist/tui/components/Spinner.js +7 -0
  117. package/dist/tui/components/Spinner.js.map +1 -0
  118. package/dist/tui/components/StatusBar.d.ts +7 -0
  119. package/dist/tui/components/StatusBar.js +6 -0
  120. package/dist/tui/components/StatusBar.js.map +1 -0
  121. package/dist/utils/config.d.ts +26 -0
  122. package/dist/utils/config.js +66 -0
  123. package/dist/utils/config.js.map +1 -0
  124. package/dist/utils/design-validator.d.ts +44 -0
  125. package/dist/utils/design-validator.js +396 -0
  126. package/dist/utils/design-validator.js.map +1 -0
  127. package/dist/utils/logger.d.ts +8 -0
  128. package/dist/utils/logger.js +10 -0
  129. package/dist/utils/logger.js.map +1 -0
  130. package/dist/utils/output-validator.d.ts +18 -0
  131. package/dist/utils/output-validator.js +194 -0
  132. package/dist/utils/output-validator.js.map +1 -0
  133. package/dist/utils/preview.d.ts +4 -0
  134. package/dist/utils/preview.js +49 -0
  135. package/dist/utils/preview.js.map +1 -0
  136. package/dist/utils/prompt-enhancer.d.ts +21 -0
  137. package/dist/utils/prompt-enhancer.js +104 -0
  138. package/dist/utils/prompt-enhancer.js.map +1 -0
  139. package/dist/utils/quota.d.ts +18 -0
  140. package/dist/utils/quota.js +49 -0
  141. package/dist/utils/quota.js.map +1 -0
  142. package/dist/utils/validators.d.ts +125 -0
  143. package/dist/utils/validators.js +110 -0
  144. package/dist/utils/validators.js.map +1 -0
  145. package/package.json +77 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-validator.js","sourceRoot":"","sources":["../../src/utils/output-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function openInBrowser(filePath: string): Promise<void>;
2
+ export declare function listScreenFiles(): string[];
3
+ export declare function resolveScreenPath(screenName: string): string | null;
4
+ export declare function openAllScreens(): Promise<void>;
@@ -0,0 +1,49 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { readdirSync, existsSync } from 'node:fs';
3
+ import { resolve, join } from 'node:path';
4
+ import { log } from './logger.js';
5
+ export function openInBrowser(filePath) {
6
+ const absPath = resolve(filePath);
7
+ const cmd = process.platform === 'darwin' ? 'open'
8
+ : process.platform === 'win32' ? 'start'
9
+ : 'xdg-open';
10
+ return new Promise((res, rej) => {
11
+ execFile(cmd, [absPath], (err) => {
12
+ if (err) {
13
+ log.error(`Could not open browser. Open manually: ${absPath}`);
14
+ rej(err);
15
+ }
16
+ else {
17
+ res();
18
+ }
19
+ });
20
+ });
21
+ }
22
+ export function listScreenFiles() {
23
+ const dir = 'screens';
24
+ if (!existsSync(dir))
25
+ return [];
26
+ return readdirSync(dir)
27
+ .filter(f => f.endsWith('.html'))
28
+ .map(f => f.replace('.html', ''))
29
+ .sort();
30
+ }
31
+ export function resolveScreenPath(screenName) {
32
+ const exact = join('screens', `${screenName}.html`);
33
+ if (existsSync(exact))
34
+ return resolve(exact);
35
+ const files = listScreenFiles();
36
+ const match = files.find(f => f.toLowerCase() === screenName.toLowerCase());
37
+ if (match)
38
+ return resolve(join('screens', `${match}.html`));
39
+ return null;
40
+ }
41
+ export async function openAllScreens() {
42
+ const files = listScreenFiles();
43
+ for (const file of files) {
44
+ const path = resolve(join('screens', `${file}.html`));
45
+ await openInBrowser(path);
46
+ await new Promise(r => setTimeout(r, 200));
47
+ }
48
+ }
49
+ //# sourceMappingURL=preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../src/utils/preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM;QAChD,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO;YACxC,CAAC,CAAC,UAAU,CAAC;IAEf,OAAO,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9B,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;YAC/B,IAAI,GAAG,EAAE,CAAC;gBACR,GAAG,CAAC,KAAK,CAAC,0CAA0C,OAAO,EAAE,CAAC,CAAC;gBAC/D,GAAG,CAAC,GAAG,CAAC,CAAC;YACX,CAAC;iBAAM,CAAC;gBACN,GAAG,EAAE,CAAC;YACR,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,SAAS,CAAC;IACtB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,OAAO,WAAW,CAAC,GAAG,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;SAChC,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,UAAU,OAAO,CAAC,CAAC;IACpD,IAAI,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;IAE7C,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5E,IAAI,KAAK;QAAE,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC;IAE5D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC;QACtD,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC"}
@@ -0,0 +1,21 @@
1
+ export interface EnhancementResult {
2
+ original: string;
3
+ enhanced: string;
4
+ suggestions: string[];
5
+ slopRiskScore: number;
6
+ businessAlignmentIssues: string[];
7
+ }
8
+ /**
9
+ * Enhance a user prompt before sending to Stitch.
10
+ * Adds design context, replaces generic terms, and scores slop risk.
11
+ */
12
+ export declare function enhancePrompt(prompt: string): EnhancementResult;
13
+ /**
14
+ * Calculate AI slop risk score (0-10).
15
+ * Higher score = more likely to get generic AI output.
16
+ */
17
+ export declare function calculateSlopRisk(prompt: string): number;
18
+ /**
19
+ * Get human-readable risk level from score.
20
+ */
21
+ export declare function getSlopRiskLevel(score: number): 'low' | 'medium' | 'high';
@@ -0,0 +1,104 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ /**
3
+ * Enhance a user prompt before sending to Stitch.
4
+ * Adds design context, replaces generic terms, and scores slop risk.
5
+ */
6
+ export function enhancePrompt(prompt) {
7
+ const suggestions = [];
8
+ let enhanced = prompt;
9
+ // 1. Add DESIGN.md reference if available
10
+ if (existsSync('DESIGN.md')) {
11
+ if (!enhanced.toLowerCase().includes('design system') && !enhanced.toLowerCase().includes('design.md')) {
12
+ enhanced = `Following the imported design system, ${enhanced}`;
13
+ suggestions.push('Added DESIGN.md reference for visual consistency.');
14
+ }
15
+ }
16
+ // 2. Calculate slop risk score
17
+ const slopRiskScore = calculateSlopRisk(prompt);
18
+ // 3. Suggest replacements for generic terms
19
+ const genericReplacements = [
20
+ [/\bmodern\b/i, 'contemporary with sharp geometric accents', 'Replace "modern" with specific visual direction'],
21
+ [/\bclean\b/i, 'minimal with generous whitespace', 'Replace "clean" with concrete layout description'],
22
+ [/\bprofessional\b/i, 'corporate with structured grid layout', 'Replace "professional" with specific aesthetic'],
23
+ [/\bnice\b/i, 'polished with intentional typography', 'Replace "nice" with visual specifics'],
24
+ [/\bbeautiful\b/i, 'visually striking with bold color contrast', 'Replace "beautiful" with design attributes'],
25
+ ];
26
+ for (const [pattern, _replacement, suggestion] of genericReplacements) {
27
+ if (pattern.test(prompt)) {
28
+ suggestions.push(suggestion);
29
+ }
30
+ }
31
+ // 4. Check for missing specifics
32
+ if (!/\d+/.test(prompt)) {
33
+ suggestions.push('Add specific numbers (e.g., "3 pricing tiers", "4 testimonials") for better results.');
34
+ }
35
+ if (!/\b(grid|bento|card|layout|sticky|floating|sidebar|split|asymmetric)\b/i.test(prompt)) {
36
+ suggestions.push('Add UI layout terms (e.g., "bento grid", "split layout", "sticky header") for structural clarity.');
37
+ }
38
+ if (!/\b(section|hero|header|footer|nav|cta|testimonial|feature|pricing)\b/i.test(prompt)) {
39
+ suggestions.push('Describe specific sections for more targeted generation.');
40
+ }
41
+ // 5. Business alignment check
42
+ const businessAlignmentIssues = [];
43
+ if (existsSync('DESIGN.md')) {
44
+ const designContent = readFileSync('DESIGN.md', 'utf-8').toLowerCase();
45
+ // If DESIGN.md says NOT e-commerce, check for e-commerce terms in prompt
46
+ if (designContent.includes('not an e-commerce') || designContent.includes('not e-commerce') || designContent.includes('no online purchasing')) {
47
+ const ecommerceTerms = prompt.match(/\b(shopping cart|add to cart|checkout|buy now|purchase|order online|e-commerce|ecommerce|shop now)\b/gi);
48
+ if (ecommerceTerms) {
49
+ businessAlignmentIssues.push(`Prompt contains e-commerce terms (${ecommerceTerms.join(', ')}) but DESIGN.md specifies this is NOT an e-commerce site. Remove these elements.`);
50
+ }
51
+ }
52
+ // If DESIGN.md mentions store locator as key, check prompt includes it
53
+ if (designContent.includes('store locator') || designContent.includes('find nearest store')) {
54
+ if (!/\b(store|tienda|sucursal|location|ubicaci|locali|find|nearest|cerca)\b/i.test(prompt)) {
55
+ businessAlignmentIssues.push('DESIGN.md specifies store locator as a key element. Consider including a store finder section in this page.');
56
+ }
57
+ }
58
+ // If DESIGN.md mentions booking/contact as primary
59
+ if (designContent.includes('booking') || designContent.includes('appointment') || designContent.includes('contact form')) {
60
+ if (!/\b(book|contact|form|appointment|schedule|cita|agendar)\b/i.test(prompt)) {
61
+ businessAlignmentIssues.push('DESIGN.md specifies booking/contact as a primary feature. Consider including a contact or booking section.');
62
+ }
63
+ }
64
+ }
65
+ return { original: prompt, enhanced, suggestions, slopRiskScore, businessAlignmentIssues };
66
+ }
67
+ /**
68
+ * Calculate AI slop risk score (0-10).
69
+ * Higher score = more likely to get generic AI output.
70
+ */
71
+ export function calculateSlopRisk(prompt) {
72
+ let score = 0;
73
+ // No layout specifics
74
+ if (!/\b(grid|bento|card|layout|sticky|floating|sidebar|split|asymmetric|column|row)\b/i.test(prompt)) {
75
+ score += 2;
76
+ }
77
+ // No specific numbers
78
+ if (!/\b\d+\b/.test(prompt)) {
79
+ score += 2;
80
+ }
81
+ // No UI/UX vocabulary
82
+ if (!/\b(section|hero|header|footer|nav|cta|testimonial|feature|pricing|carousel|accordion|tab|modal)\b/i.test(prompt)) {
83
+ score += 2;
84
+ }
85
+ // No design system reference
86
+ if (!/\b(design system|design.md|palette|typography|font)\b/i.test(prompt)) {
87
+ score += 1;
88
+ }
89
+ // Uses generic adjectives
90
+ const genericCount = (prompt.match(/\b(modern|clean|professional|nice|beautiful|sleek|elegant|stunning)\b/gi) || []).length;
91
+ score += Math.min(genericCount, 3);
92
+ return Math.min(score, 10);
93
+ }
94
+ /**
95
+ * Get human-readable risk level from score.
96
+ */
97
+ export function getSlopRiskLevel(score) {
98
+ if (score <= 3)
99
+ return 'low';
100
+ if (score <= 6)
101
+ return 'medium';
102
+ return 'high';
103
+ }
104
+ //# sourceMappingURL=prompt-enhancer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-enhancer.js","sourceRoot":"","sources":["../../src/utils/prompt-enhancer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface QuotaStatus {
2
+ flash: {
3
+ used: number;
4
+ limit: number;
5
+ remaining: number;
6
+ };
7
+ pro: {
8
+ used: number;
9
+ limit: number;
10
+ remaining: number;
11
+ };
12
+ resetDate: string;
13
+ warning?: string;
14
+ }
15
+ export declare function getQuotaStatus(): QuotaStatus;
16
+ export declare function canGenerate(model: 'GEMINI_3_PRO' | 'GEMINI_2_5_FLASH'): boolean;
17
+ export declare function formatQuotaBar(used: number, limit: number, width?: number): string;
18
+ export declare function formatQuotaDisplay(): string;
@@ -0,0 +1,49 @@
1
+ import { getConfig } from './config.js';
2
+ const LIMITS = {
3
+ GEMINI_2_5_FLASH: 350,
4
+ GEMINI_3_PRO: 200,
5
+ GEMINI_3_FLASH: 350,
6
+ GEMINI_3_1_PRO: 200,
7
+ };
8
+ export function getQuotaStatus() {
9
+ const config = getConfig();
10
+ const flashRemaining = LIMITS.GEMINI_2_5_FLASH - config.quota.flashUsed;
11
+ const proRemaining = LIMITS.GEMINI_3_PRO - config.quota.proUsed;
12
+ const status = {
13
+ flash: { used: config.quota.flashUsed, limit: LIMITS.GEMINI_2_5_FLASH, remaining: flashRemaining },
14
+ pro: { used: config.quota.proUsed, limit: LIMITS.GEMINI_3_PRO, remaining: proRemaining },
15
+ resetDate: config.quota.resetDate,
16
+ };
17
+ if (flashRemaining <= 10 || proRemaining <= 10) {
18
+ status.warning = `Low quota: Flash ${flashRemaining} remaining, Pro ${proRemaining} remaining. Resets ${config.quota.resetDate}.`;
19
+ }
20
+ return status;
21
+ }
22
+ export function canGenerate(model) {
23
+ const status = getQuotaStatus();
24
+ return model === 'GEMINI_2_5_FLASH'
25
+ ? status.flash.remaining > 0
26
+ : status.pro.remaining > 0;
27
+ }
28
+ export function formatQuotaBar(used, limit, width = 20) {
29
+ const filled = Math.round((used / limit) * width);
30
+ const empty = width - filled;
31
+ return `[${'='.repeat(filled)}${'-'.repeat(empty)}] ${used}/${limit}`;
32
+ }
33
+ export function formatQuotaDisplay() {
34
+ const status = getQuotaStatus();
35
+ const lines = [];
36
+ lines.push(`Flash (fast) ${formatQuotaBar(status.flash.used, status.flash.limit)}`);
37
+ lines.push(` ${status.flash.remaining} generations remaining this month`);
38
+ lines.push('');
39
+ lines.push(`Pro (quality) ${formatQuotaBar(status.pro.used, status.pro.limit)}`);
40
+ lines.push(` ${status.pro.remaining} generations remaining this month`);
41
+ lines.push('');
42
+ lines.push(`Resets: ${status.resetDate}`);
43
+ if (status.warning) {
44
+ lines.push('');
45
+ lines.push(`Warning: ${status.warning}`);
46
+ }
47
+ return lines.join('\n');
48
+ }
49
+ //# sourceMappingURL=quota.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota.js","sourceRoot":"","sources":["../../src/utils/quota.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,125 @@
1
+ import { z } from 'zod';
2
+ export declare const ColorRoleSchema: z.ZodObject<{
3
+ name: z.ZodString;
4
+ hex: z.ZodString;
5
+ usage: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ hex: string;
8
+ name: string;
9
+ usage: string;
10
+ }, {
11
+ hex: string;
12
+ name: string;
13
+ usage: string;
14
+ }>;
15
+ export declare const DesignMdSchema: z.ZodObject<{
16
+ visualTheme: z.ZodString;
17
+ colorPalette: z.ZodArray<z.ZodObject<{
18
+ name: z.ZodString;
19
+ hex: z.ZodString;
20
+ usage: z.ZodString;
21
+ }, "strip", z.ZodTypeAny, {
22
+ hex: string;
23
+ name: string;
24
+ usage: string;
25
+ }, {
26
+ hex: string;
27
+ name: string;
28
+ usage: string;
29
+ }>, "many">;
30
+ typography: z.ZodObject<{
31
+ heading: z.ZodString;
32
+ body: z.ZodString;
33
+ sizes: z.ZodRecord<z.ZodString, z.ZodString>;
34
+ }, "strip", z.ZodTypeAny, {
35
+ body: string;
36
+ heading: string;
37
+ sizes: Record<string, string>;
38
+ }, {
39
+ body: string;
40
+ heading: string;
41
+ sizes: Record<string, string>;
42
+ }>;
43
+ spacing: z.ZodObject<{
44
+ baseUnit: z.ZodString;
45
+ scale: z.ZodArray<z.ZodString, "many">;
46
+ }, "strip", z.ZodTypeAny, {
47
+ baseUnit: string;
48
+ scale: string[];
49
+ }, {
50
+ baseUnit: string;
51
+ scale: string[];
52
+ }>;
53
+ componentPatterns: z.ZodArray<z.ZodObject<{
54
+ name: z.ZodString;
55
+ description: z.ZodString;
56
+ }, "strip", z.ZodTypeAny, {
57
+ name: string;
58
+ description: string;
59
+ }, {
60
+ name: string;
61
+ description: string;
62
+ }>, "many">;
63
+ iconography: z.ZodString;
64
+ imagery: z.ZodString;
65
+ dos: z.ZodArray<z.ZodString, "many">;
66
+ donts: z.ZodArray<z.ZodString, "many">;
67
+ }, "strip", z.ZodTypeAny, {
68
+ typography: {
69
+ body: string;
70
+ heading: string;
71
+ sizes: Record<string, string>;
72
+ };
73
+ dos: string[];
74
+ donts: string[];
75
+ visualTheme: string;
76
+ colorPalette: {
77
+ hex: string;
78
+ name: string;
79
+ usage: string;
80
+ }[];
81
+ spacing: {
82
+ baseUnit: string;
83
+ scale: string[];
84
+ };
85
+ componentPatterns: {
86
+ name: string;
87
+ description: string;
88
+ }[];
89
+ iconography: string;
90
+ imagery: string;
91
+ }, {
92
+ typography: {
93
+ body: string;
94
+ heading: string;
95
+ sizes: Record<string, string>;
96
+ };
97
+ dos: string[];
98
+ donts: string[];
99
+ visualTheme: string;
100
+ colorPalette: {
101
+ hex: string;
102
+ name: string;
103
+ usage: string;
104
+ }[];
105
+ spacing: {
106
+ baseUnit: string;
107
+ scale: string[];
108
+ };
109
+ componentPatterns: {
110
+ name: string;
111
+ description: string;
112
+ }[];
113
+ iconography: string;
114
+ imagery: string;
115
+ }>;
116
+ export declare const PROMPT_MAX_CHARS = 5000;
117
+ export declare function validatePrompt(prompt: string): {
118
+ valid: boolean;
119
+ errors: string[];
120
+ };
121
+ export declare function validateQuota(used: number, limit: number): {
122
+ allowed: boolean;
123
+ remaining: number;
124
+ };
125
+ export type DesignMd = z.infer<typeof DesignMdSchema>;
@@ -0,0 +1,110 @@
1
+ import { z } from 'zod';
2
+ // Hex color validation
3
+ const hexColor = z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'Must be a 6-digit hex color');
4
+ // DESIGN.md color role schema
5
+ export const ColorRoleSchema = z.object({
6
+ name: z.string().min(1),
7
+ hex: hexColor,
8
+ usage: z.string().min(1),
9
+ });
10
+ // DESIGN.md validation schema
11
+ export const DesignMdSchema = z.object({
12
+ visualTheme: z.string().min(20, 'Visual theme must be at least 20 characters'),
13
+ colorPalette: z.array(ColorRoleSchema).min(5, 'Need at least 5 color roles'),
14
+ typography: z.object({
15
+ heading: z.string().min(1),
16
+ body: z.string().min(1),
17
+ sizes: z.record(z.string()),
18
+ }),
19
+ spacing: z.object({
20
+ baseUnit: z.string().regex(/^\d+(px|rem)$/, 'Must be px or rem value'),
21
+ scale: z.array(z.string()).min(3),
22
+ }),
23
+ componentPatterns: z.array(z.object({
24
+ name: z.string(),
25
+ description: z.string(),
26
+ })).min(3, 'Need at least 3 component patterns'),
27
+ iconography: z.string().min(10),
28
+ imagery: z.string().min(10),
29
+ dos: z.array(z.string()).min(3, 'Need at least 3 Do rules'),
30
+ donts: z.array(z.string()).min(3, 'Need at least 3 Don\'t rules'),
31
+ });
32
+ // Prompt validation
33
+ export const PROMPT_MAX_CHARS = 5000;
34
+ export function validatePrompt(prompt) {
35
+ const errors = [];
36
+ // Reject empty or whitespace-only prompts
37
+ if (!prompt.trim()) {
38
+ errors.push('Prompt is empty. Describe the screen you want to generate.');
39
+ return { valid: false, errors };
40
+ }
41
+ if (prompt.length > PROMPT_MAX_CHARS) {
42
+ errors.push(`Prompt is ${prompt.length} chars, max is ${PROMPT_MAX_CHARS}. ` +
43
+ `Try splitting into an initial prompt (describe the page) and refinement prompts (adjust specific sections).`);
44
+ }
45
+ // Detect multiple screens
46
+ const multiScreenPatterns = [
47
+ /\band\s+a\s+\w+\s+page\b/i,
48
+ /\bpage\s*1\b.*\bpage\s*2\b/is,
49
+ /\bfirst screen\b.*\bsecond screen\b/is,
50
+ /\b(create|build|generate|make|design)\s+.*(,\s*\w+\s+page\s*){2,}/i,
51
+ /\b(landing|home|pricing|about|contact|dashboard|login|signup)\s+page\b.*\b(landing|home|pricing|about|contact|dashboard|login|signup)\s+page\b/is,
52
+ /\bmultiple\s+(pages?|screens?)\b/i,
53
+ /\b(two|three|four|five|2|3|4|5)\s+(pages?|screens?)\b/i,
54
+ /\bpage\s+for\s+\w+\b.*\band\b.*\bpage\s+for\s+\w+\b/is,
55
+ ];
56
+ for (const pattern of multiScreenPatterns) {
57
+ if (pattern.test(prompt)) {
58
+ errors.push('Detected multiple screens in one prompt. Generate one screen at a time — ' +
59
+ 'run `forge generate` once per page for best results.');
60
+ break;
61
+ }
62
+ }
63
+ // Detect vague refinements — use word-level scoring instead of exact match
64
+ if (isVaguePrompt(prompt.trim())) {
65
+ errors.push('Prompt is too vague. Be specific about what to change. For example:\n' +
66
+ ' Instead of "make it better" try:\n' +
67
+ ' "On the hero section, increase the heading size to 4rem and change the CTA button color to #F5A623"');
68
+ }
69
+ return { valid: errors.length === 0, errors };
70
+ }
71
+ /**
72
+ * Detect vague prompts using word-level analysis instead of fragile regex.
73
+ * A prompt is vague if it's short AND contains only vague verbs/adjectives
74
+ * without any concrete UI terms (hex values, measurements, component names).
75
+ */
76
+ function isVaguePrompt(prompt) {
77
+ // Short prompts with vague intent
78
+ const words = prompt.toLowerCase().replace(/[^\w\s]/g, '').split(/\s+/);
79
+ if (words.length > 20)
80
+ return false; // Long prompts are likely specific enough
81
+ const vagueVerbs = ['make', 'get', 'fix', 'improve', 'enhance', 'update', 'change', 'tweak', 'do'];
82
+ const vagueAdj = ['better', 'nicer', 'good', 'pretty', 'nice', 'cool', 'bad', 'ugly', 'wrong', 'off', 'weird', 'professional', 'appealing'];
83
+ const vagueObjects = ['it', 'this', 'that', 'the design', 'the page', 'the layout', 'the look'];
84
+ const fillerWords = ['just', 'please', 'can', 'you', 'a', 'bit', 'more', 'something', 'about', 'looks', 'look'];
85
+ // Concrete signals that indicate specificity
86
+ const hasHexColor = /#[0-9a-f]{3,6}/i.test(prompt);
87
+ const hasMeasurement = /\d+\s*(px|rem|em|%|vh|vw)\b/.test(prompt);
88
+ const hasComponent = /\b(hero|header|footer|nav|sidebar|card|button|input|form|grid|section|modal|carousel|accordion|tab|table|banner|cta)\b/i.test(prompt);
89
+ const hasSpecificAction = /\b(color|font|size|width|height|padding|margin|spacing|border|radius|shadow|background|align|position)\b/i.test(prompt);
90
+ if (hasHexColor || hasMeasurement || hasComponent || hasSpecificAction)
91
+ return false;
92
+ const hasVagueVerb = words.some(w => vagueVerbs.includes(w));
93
+ const hasVagueAdj = words.some(w => vagueAdj.includes(w));
94
+ const meaningfulWords = words.filter(w => !fillerWords.includes(w) && w.length > 1);
95
+ // If the meaningful content is just a vague verb + vague adjective/object, it's vague
96
+ if (meaningfulWords.length <= 6 && hasVagueVerb && hasVagueAdj)
97
+ return true;
98
+ if (meaningfulWords.length <= 4 && hasVagueVerb)
99
+ return true;
100
+ // Complaints without direction: "it looks bad", "this is ugly"
101
+ if (meaningfulWords.length <= 3 && hasVagueAdj)
102
+ return true;
103
+ return false;
104
+ }
105
+ // Validate quota
106
+ export function validateQuota(used, limit) {
107
+ const remaining = limit - used;
108
+ return { allowed: remaining > 0, remaining };
109
+ }
110
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "stitch-forge",
3
+ "version": "0.3.1",
4
+ "description": "Stitch Forge — CLI framework for automating web design with Google Stitch MCP",
5
+ "type": "module",
6
+ "bin": {
7
+ "stitch-forge": "./dist/index.js",
8
+ "forge": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "dev": "tsx src/index.ts tui",
12
+ "build": "tsc && cp src/research/known-state.json dist/research/known-state.json",
13
+ "test": "vitest",
14
+ "test:run": "vitest run",
15
+ "lint": "eslint src/ tests/",
16
+ "typecheck": "tsc --noEmit",
17
+ "prepublishOnly": "npm run build && npm run test:run"
18
+ },
19
+ "dependencies": {
20
+ "commander": "^12.1.0",
21
+ "ink": "^5.1.0",
22
+ "ink-text-input": "^6.0.0",
23
+ "ink-select-input": "^6.0.0",
24
+ "ink-spinner": "^5.0.0",
25
+ "ink-table": "^3.1.0",
26
+ "react": "^18.3.1",
27
+ "chalk": "^5.3.0",
28
+ "zod": "^3.23.0",
29
+ "dotenv": "^16.4.0",
30
+ "node-fetch": "^3.3.0",
31
+ "cheerio": "^1.0.0",
32
+ "conf": "^13.0.0",
33
+ "ora": "^8.1.0",
34
+ "boxen": "^8.0.0",
35
+ "figures": "^6.1.0"
36
+ },
37
+ "devDependencies": {
38
+ "typescript": "^5.5.0",
39
+ "tsx": "^4.19.0",
40
+ "vitest": "^2.1.0",
41
+ "@types/react": "^18.3.0",
42
+ "@types/node": "^22.0.0",
43
+ "eslint": "^9.0.0"
44
+ },
45
+ "engines": {
46
+ "node": ">=20.0.0"
47
+ },
48
+ "license": "MIT",
49
+ "author": "Fernando Rodriguez Memije <hi@fernandomemije.dev> (https://fernandomemije.dev)",
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "https://github.com/freptar0/stitch-forge.git"
53
+ },
54
+ "homepage": "https://github.com/freptar0/stitch-forge#readme",
55
+ "bugs": {
56
+ "url": "https://github.com/freptar0/stitch-forge/issues"
57
+ },
58
+ "keywords": [
59
+ "stitch",
60
+ "google-stitch",
61
+ "mcp",
62
+ "web-design",
63
+ "cli",
64
+ "design-system",
65
+ "ai-design",
66
+ "claude-code",
67
+ "design-intelligence",
68
+ "anti-slop"
69
+ ],
70
+ "files": [
71
+ "dist",
72
+ ".claude/skills",
73
+ "README.md",
74
+ "LICENSE",
75
+ "DESIGN.md"
76
+ ]
77
+ }