gemini-design-mcp 3.12.0 → 3.12.2

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.
@@ -373,7 +373,24 @@ IMPORTANT:
373
373
  // Injected when generateDesignSystem === true in create_frontend
374
374
  // =============================================================================
375
375
  export const DESIGN_SYSTEM_GENERATION_PROMPT = `
376
- ## GÉNÉRATION DU DESIGN SYSTEM (MODE ACTIVÉ)
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
+ #########################################
377
394
 
378
395
  Tu dois générer un design system ULTRA COMPLET en plus du code.
379
396
 
@@ -382,13 +399,8 @@ Imagine que ce projet aura : dashboard, landing page, settings, formulaires,
382
399
  modals, tables, cards, sidebars, etc. Génère TOUS les tokens et composants
383
400
  qui pourraient être nécessaires.
384
401
 
385
- ### FORMAT DE SORTIE
386
-
387
- <!-- CODE_START -->
388
- [Le code complet de la page ici]
389
- <!-- CODE_END -->
402
+ ### TEMPLATE DU DESIGN SYSTEM (entre les markers DESIGN_SYSTEM_START/END)
390
403
 
391
- <!-- DESIGN_SYSTEM_START -->
392
404
  # Design System - [Nom du Projet]
393
405
 
394
406
  ## Colors
@@ -601,6 +613,64 @@ Si un design system est fourni dans le context, tu DOIS :
601
613
  - Si un élément n'existe pas dans le design system, le créer en utilisant UNIQUEMENT les tokens définis
602
614
  `;
603
615
 
616
+ // =============================================================================
617
+ // GENERATE VIBES PAGE PROMPT
618
+ // Generates a visual page with 5 sections for the user to see and select
619
+ // =============================================================================
620
+ export const GENERATE_VIBES_PAGE_PROMPT = `Tu génères une page React/HTML complète avec 5 sections visuelles pour permettre à l'utilisateur de choisir son design préféré.
621
+
622
+ ÉTAPE 1: Analyse le projet et génère 5 VIBES UNIQUES adaptées
623
+ - Chaque vibe doit avoir un nom créatif et une direction esthétique claire
624
+ - Les 5 vibes doivent être TRÈS différentes les unes des autres
625
+ - Adapte les vibes au type de projet et à l'audience
626
+ - Exemples de directions: Luxe/Minimal, Brutalist/Raw, Playful/Colorful, Corporate/Trust, Dark/Techy, Editorial, Y2K Revival, etc.
627
+
628
+ ÉTAPE 2: Génère une page avec 5 sections identiques (même structure) mais stylées différemment
629
+
630
+ STRUCTURE DE CHAQUE SECTION (identique pour les 5):
631
+ - Un label bien visible "Vibe #X: [Nom créatif de la vibe]" en haut
632
+ - Hero heading: "Transform Your Workflow"
633
+ - Subheading: "The modern platform for teams who want to move faster"
634
+ - CTA button: "Get Started"
635
+ - 3 feature cards en grille avec:
636
+ - Titre: "Lightning Fast" / "Secure by Design" / "Team Collaboration"
637
+ - Description courte pour chaque
638
+ - Séparateur visuel clair entre sections (ligne, espace, ou changement de fond)
639
+
640
+ RÈGLES CRITIQUES:
641
+ 1. Marquer CHAQUE section avec des commentaires HTML:
642
+ <!-- VIBE_1_START -->
643
+ ... tout le code de la section 1 ...
644
+ <!-- VIBE_1_END -->
645
+
646
+ <!-- VIBE_2_START -->
647
+ ... tout le code de la section 2 ...
648
+ <!-- VIBE_2_END -->
649
+
650
+ (et ainsi de suite jusqu'à VIBE_5)
651
+
652
+ 2. CHAQUE section doit être COMPLÈTE et auto-suffisante:
653
+ - Tous les styles Tailwind inline
654
+ - Extractible telle quelle sans modification
655
+ - Pas de dépendances sur d'autres sections
656
+
657
+ 3. Le MÊME contenu texte pour les 5 sections:
658
+ - "Transform Your Workflow"
659
+ - "The modern platform for teams who want to move faster"
660
+ - Mêmes titres de features
661
+ - SEUL LE STYLE CHANGE
662
+
663
+ 4. Styles TRÈS différents entre les sections:
664
+ - Couleurs de fond différentes
665
+ - Typographie différente (tailles, poids)
666
+ - Spacing différent
667
+ - Border-radius différent
668
+ - Effets différents (shadows, gradients, etc.)
669
+
670
+ 5. Inclure TOUTES les classes Tailwind inline - AUCUNE variable externe, AUCUN CSS custom
671
+
672
+ OUTPUT: Une page React/HTML complète et fonctionnelle avec les 5 sections bien marquées. Le code doit être prêt à être sauvegardé et ouvert dans un navigateur.`;
673
+
604
674
  export const SNIPPET_FRONTEND_PROMPT = `You are an elite UI/UX Designer generating a code snippet to INSERT.
605
675
 
606
676
  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, DESIGN_SYSTEM_GENERATION_PROMPT } from "../prompts/system.js";
4
- import { stripCodeFences, parseGeminiResponseWithDesignSystem } from "../lib/filesystem.js";
3
+ import { CREATE_FRONTEND_PROMPT, DESIGN_SYSTEM_GENERATION_PROMPT, DESIGN_SYSTEM_USAGE_INSTRUCTIONS } from "../prompts/system.js";
4
+ import { stripCodeFences, parseGeminiResponseWithDesignSystem, loadDesignSystemIfExists } 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. " +
@@ -29,9 +29,17 @@ export const createFrontendSchema = {
29
29
  "Activer UNIQUEMENT pour la PREMIÈRE page du projet. " +
30
30
  "Le design system sera retourné séparément pour être sauvegardé dans design-system.md"
31
31
  ),
32
+ projectRoot: z.string().optional().describe(
33
+ "Root directory du projet. Utilisé pour auto-charger design-system.md s'il existe. " +
34
+ "TOUJOURS passer ce paramètre pour que Gemini utilise le design system existant."
35
+ ),
32
36
  };
33
37
  export async function createFrontend(params) {
34
- const { request, filePath, techStack, context, designSystem, generateDesignSystem } = params;
38
+ const { request, filePath, techStack, context, designSystem, generateDesignSystem, projectRoot } = params;
39
+
40
+ // Auto-load design system if exists
41
+ const autoDesignSystem = loadDesignSystemIfExists(projectRoot);
42
+
35
43
  // Build design system instructions if provided
36
44
  let designSystemInstructions = '';
37
45
  if (designSystem?.vibe) {
@@ -51,9 +59,22 @@ Interpret this vibe creatively — choose colors, typography, and styling that e
51
59
  The scale above is MANDATORY and defines how large or small UI elements should be.
52
60
  `;
53
61
  }
54
- // Build context instructions (ignore empty strings and "null" strings)
62
+ // Build context instructions - prioritize auto-loaded design system
55
63
  let contextInstructions = '';
56
- if (context && context !== "null" && context.trim() !== "") {
64
+ let designSystemRules = '';
65
+
66
+ if (autoDesignSystem) {
67
+ contextInstructions = `
68
+ ## DESIGN SYSTEM COMPLET (COPIER EXACTEMENT - TOUT LE CODE):
69
+
70
+ ${autoDesignSystem}
71
+
72
+ ---
73
+ RÈGLE CRITIQUE: Copier EXACTEMENT les classes Tailwind, couleurs, spacing, border-radius du code ci-dessus.
74
+ NE JAMAIS inventer de nouvelles valeurs. Le nouveau composant doit ressembler EXACTEMENT au design system.
75
+ `;
76
+ designSystemRules = DESIGN_SYSTEM_USAGE_INSTRUCTIONS;
77
+ } else if (context && context !== "null" && context.trim() !== "") {
57
78
  contextInstructions = `
58
79
  EXISTING PROJECT CONTEXT (match this design system):
59
80
  ${context}
@@ -66,19 +87,30 @@ IMPORTANT: Analyze the existing code carefully and match:
66
87
  - Import patterns and file structure
67
88
  `;
68
89
  }
69
- // Add design system generation instructions if requested
70
- let designSystemGenerationInstructions = '';
90
+ // Build the system prompt - design system generation instructions go FIRST if enabled
91
+ let systemPrompt;
71
92
  if (generateDesignSystem) {
72
- designSystemGenerationInstructions = DESIGN_SYSTEM_GENERATION_PROMPT;
73
- }
74
- const systemPrompt = `${CREATE_FRONTEND_PROMPT}
93
+ systemPrompt = `${DESIGN_SYSTEM_GENERATION_PROMPT}
94
+
95
+ ---
96
+
97
+ ${CREATE_FRONTEND_PROMPT}
98
+ ${designSystemInstructions}
99
+ ${contextInstructions}
100
+ TECH STACK: ${techStack}
101
+ FILE PATH: ${filePath}
102
+
103
+ 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();
104
+ } else {
105
+ systemPrompt = `${CREATE_FRONTEND_PROMPT}
106
+ ${designSystemRules}
75
107
  ${designSystemInstructions}
76
108
  ${contextInstructions}
77
- ${designSystemGenerationInstructions}
78
109
  TECH STACK: ${techStack}
79
110
  FILE PATH: ${filePath}
80
111
 
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();
112
+ Remember: Return a COMPLETE file ready to save at ${filePath}`.trim();
113
+ }
82
114
  const rawResult = await generateWithGemini(systemPrompt, request, undefined, "high", "create_frontend");
83
115
  // Handle design system generation mode
84
116
  if (generateDesignSystem) {
@@ -1,42 +1,23 @@
1
1
  import { z } from "zod";
2
2
  import { generateWithGemini } from "../lib/gemini.js";
3
+ import { GENERATE_VIBES_PAGE_PROMPT } from "../prompts/system.js";
4
+ import { stripCodeFences } from "../lib/filesystem.js";
5
+
3
6
  export const generateVibesSchema = {
4
- projectDescription: z.string().describe("Brief description of the project. " +
5
- "Example: 'A SaaS dashboard for managing customer support tickets'"),
6
- projectType: z.string().optional().describe("Type of project. " +
7
- "Examples: 'landing page', 'dashboard', 'e-commerce', 'portfolio', 'blog', 'mobile app'"),
8
- targetAudience: z.string().optional().describe("Who will use this app. " +
9
- "Examples: 'developers', 'enterprise clients', 'young consumers', 'creative professionals'"),
7
+ projectDescription: z.string().describe("Description du projet. " +
8
+ "Exemple: 'Un dashboard SaaS pour gérer les tickets de support client'"),
9
+ projectType: z.string().optional().describe("Type de projet. " +
10
+ "Exemples: 'landing page', 'dashboard', 'e-commerce', 'portfolio', 'blog', 'mobile app'"),
11
+ targetAudience: z.string().optional().describe("Audience cible. " +
12
+ "Exemples: 'developers', 'enterprise clients', 'young consumers', 'creative professionals'"),
13
+ techStack: z.string().optional().describe("Tech stack pour la page de vibes. " +
14
+ "Default: 'React + TypeScript + Tailwind CSS'. " +
15
+ "Exemples: 'Next.js + Tailwind', 'Vue 3 + Tailwind', 'HTML + Tailwind'"),
10
16
  };
11
- const GENERATE_VIBES_PROMPT = `Generate 5 distinct mood/atmosphere options (VIBES) that match different interpretations of the project.
12
-
13
- Each vibe should represent a unique visual direction and feeling.
14
- Describe the mood, not specific colors - let the designer interpret creatively.
15
- Think: "Corporate & Trustworthy" vs "Playful & Vibrant" vs "Dark & Techy"
16
-
17
- IMPORTANT - Each vibe MUST include a SCALE recommendation:
18
- - "zoomed" = Large elements, big buttons, big text, full-width cards (e.g., kids apps, accessibility-focused)
19
- - "refined" = Subtle scale, smaller typography, contained elements, elegant proportions (e.g., luxury, Linear.app, Raycast)
20
- - "balanced" = Standard scale, middle ground
21
-
22
- The scale is NOT about density (dense vs sparse), it's about the SIZE of elements.
23
- A luxury watch e-commerce site has refined/small scale. A kids learning platform has zoomed/large scale.
24
-
25
- OUTPUT FORMAT (JSON):
26
- Return ONLY a valid JSON array with exactly 5 vibes. No markdown, no explanation.
27
-
28
- [
29
- {
30
- "emoji": "🏛️",
31
- "name": "Vibe Name",
32
- "description": "2-3 sentences describing the mood and atmosphere.",
33
- "scale": "refined" | "balanced" | "zoomed",
34
- "keywords": ["keyword1", "keyword2", "keyword3"]
35
- }
36
- ]`;
17
+
37
18
  export async function generateVibes(params) {
38
- const { projectDescription, projectType, targetAudience } = params;
39
- // Build context for Gemini
19
+ const { projectDescription, projectType, targetAudience, techStack } = params;
20
+
40
21
  let contextParts = [`Project: ${projectDescription}`];
41
22
  if (projectType) {
42
23
  contextParts.push(`Type: ${projectType}`);
@@ -44,57 +25,59 @@ export async function generateVibes(params) {
44
25
  if (targetAudience) {
45
26
  contextParts.push(`Target Audience: ${targetAudience}`);
46
27
  }
47
- const userPrompt = contextParts.join("\n");
48
- const result = await generateWithGemini(GENERATE_VIBES_PROMPT, userPrompt, undefined, // default model
49
- "high", // high thinking for creative vibes
50
- "generate_vibes");
51
- // Parse the JSON response
52
- try {
53
- // Clean the response (remove potential markdown code blocks)
54
- let cleanedResult = result.trim();
55
- if (cleanedResult.startsWith("```json")) {
56
- cleanedResult = cleanedResult.slice(7);
57
- }
58
- if (cleanedResult.startsWith("```")) {
59
- cleanedResult = cleanedResult.slice(3);
60
- }
61
- if (cleanedResult.endsWith("```")) {
62
- cleanedResult = cleanedResult.slice(0, -3);
63
- }
64
- cleanedResult = cleanedResult.trim();
65
- const vibes = JSON.parse(cleanedResult);
66
- // Format vibes for display
67
- const scaleLabels = {
68
- refined: "🔍 Refined (small, elegant)",
69
- balanced: "⚖️ Balanced (standard)",
70
- zoomed: "🔎 Zoomed (large elements)",
71
- };
72
- const formattedVibes = vibes.map((vibe, index) => {
73
- const scaleDisplay = scaleLabels[vibe.scale] || vibe.scale;
74
- return `${index + 1}. ${vibe.emoji} "${vibe.name}"
75
- ${vibe.description}
76
- ${scaleDisplay}`;
77
- }).join("\n\n");
78
- return {
79
- content: [
80
- {
81
- type: "text",
82
- text: `Here are 5 design vibes for your project:\n\n${formattedVibes}\n\n---\n\nAsk the user to select one vibe. Pass the selection to create_frontend via designSystem.vibe with: name, description, scale, keywords.`,
83
- },
84
- ],
85
- // Also return structured data for programmatic use
86
- vibes,
87
- };
88
- }
89
- catch {
90
- // If parsing fails, return raw result
91
- return {
92
- content: [
93
- {
94
- type: "text",
95
- text: `Generated vibes:\n\n${result}\n\n---\n\nNote: Could not parse as JSON. Please extract the vibes manually.`,
96
- },
97
- ],
98
- };
99
- }
28
+
29
+ const userPrompt = `${contextParts.join("\n")}
30
+ Tech Stack: ${techStack || "React + TypeScript + Tailwind CSS"}
31
+
32
+ Génère 5 vibes DIFFÉRENTES et ADAPTÉES à ce projet spécifique.
33
+ Puis génère la page complète avec 5 sections, une pour chaque vibe.
34
+ Chaque section doit montrer visuellement le style de la vibe.`;
35
+
36
+ const result = await generateWithGemini(
37
+ GENERATE_VIBES_PAGE_PROMPT,
38
+ userPrompt,
39
+ undefined,
40
+ "high",
41
+ "generate_vibes"
42
+ );
43
+
44
+ const code = stripCodeFences(result);
45
+
46
+ return {
47
+ content: [{
48
+ type: "text",
49
+ text: `VIBES_PAGE_CODE:
50
+
51
+ ${code}
52
+
53
+ ---
54
+
55
+ INSTRUCTIONS POUR L'AGENT:
56
+ 1. Demande à l'utilisateur: "Tu n'as pas de design system. Je peux créer vibes-selection.tsx pour que tu choisisses visuellement ton style préféré?"
57
+ 2. Si oui → Écris ce code dans le fichier (vibes-selection.tsx ou vibes-selection.html selon le projet)
58
+ 3. Dis à l'utilisateur d'ouvrir la page et de choisir (ex: "vibe 3" ou "la deuxième")
59
+ 4. Quand l'utilisateur a choisi, extrais le code entre <!-- VIBE_X_START --> et <!-- VIBE_X_END -->
60
+ 5. Sauvegarde CE CODE ENTIER (pas un résumé) dans design-system.md à la racine du projet
61
+ 6. Demande si tu dois supprimer vibes-selection.tsx
62
+
63
+ FORMAT DU design-system.md:
64
+ \`\`\`markdown
65
+ # Design System - [Nom du Projet]
66
+
67
+ ## Vibe Sélectionnée: [Nom de la vibe choisie]
68
+
69
+ ## Code de Référence (COPIER EXACTEMENT)
70
+
71
+ [Coller ici TOUT le code extrait entre les markers VIBE_X_START et VIBE_X_END]
72
+
73
+ ## Instructions d'utilisation
74
+
75
+ Pour tous les composants frontend:
76
+ - Copier EXACTEMENT les classes Tailwind de ce code de référence
77
+ - Utiliser les mêmes couleurs, spacing, border-radius
78
+ - Maintenir la même direction esthétique
79
+ \`\`\`
80
+ `
81
+ }]
82
+ };
100
83
  }
@@ -31,12 +31,18 @@ export async function modifyFrontend(params) {
31
31
  let contextInstructions = '';
32
32
  if (autoDesignSystem) {
33
33
  contextInstructions = `
34
- ## Design System (OBLIGATOIRE - copier exactement les classes)
34
+ ## DESIGN SYSTEM COMPLET (COPIER EXACTEMENT - NE RIEN MODIFIER):
35
35
 
36
36
  ${autoDesignSystem}
37
37
 
38
38
  ---
39
39
 
40
+ RÈGLES CRITIQUES:
41
+ - Copier EXACTEMENT les classes Tailwind du design system ci-dessus
42
+ - NE JAMAIS inventer de nouvelles couleurs, paddings, ou border-radius
43
+ - Utiliser les mêmes patterns visuels (shadows, transitions, etc.)
44
+ - Le code modifié doit être INDISTINGUABLE du reste du projet
45
+
40
46
  `;
41
47
  }
42
48
  if (context) {
@@ -34,12 +34,18 @@ export async function snippetFrontend(params) {
34
34
  let contextInstructions = '';
35
35
  if (autoDesignSystem) {
36
36
  contextInstructions = `
37
- ## Design System (OBLIGATOIRE - copier exactement les classes)
37
+ ## DESIGN SYSTEM COMPLET (COPIER EXACTEMENT - NE RIEN MODIFIER):
38
38
 
39
39
  ${autoDesignSystem}
40
40
 
41
41
  ---
42
42
 
43
+ RÈGLES CRITIQUES:
44
+ - Copier EXACTEMENT les classes Tailwind du design system ci-dessus
45
+ - NE JAMAIS inventer de nouvelles couleurs, paddings, ou border-radius
46
+ - Utiliser les mêmes patterns visuels (shadows, transitions, etc.)
47
+ - Le snippet doit être INDISTINGUABLE du reste du projet
48
+
43
49
  `;
44
50
  }
45
51
  if (context) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemini-design-mcp",
3
- "version": "3.12.0",
3
+ "version": "3.12.2",
4
4
  "description": "MCP server that uses Gemini 3 Pro for frontend/design code generation",
5
5
  "main": "build/index.js",
6
6
  "bin": {