gemini-design-mcp 3.11.0 → 3.12.0

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.
@@ -1,5 +1,33 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
+ /**
4
+ * Parse Gemini response that contains both code and design system
5
+ * when generateDesignSystem is enabled
6
+ */
7
+ export function parseGeminiResponseWithDesignSystem(response) {
8
+ const codeMatch = response.match(/<!-- CODE_START -->([\s\S]*?)<!-- CODE_END -->/);
9
+ const dsMatch = response.match(/<!-- DESIGN_SYSTEM_START -->([\s\S]*?)<!-- DESIGN_SYSTEM_END -->/);
10
+ return {
11
+ code: codeMatch ? codeMatch[1].trim() : response, // fallback si pas de balises
12
+ designSystem: dsMatch ? dsMatch[1].trim() : null
13
+ };
14
+ }
15
+ /**
16
+ * Load design-system.md from project root if it exists
17
+ * Checks multiple possible file names
18
+ */
19
+ export function loadDesignSystemIfExists(projectRoot) {
20
+ const possiblePaths = [
21
+ path.join(projectRoot || process.cwd(), 'design-system.md'),
22
+ path.join(projectRoot || process.cwd(), 'DESIGN-SYSTEM.md'),
23
+ ];
24
+ for (const p of possiblePaths) {
25
+ if (fs.existsSync(p)) {
26
+ return fs.readFileSync(p, 'utf-8');
27
+ }
28
+ }
29
+ return null;
30
+ }
3
31
  /**
4
32
  * Strip markdown code fences from a string
5
33
  * Removes ```language and ``` from the beginning and end
@@ -368,6 +368,239 @@ IMPORTANT:
368
368
  // SNIPPET_FRONTEND PROMPT
369
369
  // Used for generating code snippets to INSERT into existing files
370
370
  // =============================================================================
371
+ // =============================================================================
372
+ // DESIGN SYSTEM GENERATION PROMPT
373
+ // Injected when generateDesignSystem === true in create_frontend
374
+ // =============================================================================
375
+ export const DESIGN_SYSTEM_GENERATION_PROMPT = `
376
+ ## GÉNÉRATION DU DESIGN SYSTEM (MODE ACTIVÉ)
377
+
378
+ Tu dois générer un design system ULTRA COMPLET en plus du code.
379
+
380
+ IMPORTANT : Ne te limite PAS aux composants présents dans cette page.
381
+ Imagine que ce projet aura : dashboard, landing page, settings, formulaires,
382
+ modals, tables, cards, sidebars, etc. Génère TOUS les tokens et composants
383
+ qui pourraient être nécessaires.
384
+
385
+ ### FORMAT DE SORTIE
386
+
387
+ <!-- CODE_START -->
388
+ [Le code complet de la page ici]
389
+ <!-- CODE_END -->
390
+
391
+ <!-- DESIGN_SYSTEM_START -->
392
+ # Design System - [Nom du Projet]
393
+
394
+ ## Colors
395
+ - Background principal: #XXXXXX
396
+ - Background secondaire: #XXXXXX
397
+ - Background tertiaire: #XXXXXX
398
+ - Border default: #XXXXXX
399
+ - Border hover: #XXXXXX
400
+ - Text primary: #XXXXXX
401
+ - Text secondary: #XXXXXX
402
+ - Text muted: #XXXXXX
403
+ - Accent primary: #XXXXXX
404
+ - Accent hover: #XXXXXX
405
+ - Success: #XXXXXX
406
+ - Warning: #XXXXXX
407
+ - Error: #XXXXXX
408
+ - Info: #XXXXXX
409
+
410
+ ## Typography
411
+ ### Headings
412
+ - H1: \`className="..."\`
413
+ - H2: \`className="..."\`
414
+ - H3: \`className="..."\`
415
+ - H4: \`className="..."\`
416
+
417
+ ### Body
418
+ - Large: \`className="..."\`
419
+ - Default: \`className="..."\`
420
+ - Small: \`className="..."\`
421
+ - Tiny: \`className="..."\`
422
+
423
+ ### Special
424
+ - Label: \`className="..."\`
425
+ - Monospace: \`className="..."\`
426
+ - Link: \`className="..."\`
427
+
428
+ ## Spacing Scale
429
+ - xs: Xpx
430
+ - sm: Xpx
431
+ - md: Xpx
432
+ - lg: Xpx
433
+ - xl: Xpx
434
+ - 2xl: Xpx
435
+
436
+ ## Border Radius
437
+ - none: 0
438
+ - sm: Xpx
439
+ - md: Xpx
440
+ - lg: Xpx
441
+ - full: 9999px
442
+
443
+ ## Shadows
444
+ - sm: \`shadow-...\`
445
+ - md: \`shadow-...\`
446
+ - lg: \`shadow-...\`
447
+
448
+ ## Buttons
449
+ ### Primary
450
+ UTILISER EXACTEMENT :
451
+ \`className="..."\`
452
+
453
+ ### Secondary
454
+ UTILISER EXACTEMENT :
455
+ \`className="..."\`
456
+
457
+ ### Ghost
458
+ UTILISER EXACTEMENT :
459
+ \`className="..."\`
460
+
461
+ ### Danger
462
+ UTILISER EXACTEMENT :
463
+ \`className="..."\`
464
+
465
+ ### Sizes
466
+ - sm: \`className="... px-3 py-1.5 text-xs ..."\`
467
+ - md: \`className="... px-4 py-2 text-sm ..."\`
468
+ - lg: \`className="... px-6 py-3 text-base ..."\`
469
+
470
+ ## Inputs
471
+ ### Text Input
472
+ UTILISER EXACTEMENT :
473
+ \`className="..."\`
474
+
475
+ ### Textarea
476
+ UTILISER EXACTEMENT :
477
+ \`className="..."\`
478
+
479
+ ### Select
480
+ UTILISER EXACTEMENT :
481
+ \`className="..."\`
482
+
483
+ ### Checkbox/Radio
484
+ UTILISER EXACTEMENT :
485
+ \`className="..."\`
486
+
487
+ ### Input Sizes
488
+ - sm: \`className="... px-3 py-1.5 text-sm ..."\`
489
+ - md: \`className="... px-4 py-2.5 text-sm ..."\`
490
+ - lg: \`className="... px-4 py-3 text-base ..."\`
491
+
492
+ ## Cards
493
+ ### Default Card
494
+ UTILISER EXACTEMENT :
495
+ \`className="..."\`
496
+
497
+ ### Elevated Card
498
+ UTILISER EXACTEMENT :
499
+ \`className="..."\`
500
+
501
+ ### Interactive Card (hover)
502
+ UTILISER EXACTEMENT :
503
+ \`className="..."\`
504
+
505
+ ## Modals
506
+ ### Overlay
507
+ UTILISER EXACTEMENT :
508
+ \`className="..."\`
509
+
510
+ ### Modal Container
511
+ UTILISER EXACTEMENT :
512
+ \`className="..."\`
513
+
514
+ ## Tables
515
+ ### Table Container
516
+ UTILISER EXACTEMENT :
517
+ \`className="..."\`
518
+
519
+ ### Table Header
520
+ UTILISER EXACTEMENT :
521
+ \`className="..."\`
522
+
523
+ ### Table Row
524
+ UTILISER EXACTEMENT :
525
+ \`className="..."\`
526
+
527
+ ### Table Cell
528
+ UTILISER EXACTEMENT :
529
+ \`className="..."\`
530
+
531
+ ## Navigation
532
+ ### Sidebar
533
+ UTILISER EXACTEMENT :
534
+ \`className="..."\`
535
+
536
+ ### Nav Item (default)
537
+ UTILISER EXACTEMENT :
538
+ \`className="..."\`
539
+
540
+ ### Nav Item (active)
541
+ UTILISER EXACTEMENT :
542
+ \`className="..."\`
543
+
544
+ ### Topbar
545
+ UTILISER EXACTEMENT :
546
+ \`className="..."\`
547
+
548
+ ## Badges/Tags
549
+ ### Default
550
+ UTILISER EXACTEMENT :
551
+ \`className="..."\`
552
+
553
+ ### Success/Warning/Error/Info variants
554
+ [Classes exactes pour chaque variante]
555
+
556
+ ## Alerts
557
+ ### Success/Warning/Error/Info
558
+ [Classes exactes pour chaque type]
559
+
560
+ ## Dividers
561
+ UTILISER EXACTEMENT :
562
+ \`className="..."\`
563
+
564
+ ## Avatar
565
+ ### Sizes (sm/md/lg)
566
+ [Classes exactes pour chaque taille]
567
+
568
+ ## Dropdown Menu
569
+ ### Container
570
+ UTILISER EXACTEMENT :
571
+ \`className="..."\`
572
+
573
+ ### Menu Item
574
+ UTILISER EXACTEMENT :
575
+ \`className="..."\`
576
+
577
+ ---
578
+
579
+ ## RÈGLES D'UTILISATION
580
+
581
+ 1. **COPIER EXACTEMENT** les classes spécifiées ci-dessus
582
+ 2. **NE JAMAIS** inventer de nouvelles valeurs de padding, margin, couleurs
583
+ 3. **NE JAMAIS** modifier les border-radius ou shadows définis
584
+ 4. **TOUJOURS** utiliser les tailles définies (sm/md/lg)
585
+ 5. Si un composant n'existe pas dans ce design system, le créer en respectant les tokens (colors, spacing, radius) définis
586
+
587
+ <!-- DESIGN_SYSTEM_END -->
588
+ `;
589
+
590
+ // =============================================================================
591
+ // DESIGN SYSTEM USAGE INSTRUCTIONS
592
+ // Added to modify/snippet prompts when design system is loaded
593
+ // =============================================================================
594
+ export const DESIGN_SYSTEM_USAGE_INSTRUCTIONS = `
595
+ RÈGLE CRITIQUE - DESIGN SYSTEM OBLIGATOIRE:
596
+ Si un design system est fourni dans le context, tu DOIS :
597
+ - Copier EXACTEMENT les classes Tailwind spécifiées
598
+ - NE JAMAIS inventer de nouvelles couleurs, paddings, ou border-radius
599
+ - Utiliser les composants définis (Button Primary, Input, Card, etc.)
600
+ - Respecter les tailles définies (sm/md/lg) sans les modifier
601
+ - Si un élément n'existe pas dans le design system, le créer en utilisant UNIQUEMENT les tokens définis
602
+ `;
603
+
371
604
  export const SNIPPET_FRONTEND_PROMPT = `You are an elite UI/UX Designer generating a code snippet to INSERT.
372
605
 
373
606
  YOUR TASK: Generate a focused code snippet that will be INSERTED into an existing file.
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { generateWithGemini } from "../lib/gemini.js";
3
- import { CREATE_FRONTEND_PROMPT } from "../prompts/system.js";
4
- import { stripCodeFences } from "../lib/filesystem.js";
3
+ import { CREATE_FRONTEND_PROMPT, DESIGN_SYSTEM_GENERATION_PROMPT } from "../prompts/system.js";
4
+ import { stripCodeFences, parseGeminiResponseWithDesignSystem } from "../lib/filesystem.js";
5
5
  import { scaleSchema, scaleDescriptions } from "../lib/scale.js";
6
6
  export const createFrontendSchema = {
7
7
  request: z.string().describe("What to create: describe the page, component, or section. " +
@@ -24,9 +24,14 @@ export const createFrontendSchema = {
24
24
  }).describe("The selected design vibe"),
25
25
  }).optional().describe("Design system with selected vibe. REQUIRED for new projects without existing design. " +
26
26
  "Call generate_vibes first, user selects, then pass the selection here."),
27
+ generateDesignSystem: z.boolean().optional().describe(
28
+ "Si true, Gemini génère aussi un design system complet en plus du code. " +
29
+ "Activer UNIQUEMENT pour la PREMIÈRE page du projet. " +
30
+ "Le design system sera retourné séparément pour être sauvegardé dans design-system.md"
31
+ ),
27
32
  };
28
33
  export async function createFrontend(params) {
29
- const { request, filePath, techStack, context, designSystem } = params;
34
+ const { request, filePath, techStack, context, designSystem, generateDesignSystem } = params;
30
35
  // Build design system instructions if provided
31
36
  let designSystemInstructions = '';
32
37
  if (designSystem?.vibe) {
@@ -61,14 +66,29 @@ IMPORTANT: Analyze the existing code carefully and match:
61
66
  - Import patterns and file structure
62
67
  `;
63
68
  }
69
+ // Add design system generation instructions if requested
70
+ let designSystemGenerationInstructions = '';
71
+ if (generateDesignSystem) {
72
+ designSystemGenerationInstructions = DESIGN_SYSTEM_GENERATION_PROMPT;
73
+ }
64
74
  const systemPrompt = `${CREATE_FRONTEND_PROMPT}
65
75
  ${designSystemInstructions}
66
76
  ${contextInstructions}
77
+ ${designSystemGenerationInstructions}
67
78
  TECH STACK: ${techStack}
68
79
  FILE PATH: ${filePath}
69
80
 
70
- Remember: Return a COMPLETE file ready to save at ${filePath}`.trim();
81
+ Remember: Return a COMPLETE file ready to save at ${filePath}${generateDesignSystem ? '. IMPORTANT: Follow the exact output format with <!-- CODE_START/END --> and <!-- DESIGN_SYSTEM_START/END --> markers.' : ''}`.trim();
71
82
  const rawResult = await generateWithGemini(systemPrompt, request, undefined, "high", "create_frontend");
83
+ // Handle design system generation mode
84
+ if (generateDesignSystem) {
85
+ const parsed = parseGeminiResponseWithDesignSystem(rawResult);
86
+ const code = stripCodeFences(parsed.code);
87
+ return {
88
+ content: [{ type: "text", text: code }],
89
+ designSystem: parsed.designSystem,
90
+ };
91
+ }
72
92
  // Strip markdown code fences from the result
73
93
  const result = stripCodeFences(rawResult);
74
94
  // Return the code for the agent to write
@@ -1,7 +1,8 @@
1
1
  import { z } from "zod";
2
2
  import { generateWithGemini } from "../lib/gemini.js";
3
- import { MODIFY_FRONTEND_PROMPT } from "../prompts/system.js";
3
+ import { MODIFY_FRONTEND_PROMPT, DESIGN_SYSTEM_USAGE_INSTRUCTIONS } from "../prompts/system.js";
4
4
  import { scaleSchema, getScaleInstructions } from "../lib/scale.js";
5
+ import { loadDesignSystemIfExists } from "../lib/filesystem.js";
5
6
  export const modifyFrontendSchema = {
6
7
  modification: z.string().describe("The SINGLE design modification to make. Be specific. " +
7
8
  "Examples: " +
@@ -19,20 +20,37 @@ export const modifyFrontendSchema = {
19
20
  "Example: 'Project uses: var(--font-heading), var(--bg-primary), .section-padding class'"),
20
21
  scale: scaleSchema.optional().describe("Element sizing: 'refined' (small, elegant), 'balanced' (standard), 'zoomed' (large). " +
21
22
  "Controls button sizes, typography, spacing, icons."),
23
+ projectRoot: z.string().optional().describe("Root directory of the project. Used to auto-load design-system.md if it exists. " +
24
+ "If not provided, uses current working directory."),
22
25
  };
23
26
  export async function modifyFrontend(params) {
24
- const { modification, targetCode, filePath, context, scale } = params;
25
- // Build context instructions
27
+ const { modification, targetCode, filePath, context, scale, projectRoot } = params;
28
+ // Auto-load design system if exists
29
+ const autoDesignSystem = loadDesignSystemIfExists(projectRoot);
30
+ // Build context instructions with design system merged
26
31
  let contextInstructions = '';
27
- if (context) {
32
+ if (autoDesignSystem) {
28
33
  contextInstructions = `
34
+ ## Design System (OBLIGATOIRE - copier exactement les classes)
35
+
36
+ ${autoDesignSystem}
37
+
38
+ ---
39
+
40
+ `;
41
+ }
42
+ if (context) {
43
+ contextInstructions += `
29
44
  DESIGN CONTEXT:
30
45
  ${context}
31
46
  `;
32
47
  }
33
48
  // Build scale instructions
34
49
  const scaleInstructions = getScaleInstructions(scale);
50
+ // Add design system usage instructions if design system was loaded
51
+ const designSystemRules = autoDesignSystem ? DESIGN_SYSTEM_USAGE_INSTRUCTIONS : '';
35
52
  const systemPrompt = `${MODIFY_FRONTEND_PROMPT}
53
+ ${designSystemRules}
36
54
  ${scaleInstructions}
37
55
  ${contextInstructions}
38
56
  FILE: ${filePath}
@@ -1,7 +1,8 @@
1
1
  import { z } from "zod";
2
2
  import { generateWithGemini } from "../lib/gemini.js";
3
- import { SNIPPET_FRONTEND_PROMPT } from "../prompts/system.js";
3
+ import { SNIPPET_FRONTEND_PROMPT, DESIGN_SYSTEM_USAGE_INSTRUCTIONS } from "../prompts/system.js";
4
4
  import { scaleSchema, getScaleInstructions } from "../lib/scale.js";
5
+ import { loadDesignSystemIfExists } from "../lib/filesystem.js";
5
6
  export const snippetFrontendSchema = {
6
7
  request: z.string().describe("What code snippet to generate. Be specific about what you need. " +
7
8
  "Examples: " +
@@ -22,20 +23,37 @@ export const snippetFrontendSchema = {
22
23
  "Without this, Gemini will create standalone styles that won't match your design system."),
23
24
  scale: scaleSchema.optional().describe("Element sizing: 'refined' (small, elegant), 'balanced' (standard), 'zoomed' (large). " +
24
25
  "Controls button sizes, typography, spacing, icons."),
26
+ projectRoot: z.string().optional().describe("Root directory of the project. Used to auto-load design-system.md if it exists. " +
27
+ "If not provided, uses current working directory."),
25
28
  };
26
29
  export async function snippetFrontend(params) {
27
- const { request, targetFile, techStack, insertionContext, context, scale } = params;
28
- // Build context instructions
30
+ const { request, targetFile, techStack, insertionContext, context, scale, projectRoot } = params;
31
+ // Auto-load design system if exists
32
+ const autoDesignSystem = loadDesignSystemIfExists(projectRoot);
33
+ // Build context instructions with design system merged
29
34
  let contextInstructions = '';
30
- if (context) {
35
+ if (autoDesignSystem) {
31
36
  contextInstructions = `
37
+ ## Design System (OBLIGATOIRE - copier exactement les classes)
38
+
39
+ ${autoDesignSystem}
40
+
41
+ ---
42
+
43
+ `;
44
+ }
45
+ if (context) {
46
+ contextInstructions += `
32
47
  PROJECT CONTEXT (match these patterns):
33
48
  ${context}
34
49
  `;
35
50
  }
36
51
  // Build scale instructions
37
52
  const scaleInstructions = getScaleInstructions(scale);
53
+ // Add design system usage instructions if design system was loaded
54
+ const designSystemRules = autoDesignSystem ? DESIGN_SYSTEM_USAGE_INSTRUCTIONS : '';
38
55
  const systemPrompt = `${SNIPPET_FRONTEND_PROMPT}
56
+ ${designSystemRules}
39
57
  ${scaleInstructions}
40
58
  ${contextInstructions}
41
59
  TECH STACK: ${techStack}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemini-design-mcp",
3
- "version": "3.11.0",
3
+ "version": "3.12.0",
4
4
  "description": "MCP server that uses Gemini 3 Pro for frontend/design code generation",
5
5
  "main": "build/index.js",
6
6
  "bin": {