gemini-design-mcp 3.9.0 → 3.10.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.
- package/build/index.js +163 -45
- package/build/prompts/system.js +285 -55
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import {
|
|
4
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
5
|
+
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
5
6
|
import express from "express";
|
|
6
7
|
import cors from "cors";
|
|
8
|
+
import { randomUUID } from "crypto";
|
|
7
9
|
import { createFrontendSchema, createFrontend } from "./tools/create-frontend.js";
|
|
8
10
|
import { modifyFrontendSchema, modifyFrontend } from "./tools/modify-frontend.js";
|
|
9
11
|
import { snippetFrontendSchema, snippetFrontend } from "./tools/snippet-frontend.js";
|
|
10
12
|
import { generateVibesSchema, generateVibes } from "./tools/generate-vibes.js";
|
|
11
|
-
|
|
12
|
-
const server = new McpServer({
|
|
13
|
-
name: "gemini-design-mcp",
|
|
14
|
-
version: "3.9.0",
|
|
15
|
-
});
|
|
13
|
+
|
|
16
14
|
// =============================================================================
|
|
17
|
-
//
|
|
15
|
+
// HELPER: Create and configure MCP server with all tools
|
|
18
16
|
// =============================================================================
|
|
19
|
-
|
|
17
|
+
function createMcpServer() {
|
|
18
|
+
const server = new McpServer({
|
|
19
|
+
name: "gemini-design-mcp",
|
|
20
|
+
version: "3.10.0",
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// TOOL 1: CREATE_FRONTEND
|
|
24
|
+
server.tool("create_frontend", `Create a NEW, complete frontend file with PREMIUM DESIGN quality.
|
|
20
25
|
|
|
21
26
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
22
27
|
🎯 WHEN TO USE THIS TOOL
|
|
@@ -63,10 +68,9 @@ Present options to user, they select one, then pass it here via designSystem.vib
|
|
|
63
68
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
64
69
|
|
|
65
70
|
Returns the complete code. YOU (the agent) are responsible for writing it to disk.`, createFrontendSchema, createFrontend);
|
|
66
|
-
|
|
67
|
-
// TOOL 2: MODIFY_FRONTEND
|
|
68
|
-
|
|
69
|
-
server.tool("modify_frontend", `Redesign a SINGLE UI element. Returns ONLY the changed code (find/replace format).
|
|
71
|
+
|
|
72
|
+
// TOOL 2: MODIFY_FRONTEND
|
|
73
|
+
server.tool("modify_frontend", `Redesign a SINGLE UI element. Returns ONLY the changed code (find/replace format).
|
|
70
74
|
|
|
71
75
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
72
76
|
⚠️ CRITICAL: ONE MODIFICATION PER CALL
|
|
@@ -116,10 +120,9 @@ import { X } from "y";
|
|
|
116
120
|
<new redesigned code>
|
|
117
121
|
|
|
118
122
|
YOU (the agent) are responsible for applying this find/replace to the file.`, modifyFrontendSchema, modifyFrontend);
|
|
119
|
-
|
|
120
|
-
// TOOL 3: SNIPPET_FRONTEND
|
|
121
|
-
|
|
122
|
-
server.tool("snippet_frontend", `Generate the JSX/HTML for a NEW UI component to INSERT into an existing file.
|
|
123
|
+
|
|
124
|
+
// TOOL 3: SNIPPET_FRONTEND
|
|
125
|
+
server.tool("snippet_frontend", `Generate the JSX/HTML for a NEW UI component to INSERT into an existing file.
|
|
123
126
|
|
|
124
127
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
125
128
|
⚠️ CRITICAL: SEPARATION OF CONCERNS
|
|
@@ -240,10 +243,9 @@ import { Search } from "lucide-react";
|
|
|
240
243
|
YOU (the agent) are responsible for:
|
|
241
244
|
- Adding the logic (useState, handlers) BEFORE calling this tool
|
|
242
245
|
- Inserting the returned snippet into the correct location in the file`, snippetFrontendSchema, snippetFrontend);
|
|
243
|
-
|
|
244
|
-
// TOOL 4: GENERATE_VIBES
|
|
245
|
-
|
|
246
|
-
server.tool("generate_vibes", `Generate 5 unique design vibes for a new project using Gemini AI.
|
|
246
|
+
|
|
247
|
+
// TOOL 4: GENERATE_VIBES
|
|
248
|
+
server.tool("generate_vibes", `Generate 5 unique design vibes for a new project using Gemini AI.
|
|
247
249
|
|
|
248
250
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
249
251
|
🎯 WHEN TO USE THIS TOOL
|
|
@@ -278,97 +280,213 @@ Example vibe:
|
|
|
278
280
|
🏛️ "Pristine Museum"
|
|
279
281
|
An ultra-clean, 'white-cube' aesthetic focused on vast negative space.
|
|
280
282
|
Keywords: minimal, whitespace, gallery, clean, sophisticated`, generateVibesSchema, generateVibes);
|
|
283
|
+
|
|
284
|
+
return server;
|
|
285
|
+
}
|
|
286
|
+
|
|
281
287
|
// =============================================================================
|
|
282
288
|
// START SERVER
|
|
283
289
|
// =============================================================================
|
|
284
290
|
async function main() {
|
|
285
291
|
const transportType = process.env.TRANSPORT || "stdio";
|
|
286
292
|
|
|
287
|
-
if (transportType === "
|
|
288
|
-
//
|
|
293
|
+
if (transportType === "http" || transportType === "streamable-http") {
|
|
294
|
+
// Streamable HTTP mode (NEW - recommended for remote connections)
|
|
289
295
|
const app = express();
|
|
290
296
|
|
|
291
297
|
app.use(cors({
|
|
292
298
|
origin: "*",
|
|
293
|
-
methods: ["GET", "POST", "OPTIONS"],
|
|
299
|
+
methods: ["GET", "POST", "DELETE", "OPTIONS"],
|
|
294
300
|
allowedHeaders: ["Content-Type", "Authorization", "mcp-session-id"],
|
|
301
|
+
exposedHeaders: ["mcp-session-id"],
|
|
295
302
|
credentials: true,
|
|
296
303
|
}));
|
|
297
304
|
app.use(express.json());
|
|
298
305
|
|
|
299
|
-
// Store active transports by session
|
|
306
|
+
// Store active transports and servers by session
|
|
300
307
|
const transports = new Map();
|
|
308
|
+
const servers = new Map();
|
|
301
309
|
|
|
302
310
|
// Health check endpoint
|
|
303
311
|
app.get("/health", (req, res) => {
|
|
304
312
|
res.json({
|
|
305
313
|
status: "ok",
|
|
306
314
|
service: "gemini-design-mcp",
|
|
307
|
-
version: "3.
|
|
308
|
-
transport: "
|
|
315
|
+
version: "3.10.0",
|
|
316
|
+
transport: "streamable-http",
|
|
309
317
|
timestamp: Date.now(),
|
|
310
318
|
});
|
|
311
319
|
});
|
|
312
320
|
|
|
313
|
-
//
|
|
321
|
+
// Main MCP endpoint - handles all communication
|
|
322
|
+
app.post("/mcp", async (req, res) => {
|
|
323
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
324
|
+
let transport = sessionId ? transports.get(sessionId) : undefined;
|
|
325
|
+
|
|
326
|
+
if (transport) {
|
|
327
|
+
// Existing session - reuse transport
|
|
328
|
+
console.log(`[MCP] Reusing session: ${sessionId}`);
|
|
329
|
+
await transport.handleRequest(req, res, req.body);
|
|
330
|
+
} else if (!sessionId && isInitializeRequest(req.body)) {
|
|
331
|
+
// New session - create transport and server
|
|
332
|
+
console.log("[MCP] New session initialization");
|
|
333
|
+
|
|
334
|
+
// Extract API key from Authorization header
|
|
335
|
+
const authHeader = req.headers.authorization;
|
|
336
|
+
const apiKey = authHeader?.replace("Bearer ", "");
|
|
337
|
+
|
|
338
|
+
if (apiKey && (apiKey.startsWith("gd_") || apiKey.startsWith("AIza"))) {
|
|
339
|
+
process.env.API_KEY = apiKey;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const newTransport = new StreamableHTTPServerTransport({
|
|
343
|
+
sessionIdGenerator: () => randomUUID(),
|
|
344
|
+
onsessioninitialized: (sid) => {
|
|
345
|
+
transports.set(sid, newTransport);
|
|
346
|
+
console.log(`[MCP] Session initialized: ${sid}`);
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
// Clean up on close
|
|
351
|
+
newTransport.onclose = () => {
|
|
352
|
+
if (newTransport.sessionId) {
|
|
353
|
+
console.log(`[MCP] Session closed: ${newTransport.sessionId}`);
|
|
354
|
+
transports.delete(newTransport.sessionId);
|
|
355
|
+
servers.delete(newTransport.sessionId);
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
// Create new server instance for this session
|
|
360
|
+
const server = createMcpServer();
|
|
361
|
+
servers.set(newTransport.sessionId, server);
|
|
362
|
+
|
|
363
|
+
// Connect server to transport
|
|
364
|
+
await server.connect(newTransport);
|
|
365
|
+
|
|
366
|
+
// Handle the initialization request
|
|
367
|
+
await newTransport.handleRequest(req, res, req.body);
|
|
368
|
+
} else {
|
|
369
|
+
// Invalid request
|
|
370
|
+
console.warn("[MCP] Bad request - no session ID or not an init request");
|
|
371
|
+
res.status(400).json({
|
|
372
|
+
error: "Bad Request: No valid session ID provided and not an initialization request",
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// GET for server-to-client streaming (optional, for long-running operations)
|
|
378
|
+
app.get("/mcp", async (req, res) => {
|
|
379
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
380
|
+
const transport = sessionId ? transports.get(sessionId) : undefined;
|
|
381
|
+
|
|
382
|
+
if (!transport) {
|
|
383
|
+
return res.status(404).json({ error: "Session not found" });
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
await transport.handleRequest(req, res);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// DELETE for explicit session termination
|
|
390
|
+
app.delete("/mcp", async (req, res) => {
|
|
391
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
392
|
+
const transport = sessionId ? transports.get(sessionId) : undefined;
|
|
393
|
+
|
|
394
|
+
if (!transport) {
|
|
395
|
+
return res.status(404).json({ error: "Session not found" });
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
await transport.handleRequest(req, res);
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// =========================================================================
|
|
402
|
+
// LEGACY SSE ENDPOINTS (for backwards compatibility with mcp-remote)
|
|
403
|
+
// =========================================================================
|
|
404
|
+
// Keep SSE support for clients that haven't migrated yet
|
|
405
|
+
const { SSEServerTransport } = await import("@modelcontextprotocol/sdk/server/sse.js");
|
|
406
|
+
const sseTransports = new Map();
|
|
407
|
+
|
|
314
408
|
app.get("/sse", async (req, res) => {
|
|
315
409
|
const authHeader = req.headers.authorization;
|
|
316
410
|
const apiKey = authHeader?.replace("Bearer ", "");
|
|
317
411
|
|
|
318
|
-
// Accept both platform keys (gd_) and Google API keys (AIza)
|
|
319
412
|
const isValidKey = apiKey && (apiKey.startsWith("gd_") || apiKey.startsWith("AIza"));
|
|
320
413
|
if (!isValidKey) {
|
|
321
414
|
return res.status(401).json({
|
|
322
|
-
error: "Missing or invalid API key. Use Authorization: Bearer <key
|
|
323
|
-
"Accepted formats: gd_xxx (platform) or AIza... (Google API key)",
|
|
415
|
+
error: "Missing or invalid API key. Use Authorization: Bearer <key>",
|
|
324
416
|
});
|
|
325
417
|
}
|
|
326
418
|
|
|
327
|
-
// Set API_KEY env var for this request (tools read from process.env)
|
|
328
419
|
process.env.API_KEY = apiKey;
|
|
329
420
|
|
|
330
|
-
// Create SSE transport
|
|
331
421
|
const transport = new SSEServerTransport("/messages", res);
|
|
332
|
-
const sessionId =
|
|
333
|
-
|
|
422
|
+
const sessionId = transport.sessionId;
|
|
423
|
+
sseTransports.set(sessionId, transport);
|
|
334
424
|
|
|
335
|
-
// Send session ID to client
|
|
336
425
|
res.setHeader("mcp-session-id", sessionId);
|
|
337
426
|
|
|
338
|
-
// Clean up on disconnect
|
|
339
427
|
res.on("close", () => {
|
|
340
|
-
|
|
428
|
+
console.log("[SSE] Connection closed for session:", sessionId);
|
|
429
|
+
sseTransports.delete(sessionId);
|
|
341
430
|
});
|
|
342
431
|
|
|
432
|
+
const server = createMcpServer();
|
|
343
433
|
await server.connect(transport);
|
|
434
|
+
|
|
435
|
+
// Keepalive every 5s
|
|
436
|
+
const keepAlive = setInterval(() => {
|
|
437
|
+
try {
|
|
438
|
+
res.write(":keepalive\n\n");
|
|
439
|
+
} catch {
|
|
440
|
+
// Ignore errors
|
|
441
|
+
}
|
|
442
|
+
}, 5000);
|
|
443
|
+
res.on("close", () => clearInterval(keepAlive));
|
|
344
444
|
});
|
|
345
445
|
|
|
346
|
-
// Messages endpoint - receives JSON-RPC from client
|
|
347
446
|
app.post("/messages", async (req, res) => {
|
|
348
|
-
const
|
|
349
|
-
const
|
|
447
|
+
const headerSession = req.headers["mcp-session-id"];
|
|
448
|
+
const headerSessionId = Array.isArray(headerSession) ? headerSession[0] : headerSession;
|
|
449
|
+
let sessionId = req.query.sessionId || headerSessionId;
|
|
450
|
+
let transport = sessionId ? sseTransports.get(sessionId) : undefined;
|
|
451
|
+
|
|
452
|
+
if (!transport && !sessionId && sseTransports.size === 1) {
|
|
453
|
+
const onlyEntry = sseTransports.entries().next().value;
|
|
454
|
+
if (onlyEntry) {
|
|
455
|
+
sessionId = onlyEntry[0];
|
|
456
|
+
transport = onlyEntry[1];
|
|
457
|
+
}
|
|
458
|
+
}
|
|
350
459
|
|
|
351
460
|
if (!transport) {
|
|
352
461
|
return res.status(400).json({ error: "Invalid or expired session" });
|
|
353
462
|
}
|
|
354
463
|
|
|
355
|
-
|
|
464
|
+
try {
|
|
465
|
+
await transport.handlePostMessage(req, res, req.body);
|
|
466
|
+
} catch (error) {
|
|
467
|
+
console.error("[SSE] Error handling message:", error);
|
|
468
|
+
if (!res.headersSent) {
|
|
469
|
+
res.status(400).json({ error: "Invalid message" });
|
|
470
|
+
}
|
|
471
|
+
}
|
|
356
472
|
});
|
|
357
473
|
|
|
358
474
|
const port = parseInt(process.env.PORT || "3000", 10);
|
|
359
475
|
app.listen(port, "0.0.0.0", () => {
|
|
360
|
-
console.log(`gemini-design-mcp v3.
|
|
361
|
-
console.log(`
|
|
362
|
-
console.log(`
|
|
476
|
+
console.log(`gemini-design-mcp v3.10.0 running on Streamable HTTP transport`);
|
|
477
|
+
console.log(` MCP endpoint: http://0.0.0.0:${port}/mcp`);
|
|
478
|
+
console.log(` Legacy SSE: http://0.0.0.0:${port}/sse`);
|
|
363
479
|
console.log(` Health check: http://0.0.0.0:${port}/health`);
|
|
364
480
|
});
|
|
365
481
|
} else {
|
|
366
482
|
// Stdio mode (default, for local IDE usage)
|
|
483
|
+
const server = createMcpServer();
|
|
367
484
|
const transport = new StdioServerTransport();
|
|
368
485
|
await server.connect(transport);
|
|
369
|
-
console.error("gemini-design-mcp v3.
|
|
486
|
+
console.error("gemini-design-mcp v3.10.0 running on stdio");
|
|
370
487
|
}
|
|
371
488
|
}
|
|
489
|
+
|
|
372
490
|
main().catch((error) => {
|
|
373
491
|
console.error("Fatal error:", error);
|
|
374
492
|
process.exit(1);
|
package/build/prompts/system.js
CHANGED
|
@@ -2,66 +2,296 @@
|
|
|
2
2
|
// CREATE_FRONTEND PROMPT
|
|
3
3
|
// Used for creating NEW complete files (pages, components, sections)
|
|
4
4
|
// =============================================================================
|
|
5
|
-
export const CREATE_FRONTEND_PROMPT =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
5
|
+
export const CREATE_FRONTEND_PROMPT = `# Frontend Design Skill - Enhanced Prompt
|
|
6
|
+
|
|
7
|
+
This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
|
8
|
+
|
|
9
|
+
The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Design Thinking
|
|
14
|
+
|
|
15
|
+
Before coding, understand the context and commit to a BOLD aesthetic direction:
|
|
16
|
+
|
|
17
|
+
**Purpose & Context**: What problem does this interface solve? Who uses it? Adapt the "volume" of creativity to the intent.
|
|
18
|
+
|
|
19
|
+
- **Trust Tier** (Banks, SaaS, Enterprise): Innovation lies in subtlety—perfect typography, "glass" materials, and silky smooth interactions.
|
|
20
|
+
- **Disrupt Tier** (Fashion, Portfolio, Event): Innovation lies in shock—brutalism, WebGL distortion, and aggressive layouts.
|
|
21
|
+
|
|
22
|
+
**Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian.
|
|
23
|
+
|
|
24
|
+
**Differentiation**: What makes this UNFORGETTABLE? Is it a physics-based interaction? A seamless video background? A shader effect?
|
|
25
|
+
|
|
26
|
+
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Aesthetic References (Non-Exhaustive Inspiration)
|
|
31
|
+
|
|
32
|
+
Sites to study for different vibes—don't copy, extract the *principle* that makes them work:
|
|
33
|
+
|
|
34
|
+
| Vibe | References |
|
|
35
|
+
|------|------------|
|
|
36
|
+
| **Liquid/Organic** | Linear.app, Stripe.com, Raycast.com |
|
|
37
|
+
| **Brutalist/Raw** | Balenciaga, Bloomberg Businessweek |
|
|
38
|
+
| **Editorial/Magazine** | Pudding.cool, The Outline (RIP), NYT Interactive |
|
|
39
|
+
| **3D/Immersive** | Apple product pages, Porsche.com, Rivian.com |
|
|
40
|
+
| **Retro-Web/Y2K** | Poolsuite.net, Superbad.com |
|
|
41
|
+
| **Neo-Corporate** | Vercel, Supabase, Planetscale, Railway.app |
|
|
42
|
+
| **Luxury/Fashion** | Bottega Veneta, Acne Studios, SSENSE |
|
|
43
|
+
| **Experimental** | Awwwards winners, Hoverstat.es, Brutalist Websites |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Frontend Aesthetics Guidelines
|
|
48
|
+
|
|
49
|
+
### 1. Visual Fidelity & Alchemy
|
|
50
|
+
|
|
51
|
+
Go beyond standard CSS. Layer lighting, depth, and texture to create objects that feel tactile.
|
|
52
|
+
|
|
53
|
+
**The "Hyper-Border"**: Instead of simple borders, consider mask-composite or pseudo-elements with conic-gradients to create flowing light. Use \`box-shadow: inset\` for inner glows that create depth (e.g., buttons that feel carved into the screen).
|
|
54
|
+
|
|
55
|
+
**Backgrounds & Atmosphere**: Create atmosphere rather than solid colors. Use gradient meshes, noise textures to prevent banding, geometric patterns, or layered transparencies.
|
|
56
|
+
|
|
57
|
+
**Cinematic Materials**: Treat video as a texture. Don't just embed a player; blend video footage using \`mix-blend-mode\`, mask it inside typography, or use it as a blurred atmospheric layer.
|
|
58
|
+
|
|
59
|
+
### 2. Motion & Physics
|
|
60
|
+
|
|
61
|
+
Motion should feel alive, not just "animated."
|
|
62
|
+
|
|
63
|
+
**Tools**: Prioritize CSS-only solutions for simple movement. For complex interactions, feel free to use libraries like Framer Motion, GSAP (ScrollTrigger), or Lenis (for smooth scrolling).
|
|
64
|
+
|
|
65
|
+
**Interaction**: Use magnetic buttons that track the cursor, scroll-linked animations (scrubbing), or parallax effects.
|
|
66
|
+
|
|
67
|
+
**The "Woah" Moment**: Focus on one high-impact centerpiece. A well-orchestrated hero section with staggered reveals is better than chaotic noise.
|
|
68
|
+
|
|
69
|
+
### 3. Advanced Tech (Optional)
|
|
70
|
+
|
|
71
|
+
If the aesthetic demands "God-tier" visuals (and performance permits), do not hesitate to suggest or implement:
|
|
72
|
+
|
|
73
|
+
- **WebGL / Shaders**: Use Three.js / React Three Fiber for liquid distortions, particle systems, or 3D displacement maps.
|
|
74
|
+
- **Canvas**: For fluid simulations or interactive grain.
|
|
75
|
+
|
|
76
|
+
### 4. Typography & Layout
|
|
77
|
+
|
|
78
|
+
**Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts (Arial, Inter). Pair a distinctive display font with a refined body font.
|
|
79
|
+
|
|
80
|
+
**Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Details That Elevate
|
|
85
|
+
|
|
86
|
+
Small touches that separate good from unforgettable:
|
|
87
|
+
|
|
88
|
+
- Custom cursor that reacts to context (pointer changes near interactive elements, grows on hover)
|
|
89
|
+
- Text that reveals on scroll with \`clip-path\` or mask
|
|
90
|
+
- Hover states that feel physical (\`scale(0.98)\` + shadow reduction = "pressed")
|
|
91
|
+
- Loading states that are actually delightful (skeleton with shimmer, not spinner)
|
|
92
|
+
- Scroll progress indicators (subtle bar, dot navigation, or percentage)
|
|
93
|
+
- Easter eggs (Konami code, hidden interactions, developer console messages)
|
|
94
|
+
- Sound design (subtle click/hover sounds for immersive experiences)
|
|
95
|
+
- View Transitions API for seamless page changes
|
|
96
|
+
- Staggered animations with variable delays (not uniform timing)
|
|
97
|
+
- "Breathing" elements (subtle scale oscillation on idle states)
|
|
98
|
+
- Focus states that are beautiful, not just functional
|
|
99
|
+
- Selection highlight with custom \`::selection\` colors
|
|
100
|
+
- Smooth scroll behavior with momentum
|
|
101
|
+
- Magnetic snap points on scroll
|
|
102
|
+
- Cursor trails or custom pointer effects
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Creative Moves Toolkit
|
|
107
|
+
|
|
108
|
+
A palette of techniques to draw from—mix and match based on your aesthetic direction:
|
|
109
|
+
|
|
110
|
+
### Typography Moves
|
|
111
|
+
|
|
112
|
+
- Massive display type (200px+) cropped by viewport edge
|
|
113
|
+
- Mixed weights in same headline ("Build **FAST**")
|
|
114
|
+
- Vertical text for navigation or accents
|
|
115
|
+
- Variable fonts animated on scroll/hover (weight, width, slant)
|
|
116
|
+
- Text stroke / outline only (no fill)
|
|
117
|
+
- Kinetic typography (letters that move independently)
|
|
118
|
+
- Highlighted text with custom underlines or background marks
|
|
119
|
+
- Rotated or angled headlines
|
|
120
|
+
- Text masks revealing images or video
|
|
121
|
+
- Stacked/layered text shadows for depth
|
|
122
|
+
- Justified text with careful hyphenation
|
|
123
|
+
- Pull quotes that break the grid
|
|
124
|
+
|
|
125
|
+
### Layout Moves
|
|
126
|
+
|
|
127
|
+
- Bento grid (varied cell sizes like Apple)
|
|
128
|
+
- Overlap everything (z-index chaos, controlled)
|
|
129
|
+
- Sticky elements that transform as you scroll
|
|
130
|
+
- Split screen with independent scroll speeds
|
|
131
|
+
- Cards that "fan out" or "stack" on hover
|
|
132
|
+
- Masonry that reflows dynamically
|
|
133
|
+
- Off-canvas elements peeking in
|
|
134
|
+
- Full-bleed sections alternating with contained
|
|
135
|
+
- Diagonal dividers between sections
|
|
136
|
+
- Floating elements that respond to scroll/cursor
|
|
137
|
+
- Horizontal scroll sections within vertical page
|
|
138
|
+
- Asymmetric hero with off-center focal point
|
|
139
|
+
|
|
140
|
+
### Color Moves
|
|
141
|
+
|
|
142
|
+
- Monochrome + ONE violent accent color
|
|
143
|
+
- Dark mode with glowing/neon edges
|
|
144
|
+
- Gradient text (\`background-clip: text\`)
|
|
145
|
+
- Color that shifts with scroll position
|
|
146
|
+
- Inverted sections (dark/light alternating dramatically)
|
|
147
|
+
- Duotone images (two-color treatment)
|
|
148
|
+
- Color theming that changes per section
|
|
149
|
+
- Complementary color clashes (intentional tension)
|
|
150
|
+
- Single hue with many tints/shades
|
|
151
|
+
- Black & white with selective color pops
|
|
152
|
+
- Iridescent/holographic effects
|
|
153
|
+
- Color that responds to time of day
|
|
154
|
+
|
|
155
|
+
### Texture Moves
|
|
156
|
+
|
|
157
|
+
- Grain overlay (SVG noise filter or CSS)
|
|
158
|
+
- Glassmorphism done right (\`backdrop-blur\` + subtle border glow)
|
|
159
|
+
- Halftone patterns for retro feel
|
|
160
|
+
- Scan lines (CRT/retro screen effect)
|
|
161
|
+
- Paper texture for editorial authenticity
|
|
162
|
+
- Metallic/chrome reflections (\`conic-gradient\`)
|
|
163
|
+
- Mesh gradients for organic depth
|
|
164
|
+
- Dot patterns or grids as backgrounds
|
|
165
|
+
- Frosted glass panels
|
|
166
|
+
- Subtle shadows with colored tints
|
|
167
|
+
- Glow effects (outer and inner)
|
|
168
|
+
- Noise dithering on gradients
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Proven Aesthetic Combos
|
|
173
|
+
|
|
174
|
+
Pre-validated combinations that work—use as starting points, then make them your own:
|
|
175
|
+
|
|
176
|
+
| Vibe | Typography | Colors | Motion | Layout |
|
|
177
|
+
|------|-----------|--------|--------|--------|
|
|
178
|
+
| **Luxury Tech** | Thin serif + monospace | Black + gold/cream accent | Slow, smooth reveals | Generous whitespace |
|
|
179
|
+
| **Y2K Revival** | Bubble/rounded + pixel fonts | Chrome + hot pink/lime | Bouncy, elastic easing | Chaotic overlap |
|
|
180
|
+
| **Editorial** | High-contrast serif (Playfair, etc.) | B&W + single red accent | Subtle, purposeful fades | Grid with intentional breaks |
|
|
181
|
+
| **Neo-Brutalist** | Heavy grotesque (bold sans) | Primary colors + pure black | Instant, no easing (steps) | Rigid grid, raw borders |
|
|
182
|
+
| **Organic/Calm** | Rounded sans + hand-drawn elements | Earth tones + warm cream | Gentle, breathing motion | Flowing, asymmetric curves |
|
|
183
|
+
| **Cyberpunk** | Condensed industrial + glitch | Neon on dark, high contrast | Flicker, glitch effects | Dense, information-heavy |
|
|
184
|
+
| **Minimal Luxury** | Ultra-thin sans + elegant serif | Muted neutrals, subtle warmth | Almost invisible, precise | Extreme whitespace |
|
|
185
|
+
| **Playful/Toy** | Rounded, chunky, friendly | Bright primaries, pastels | Bouncy, squash & stretch | Loose, scattered, fun |
|
|
186
|
+
| **Art Deco** | Geometric display, gold accents | Black + gold + cream | Elegant reveals, symmetric | Strong geometry, patterns |
|
|
187
|
+
| **Swiss/International** | Helvetica-adjacent, grid-locked | Limited palette, functional | Minimal, functional only | Strict grid system |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## The "AI Slop" Detector
|
|
192
|
+
|
|
193
|
+
You've made AI slop if you see any of these patterns. Stop immediately and pick a weirder direction:
|
|
194
|
+
|
|
195
|
+
### Visual Red Flags
|
|
196
|
+
- Purple-to-blue gradient on white background
|
|
197
|
+
- Generic 3D blob/abstract illustrations
|
|
198
|
+
- Card grid with identical border-radius and shadows
|
|
199
|
+
- Perfectly centered everything with no tension
|
|
200
|
+
- Stock photos of people smiling at laptops
|
|
201
|
+
- Gradient orbs floating in the background
|
|
202
|
+
- The same "glass card" component everywhere
|
|
203
|
+
|
|
204
|
+
### Typography Red Flags
|
|
205
|
+
- Inter, Roboto, Poppins, or system fonts as primary
|
|
206
|
+
- Generic font pairing with no character
|
|
207
|
+
- All text perfectly aligned and safe
|
|
208
|
+
- No hierarchy risks taken
|
|
209
|
+
|
|
210
|
+
### Layout Red Flags
|
|
211
|
+
- "Hero section with headline, subtext, two buttons" (the holy trinity of boring)
|
|
212
|
+
- Three-column feature grid
|
|
213
|
+
- Testimonial carousel
|
|
214
|
+
- "Clean and modern" as the only design rationale
|
|
215
|
+
- Footer with 4 equal columns of links
|
|
216
|
+
|
|
217
|
+
### Motion Red Flags
|
|
218
|
+
- \`transition: all 0.3s ease\` on everything
|
|
219
|
+
- Fade-in-up on scroll for every element
|
|
220
|
+
- No motion at all (static = forgettable)
|
|
221
|
+
- Overused bounce effects
|
|
222
|
+
|
|
223
|
+
**If you catch yourself here**: STOP. Go back to the aesthetic combos. Pick something with actual personality. Ask "what would make someone screenshot this?"
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Before You Ship, Ask Yourself
|
|
228
|
+
|
|
229
|
+
Gut-check questions to ensure you're not shipping mediocrity:
|
|
230
|
+
|
|
231
|
+
1. **Would this make someone stop scrolling?**
|
|
232
|
+
2. **If I remove the logo, is this still recognizable as this brand/product?**
|
|
233
|
+
3. **What's the ONE thing people will screenshot or share?**
|
|
234
|
+
4. **Does this feel like a human made it, or an algorithm?**
|
|
235
|
+
5. **Is there any moment of genuine surprise or delight?**
|
|
236
|
+
6. **Would I put this in my portfolio?**
|
|
237
|
+
7. **Can I describe the aesthetic in one evocative phrase?** (If you can only say "clean and modern," try again)
|
|
238
|
+
8. **Did I take at least ONE real risk?**
|
|
239
|
+
9. **Is the typography doing heavy lifting or just existing?**
|
|
240
|
+
10. **Will this be remembered tomorrow?**
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Implementation Rules
|
|
245
|
+
|
|
246
|
+
**Code Quality**: Production-grade, functional, and clean. No placeholder content unless explicitly temporary.
|
|
247
|
+
|
|
248
|
+
**Styling**: Use Tailwind CSS (with arbitrary values \`[]\` for precision) or custom CSS/SCSS as appropriate for the project.
|
|
249
|
+
|
|
250
|
+
**Responsiveness**: Design for all viewports. Mobile should feel intentional, not cramped.
|
|
251
|
+
|
|
252
|
+
**Performance**: Don't sacrifice loading speed for aesthetics. Lazy load heavy assets. Optimize images.
|
|
253
|
+
|
|
254
|
+
**Accessibility**: Beautiful AND usable. Proper contrast, focus states, semantic HTML, ARIA where needed.
|
|
255
|
+
|
|
256
|
+
**Match Complexity to Vision**:
|
|
257
|
+
- Maximalist designs need elaborate code with extensive animations and effects
|
|
258
|
+
- Minimalist designs need restraint, precision, and obsessive attention to spacing, typography, and subtle details
|
|
259
|
+
- Elegance comes from executing the vision well, not from adding more
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## DESIGN SYSTEM INTEGRATION (CRITICAL WHEN CONTEXT IS PROVIDED)
|
|
264
|
+
|
|
265
|
+
When existing project context is provided, you MUST:
|
|
266
|
+
- NEVER add inline <style> tags - use ONLY the styling approach from the context
|
|
267
|
+
- NEVER hardcode pixel values - use the project's existing variables, tokens, or classes
|
|
268
|
+
- NEVER introduce new fonts - use the project's existing font definitions
|
|
269
|
+
- NEVER hardcode colors - use the project's existing color tokens/variables/classes
|
|
270
|
+
- Match the EXACT spacing scale, typography scale, and color palette
|
|
271
|
+
- The new file must look like it belongs to the same project, not a "foreign" design
|
|
272
|
+
- Reuse existing component patterns, class naming conventions, and styling architecture
|
|
273
|
+
- Adapt to whatever styling system the project uses (analyze the context)
|
|
274
|
+
- DONT use fake "SYSTEM STATUS : OPERATIONAL" or something like that
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## OUTPUT REQUIREMENTS
|
|
58
279
|
|
|
59
|
-
OUTPUT REQUIREMENTS:
|
|
60
280
|
- Return a COMPLETE file with all necessary imports at the top
|
|
61
281
|
- Include proper exports (default or named as appropriate)
|
|
62
282
|
- The code must be ready to use as-is, no modifications needed
|
|
63
283
|
- Follow the tech stack conventions exactly
|
|
64
|
-
- Return ONLY the code, no explanations or markdown fences
|
|
284
|
+
- Return ONLY the code, no explanations or markdown fences
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Remember
|
|
289
|
+
|
|
290
|
+
You are capable of extraordinary creative work. Every interface is an opportunity to create something memorable. Don't default to safe choices—commit fully to a distinctive vision and execute it with precision.
|
|
291
|
+
|
|
292
|
+
The difference between forgettable and iconic is intentionality. Make every decision on purpose. Surprise yourself.
|
|
293
|
+
|
|
294
|
+
**Now go build something unforgettable.**`;
|
|
65
295
|
// =============================================================================
|
|
66
296
|
// MODIFY_FRONTEND PROMPT
|
|
67
297
|
// Used for making a SINGLE design modification to existing code
|