gemini-design-mcp 3.12.1 → 3.12.3

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.
@@ -613,6 +613,64 @@ Si un design system est fourni dans le context, tu DOIS :
613
613
  - Si un élément n'existe pas dans le design system, le créer en utilisant UNIQUEMENT les tokens définis
614
614
  `;
615
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
+
616
674
  export const SNIPPET_FRONTEND_PROMPT = `You are an elite UI/UX Designer generating a code snippet to INSERT.
617
675
 
618
676
  YOUR TASK: Generate a focused code snippet that will be INSERTED into an existing file.
@@ -2,7 +2,6 @@ import { z } from "zod";
2
2
  import { type Scale } from "../lib/scale.js";
3
3
  export declare const createFrontendSchema: {
4
4
  request: z.ZodString;
5
- filePath: z.ZodString;
6
5
  techStack: z.ZodString;
7
6
  context: z.ZodOptional<z.ZodString>;
8
7
  designSystem: z.ZodOptional<z.ZodObject<{
@@ -41,7 +40,6 @@ export declare const createFrontendSchema: {
41
40
  };
42
41
  export declare function createFrontend(params: {
43
42
  request: string;
44
- filePath: string;
45
43
  techStack: string;
46
44
  context?: string;
47
45
  designSystem?: {
@@ -1,14 +1,12 @@
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. " +
8
8
  "Be specific about functionality and content. " +
9
9
  "Example: 'A pricing page with 3 tiers (Basic, Pro, Enterprise) with feature comparison table'"),
10
- filePath: z.string().describe("The path where this file will be created. " +
11
- "Example: 'src/components/PricingPage.tsx' or 'app/dashboard/page.tsx'"),
12
10
  techStack: z.string().describe("The tech stack to use. Be specific. " +
13
11
  "Examples: 'React + TypeScript + Tailwind CSS', 'Next.js 14 App Router + shadcn/ui', 'Vue 3 + Composition API + CSS Modules'"),
14
12
  context: z.string().optional().describe("CRITICAL FOR EXISTING PROJECTS: Pass the styling files (CSS, SCSS, theme config, etc.). " +
@@ -29,9 +27,17 @@ export const createFrontendSchema = {
29
27
  "Activer UNIQUEMENT pour la PREMIÈRE page du projet. " +
30
28
  "Le design system sera retourné séparément pour être sauvegardé dans design-system.md"
31
29
  ),
30
+ projectRoot: z.string().optional().describe(
31
+ "Root directory du projet. Utilisé pour auto-charger design-system.md s'il existe. " +
32
+ "TOUJOURS passer ce paramètre pour que Gemini utilise le design system existant."
33
+ ),
32
34
  };
33
35
  export async function createFrontend(params) {
34
- const { request, filePath, techStack, context, designSystem, generateDesignSystem } = params;
36
+ const { request, techStack, context, designSystem, generateDesignSystem, projectRoot } = params;
37
+
38
+ // Auto-load design system if exists
39
+ const autoDesignSystem = loadDesignSystemIfExists(projectRoot);
40
+
35
41
  // Build design system instructions if provided
36
42
  let designSystemInstructions = '';
37
43
  if (designSystem?.vibe) {
@@ -51,9 +57,22 @@ Interpret this vibe creatively — choose colors, typography, and styling that e
51
57
  The scale above is MANDATORY and defines how large or small UI elements should be.
52
58
  `;
53
59
  }
54
- // Build context instructions (ignore empty strings and "null" strings)
60
+ // Build context instructions - prioritize auto-loaded design system
55
61
  let contextInstructions = '';
56
- if (context && context !== "null" && context.trim() !== "") {
62
+ let designSystemRules = '';
63
+
64
+ if (autoDesignSystem) {
65
+ contextInstructions = `
66
+ ## DESIGN SYSTEM COMPLET (COPIER EXACTEMENT - TOUT LE CODE):
67
+
68
+ ${autoDesignSystem}
69
+
70
+ ---
71
+ RÈGLE CRITIQUE: Copier EXACTEMENT les classes Tailwind, couleurs, spacing, border-radius du code ci-dessus.
72
+ NE JAMAIS inventer de nouvelles valeurs. Le nouveau composant doit ressembler EXACTEMENT au design system.
73
+ `;
74
+ designSystemRules = DESIGN_SYSTEM_USAGE_INSTRUCTIONS;
75
+ } else if (context && context !== "null" && context.trim() !== "") {
57
76
  contextInstructions = `
58
77
  EXISTING PROJECT CONTEXT (match this design system):
59
78
  ${context}
@@ -77,17 +96,16 @@ ${CREATE_FRONTEND_PROMPT}
77
96
  ${designSystemInstructions}
78
97
  ${contextInstructions}
79
98
  TECH STACK: ${techStack}
80
- FILE PATH: ${filePath}
81
99
 
82
100
  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
101
  } else {
84
102
  systemPrompt = `${CREATE_FRONTEND_PROMPT}
103
+ ${designSystemRules}
85
104
  ${designSystemInstructions}
86
105
  ${contextInstructions}
87
106
  TECH STACK: ${techStack}
88
- FILE PATH: ${filePath}
89
107
 
90
- Remember: Return a COMPLETE file ready to save at ${filePath}`.trim();
108
+ Remember: Return a COMPLETE, functional file ready to use.`.trim();
91
109
  }
92
110
  const rawResult = await generateWithGemini(systemPrompt, request, undefined, "high", "create_frontend");
93
111
  // Handle design system generation mode
@@ -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
  }
@@ -3,7 +3,6 @@ import { type Scale } from "../lib/scale.js";
3
3
  export declare const modifyFrontendSchema: {
4
4
  modification: z.ZodString;
5
5
  targetCode: z.ZodString;
6
- filePath: z.ZodString;
7
6
  context: z.ZodOptional<z.ZodString>;
8
7
  scale: z.ZodOptional<z.ZodEnum<["refined", "balanced", "zoomed"]>>;
9
8
  writeFile: z.ZodDefault<z.ZodBoolean>;
@@ -11,7 +10,6 @@ export declare const modifyFrontendSchema: {
11
10
  export declare function modifyFrontend(params: {
12
11
  modification: string;
13
12
  targetCode: string;
14
- filePath: string;
15
13
  context?: string;
16
14
  scale?: Scale;
17
15
  writeFile?: boolean;
@@ -12,8 +12,6 @@ export const modifyFrontendSchema = {
12
12
  targetCode: z.string().describe("The specific code section to modify (NOT the full file). " +
13
13
  "Pass only the relevant component/element that needs redesigning. " +
14
14
  "This helps Gemini focus on exactly what to change."),
15
- filePath: z.string().describe("The path of the file being modified. " +
16
- "Example: 'src/components/Sidebar.tsx'"),
17
15
  context: z.string().optional().describe("CRITICAL: Pass the styling files (CSS, SCSS, theme config, etc.) with design tokens. " +
18
16
  "Include: variables, tokens, classes from your project. " +
19
17
  "Without this, Gemini may introduce styles that don't match your design system. " +
@@ -24,19 +22,25 @@ export const modifyFrontendSchema = {
24
22
  "If not provided, uses current working directory."),
25
23
  };
26
24
  export async function modifyFrontend(params) {
27
- const { modification, targetCode, filePath, context, scale, projectRoot } = params;
25
+ const { modification, targetCode, context, scale, projectRoot } = params;
28
26
  // Auto-load design system if exists
29
27
  const autoDesignSystem = loadDesignSystemIfExists(projectRoot);
30
28
  // Build context instructions with design system merged
31
29
  let contextInstructions = '';
32
30
  if (autoDesignSystem) {
33
31
  contextInstructions = `
34
- ## Design System (OBLIGATOIRE - copier exactement les classes)
32
+ ## DESIGN SYSTEM COMPLET (COPIER EXACTEMENT - NE RIEN MODIFIER):
35
33
 
36
34
  ${autoDesignSystem}
37
35
 
38
36
  ---
39
37
 
38
+ RÈGLES CRITIQUES:
39
+ - Copier EXACTEMENT les classes Tailwind du design system ci-dessus
40
+ - NE JAMAIS inventer de nouvelles couleurs, paddings, ou border-radius
41
+ - Utiliser les mêmes patterns visuels (shadows, transitions, etc.)
42
+ - Le code modifié doit être INDISTINGUABLE du reste du projet
43
+
40
44
  `;
41
45
  }
42
46
  if (context) {
@@ -53,8 +57,6 @@ ${context}
53
57
  ${designSystemRules}
54
58
  ${scaleInstructions}
55
59
  ${contextInstructions}
56
- FILE: ${filePath}
57
-
58
60
  CODE TO MODIFY:
59
61
  \`\`\`
60
62
  ${targetCode}
@@ -2,7 +2,6 @@ import { z } from "zod";
2
2
  import { type Scale } from "../lib/scale.js";
3
3
  export declare const snippetFrontendSchema: {
4
4
  request: z.ZodString;
5
- targetFile: z.ZodString;
6
5
  techStack: z.ZodString;
7
6
  insertionContext: z.ZodString;
8
7
  context: z.ZodOptional<z.ZodString>;
@@ -13,7 +12,6 @@ export declare const snippetFrontendSchema: {
13
12
  };
14
13
  export declare function snippetFrontend(params: {
15
14
  request: string;
16
- targetFile: string;
17
15
  techStack: string;
18
16
  insertionContext: string;
19
17
  context?: string;
@@ -10,8 +10,6 @@ export const snippetFrontendSchema = {
10
10
  "'A data table with sorting, filtering, and pagination', " +
11
11
  "'A form validation function for email and password', " +
12
12
  "'A custom hook for handling API requests with loading/error states'"),
13
- targetFile: z.string().describe("The file where this snippet will be inserted. " +
14
- "Example: 'src/components/Dashboard.tsx' - helps Gemini match the file's patterns"),
15
13
  techStack: z.string().describe("The tech stack being used. " +
16
14
  "Examples: 'React + TypeScript + Tailwind CSS', 'Vue 3 + Composition API'"),
17
15
  insertionContext: z.string().describe("WHERE in the file this snippet will go AND the design tokens to use. " +
@@ -27,19 +25,25 @@ export const snippetFrontendSchema = {
27
25
  "If not provided, uses current working directory."),
28
26
  };
29
27
  export async function snippetFrontend(params) {
30
- const { request, targetFile, techStack, insertionContext, context, scale, projectRoot } = params;
28
+ const { request, techStack, insertionContext, context, scale, projectRoot } = params;
31
29
  // Auto-load design system if exists
32
30
  const autoDesignSystem = loadDesignSystemIfExists(projectRoot);
33
31
  // Build context instructions with design system merged
34
32
  let contextInstructions = '';
35
33
  if (autoDesignSystem) {
36
34
  contextInstructions = `
37
- ## Design System (OBLIGATOIRE - copier exactement les classes)
35
+ ## DESIGN SYSTEM COMPLET (COPIER EXACTEMENT - NE RIEN MODIFIER):
38
36
 
39
37
  ${autoDesignSystem}
40
38
 
41
39
  ---
42
40
 
41
+ RÈGLES CRITIQUES:
42
+ - Copier EXACTEMENT les classes Tailwind du design system ci-dessus
43
+ - NE JAMAIS inventer de nouvelles couleurs, paddings, ou border-radius
44
+ - Utiliser les mêmes patterns visuels (shadows, transitions, etc.)
45
+ - Le snippet doit être INDISTINGUABLE du reste du projet
46
+
43
47
  `;
44
48
  }
45
49
  if (context) {
@@ -57,7 +61,6 @@ ${designSystemRules}
57
61
  ${scaleInstructions}
58
62
  ${contextInstructions}
59
63
  TECH STACK: ${techStack}
60
- TARGET FILE: ${targetFile}
61
64
 
62
65
  INSERTION CONTEXT:
63
66
  ${insertionContext}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemini-design-mcp",
3
- "version": "3.12.1",
3
+ "version": "3.12.3",
4
4
  "description": "MCP server that uses Gemini 3 Pro for frontend/design code generation",
5
5
  "main": "build/index.js",
6
6
  "bin": {