gemini-design-mcp 3.11.0 → 3.12.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.
@@ -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,251 @@ 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
+ #########################################
377
+ # MODE DESIGN SYSTEM ACTIVÉ
378
+ #########################################
379
+
380
+ CRITICAL: Tu DOIS retourner ta réponse dans ce format EXACT avec les markers HTML.
381
+ NE RETOURNE JAMAIS juste du code. Tu DOIS inclure les DEUX sections.
382
+
383
+ ## FORMAT OBLIGATOIRE (à respecter à la lettre)
384
+
385
+ <!-- CODE_START -->
386
+ (le code complet de la page ici)
387
+ <!-- CODE_END -->
388
+
389
+ <!-- DESIGN_SYSTEM_START -->
390
+ (le design system complet ici)
391
+ <!-- DESIGN_SYSTEM_END -->
392
+
393
+ #########################################
394
+
395
+ Tu dois générer un design system ULTRA COMPLET en plus du code.
396
+
397
+ IMPORTANT : Ne te limite PAS aux composants présents dans cette page.
398
+ Imagine que ce projet aura : dashboard, landing page, settings, formulaires,
399
+ modals, tables, cards, sidebars, etc. Génère TOUS les tokens et composants
400
+ qui pourraient être nécessaires.
401
+
402
+ ### TEMPLATE DU DESIGN SYSTEM (entre les markers DESIGN_SYSTEM_START/END)
403
+
404
+ # Design System - [Nom du Projet]
405
+
406
+ ## Colors
407
+ - Background principal: #XXXXXX
408
+ - Background secondaire: #XXXXXX
409
+ - Background tertiaire: #XXXXXX
410
+ - Border default: #XXXXXX
411
+ - Border hover: #XXXXXX
412
+ - Text primary: #XXXXXX
413
+ - Text secondary: #XXXXXX
414
+ - Text muted: #XXXXXX
415
+ - Accent primary: #XXXXXX
416
+ - Accent hover: #XXXXXX
417
+ - Success: #XXXXXX
418
+ - Warning: #XXXXXX
419
+ - Error: #XXXXXX
420
+ - Info: #XXXXXX
421
+
422
+ ## Typography
423
+ ### Headings
424
+ - H1: \`className="..."\`
425
+ - H2: \`className="..."\`
426
+ - H3: \`className="..."\`
427
+ - H4: \`className="..."\`
428
+
429
+ ### Body
430
+ - Large: \`className="..."\`
431
+ - Default: \`className="..."\`
432
+ - Small: \`className="..."\`
433
+ - Tiny: \`className="..."\`
434
+
435
+ ### Special
436
+ - Label: \`className="..."\`
437
+ - Monospace: \`className="..."\`
438
+ - Link: \`className="..."\`
439
+
440
+ ## Spacing Scale
441
+ - xs: Xpx
442
+ - sm: Xpx
443
+ - md: Xpx
444
+ - lg: Xpx
445
+ - xl: Xpx
446
+ - 2xl: Xpx
447
+
448
+ ## Border Radius
449
+ - none: 0
450
+ - sm: Xpx
451
+ - md: Xpx
452
+ - lg: Xpx
453
+ - full: 9999px
454
+
455
+ ## Shadows
456
+ - sm: \`shadow-...\`
457
+ - md: \`shadow-...\`
458
+ - lg: \`shadow-...\`
459
+
460
+ ## Buttons
461
+ ### Primary
462
+ UTILISER EXACTEMENT :
463
+ \`className="..."\`
464
+
465
+ ### Secondary
466
+ UTILISER EXACTEMENT :
467
+ \`className="..."\`
468
+
469
+ ### Ghost
470
+ UTILISER EXACTEMENT :
471
+ \`className="..."\`
472
+
473
+ ### Danger
474
+ UTILISER EXACTEMENT :
475
+ \`className="..."\`
476
+
477
+ ### Sizes
478
+ - sm: \`className="... px-3 py-1.5 text-xs ..."\`
479
+ - md: \`className="... px-4 py-2 text-sm ..."\`
480
+ - lg: \`className="... px-6 py-3 text-base ..."\`
481
+
482
+ ## Inputs
483
+ ### Text Input
484
+ UTILISER EXACTEMENT :
485
+ \`className="..."\`
486
+
487
+ ### Textarea
488
+ UTILISER EXACTEMENT :
489
+ \`className="..."\`
490
+
491
+ ### Select
492
+ UTILISER EXACTEMENT :
493
+ \`className="..."\`
494
+
495
+ ### Checkbox/Radio
496
+ UTILISER EXACTEMENT :
497
+ \`className="..."\`
498
+
499
+ ### Input Sizes
500
+ - sm: \`className="... px-3 py-1.5 text-sm ..."\`
501
+ - md: \`className="... px-4 py-2.5 text-sm ..."\`
502
+ - lg: \`className="... px-4 py-3 text-base ..."\`
503
+
504
+ ## Cards
505
+ ### Default Card
506
+ UTILISER EXACTEMENT :
507
+ \`className="..."\`
508
+
509
+ ### Elevated Card
510
+ UTILISER EXACTEMENT :
511
+ \`className="..."\`
512
+
513
+ ### Interactive Card (hover)
514
+ UTILISER EXACTEMENT :
515
+ \`className="..."\`
516
+
517
+ ## Modals
518
+ ### Overlay
519
+ UTILISER EXACTEMENT :
520
+ \`className="..."\`
521
+
522
+ ### Modal Container
523
+ UTILISER EXACTEMENT :
524
+ \`className="..."\`
525
+
526
+ ## Tables
527
+ ### Table Container
528
+ UTILISER EXACTEMENT :
529
+ \`className="..."\`
530
+
531
+ ### Table Header
532
+ UTILISER EXACTEMENT :
533
+ \`className="..."\`
534
+
535
+ ### Table Row
536
+ UTILISER EXACTEMENT :
537
+ \`className="..."\`
538
+
539
+ ### Table Cell
540
+ UTILISER EXACTEMENT :
541
+ \`className="..."\`
542
+
543
+ ## Navigation
544
+ ### Sidebar
545
+ UTILISER EXACTEMENT :
546
+ \`className="..."\`
547
+
548
+ ### Nav Item (default)
549
+ UTILISER EXACTEMENT :
550
+ \`className="..."\`
551
+
552
+ ### Nav Item (active)
553
+ UTILISER EXACTEMENT :
554
+ \`className="..."\`
555
+
556
+ ### Topbar
557
+ UTILISER EXACTEMENT :
558
+ \`className="..."\`
559
+
560
+ ## Badges/Tags
561
+ ### Default
562
+ UTILISER EXACTEMENT :
563
+ \`className="..."\`
564
+
565
+ ### Success/Warning/Error/Info variants
566
+ [Classes exactes pour chaque variante]
567
+
568
+ ## Alerts
569
+ ### Success/Warning/Error/Info
570
+ [Classes exactes pour chaque type]
571
+
572
+ ## Dividers
573
+ UTILISER EXACTEMENT :
574
+ \`className="..."\`
575
+
576
+ ## Avatar
577
+ ### Sizes (sm/md/lg)
578
+ [Classes exactes pour chaque taille]
579
+
580
+ ## Dropdown Menu
581
+ ### Container
582
+ UTILISER EXACTEMENT :
583
+ \`className="..."\`
584
+
585
+ ### Menu Item
586
+ UTILISER EXACTEMENT :
587
+ \`className="..."\`
588
+
589
+ ---
590
+
591
+ ## RÈGLES D'UTILISATION
592
+
593
+ 1. **COPIER EXACTEMENT** les classes spécifiées ci-dessus
594
+ 2. **NE JAMAIS** inventer de nouvelles valeurs de padding, margin, couleurs
595
+ 3. **NE JAMAIS** modifier les border-radius ou shadows définis
596
+ 4. **TOUJOURS** utiliser les tailles définies (sm/md/lg)
597
+ 5. Si un composant n'existe pas dans ce design system, le créer en respectant les tokens (colors, spacing, radius) définis
598
+
599
+ <!-- DESIGN_SYSTEM_END -->
600
+ `;
601
+
602
+ // =============================================================================
603
+ // DESIGN SYSTEM USAGE INSTRUCTIONS
604
+ // Added to modify/snippet prompts when design system is loaded
605
+ // =============================================================================
606
+ export const DESIGN_SYSTEM_USAGE_INSTRUCTIONS = `
607
+ RÈGLE CRITIQUE - DESIGN SYSTEM OBLIGATOIRE:
608
+ Si un design system est fourni dans le context, tu DOIS :
609
+ - Copier EXACTEMENT les classes Tailwind spécifiées
610
+ - NE JAMAIS inventer de nouvelles couleurs, paddings, ou border-radius
611
+ - Utiliser les composants définis (Button Primary, Input, Card, etc.)
612
+ - Respecter les tailles définies (sm/md/lg) sans les modifier
613
+ - Si un élément n'existe pas dans le design system, le créer en utilisant UNIQUEMENT les tokens définis
614
+ `;
615
+
371
616
  export const SNIPPET_FRONTEND_PROMPT = `You are an elite UI/UX Designer generating a code snippet to INSERT.
372
617
 
373
618
  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,39 @@ IMPORTANT: Analyze the existing code carefully and match:
61
66
  - Import patterns and file structure
62
67
  `;
63
68
  }
64
- const systemPrompt = `${CREATE_FRONTEND_PROMPT}
69
+ // Build the system prompt - design system generation instructions go FIRST if enabled
70
+ let systemPrompt;
71
+ if (generateDesignSystem) {
72
+ systemPrompt = `${DESIGN_SYSTEM_GENERATION_PROMPT}
73
+
74
+ ---
75
+
76
+ ${CREATE_FRONTEND_PROMPT}
77
+ ${designSystemInstructions}
78
+ ${contextInstructions}
79
+ TECH STACK: ${techStack}
80
+ FILE PATH: ${filePath}
81
+
82
+ RAPPEL CRITIQUE: Tu DOIS utiliser le format avec les markers <!-- CODE_START/END --> et <!-- DESIGN_SYSTEM_START/END -->. Ne retourne JAMAIS juste le code.`.trim();
83
+ } else {
84
+ systemPrompt = `${CREATE_FRONTEND_PROMPT}
65
85
  ${designSystemInstructions}
66
86
  ${contextInstructions}
67
87
  TECH STACK: ${techStack}
68
88
  FILE PATH: ${filePath}
69
89
 
70
90
  Remember: Return a COMPLETE file ready to save at ${filePath}`.trim();
91
+ }
71
92
  const rawResult = await generateWithGemini(systemPrompt, request, undefined, "high", "create_frontend");
93
+ // Handle design system generation mode
94
+ if (generateDesignSystem) {
95
+ const parsed = parseGeminiResponseWithDesignSystem(rawResult);
96
+ const code = stripCodeFences(parsed.code);
97
+ return {
98
+ content: [{ type: "text", text: code }],
99
+ designSystem: parsed.designSystem,
100
+ };
101
+ }
72
102
  // Strip markdown code fences from the result
73
103
  const result = stripCodeFences(rawResult);
74
104
  // 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.1",
4
4
  "description": "MCP server that uses Gemini 3 Pro for frontend/design code generation",
5
5
  "main": "build/index.js",
6
6
  "bin": {