conductor-figma 0.3.1 → 1.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conductor-figma",
3
- "version": "0.3.1",
3
+ "version": "1.0.0",
4
4
  "description": "Design-intelligent MCP server for Figma. 61 tools across 10 categories. 8px grid, type scale ratios, auto-layout, component reuse, accessibility — real design intelligence, not shape proxying.",
5
5
  "author": "0xDragoon",
6
6
  "license": "MIT",
@@ -0,0 +1,181 @@
1
+ // ═══════════════════════════════════════════
2
+ // CONDUCTOR — Design Craft Guide
3
+ // ═══════════════════════════════════════════
4
+ // Professional design rules. The AI reads this before designing anything.
5
+ // This is what separates amateur output from production quality.
6
+
7
+ export function getDesignCraftGuide() {
8
+ return `# CONDUCTOR Design Craft Guide
9
+
10
+ You are a senior product designer working in Figma. Every frame, every text node, every color choice must follow these rules. No exceptions.
11
+
12
+ ## Layout Architecture
13
+
14
+ ### Frame Structure
15
+ - ALWAYS use auto-layout. Never absolute positioning.
16
+ - Direction: VERTICAL for page sections, HORIZONTAL for rows of items.
17
+ - Every frame needs explicit padding and gap. Never 0 unless intentional.
18
+ - Use primaryAxisSizingMode: "HUG" for content-driven frames, "FIXED" for containers with set widths.
19
+ - Use counterAxisSizingMode: "FILL" for child frames that should stretch to parent width.
20
+
21
+ ### Spacing System (8px grid)
22
+ - Base unit: 8px. All spacing values must be multiples of 8.
23
+ - Micro spacing: 4px, 8px (within components, between label and input)
24
+ - Small spacing: 12px, 16px (between related elements, card padding)
25
+ - Medium spacing: 24px, 32px (between component groups, section padding)
26
+ - Large spacing: 48px, 64px (between page sections)
27
+ - Extra large: 80px, 96px, 120px (page-level vertical rhythm)
28
+ - NEVER use: 5, 7, 10, 13, 15, 17, 22, 25, 30, 35, 50, 55, 65, 70, 75, 90, 100
29
+
30
+ ### Content Width
31
+ - Max content width: 1200px for desktop, centered in wider frames
32
+ - For a 1440px page, use 48-80px horizontal padding to create margins
33
+ - Card grid max: 3-4 columns. Never 5+ columns for content cards.
34
+ - Sidebar: 240-280px. Never wider than 320px.
35
+
36
+ ## Typography
37
+
38
+ ### Type Scale (use Inter font family)
39
+ - Display: 56-72px, Bold or Extra Bold, line-height 1.1
40
+ - H1: 40-48px, Bold, line-height 1.15
41
+ - H2: 32-36px, Bold or Semi Bold, line-height 1.2
42
+ - H3: 24-28px, Semi Bold, line-height 1.25
43
+ - H4: 18-20px, Semi Bold, line-height 1.3
44
+ - Body large: 18px, Regular, line-height 1.6
45
+ - Body: 15-16px, Regular, line-height 1.6
46
+ - Body small: 13-14px, Regular, line-height 1.5
47
+ - Caption: 11-12px, Medium, line-height 1.4
48
+ - Overline: 10-12px, Semi Bold or Bold, uppercase, letter-spacing 0.08em
49
+
50
+ ### Typography Rules
51
+ - Maximum 2 font weights per section (e.g., Bold + Regular, Semi Bold + Regular)
52
+ - Body text color should NEVER be pure white (#ffffff). Use #f0f0f8 or #e8e8f0 for dark themes.
53
+ - Muted text: #a0a0b8 for dark themes, #666680 for light themes.
54
+ - Heading to body size ratio should be at least 1.5x.
55
+ - Line length: 45-75 characters for body text. Use max-width on text containers.
56
+
57
+ ## Color
58
+
59
+ ### Dark Theme Palette
60
+ - Background levels: #09090f → #0c0c18 → #0f0f1c → #12122a → #16163a
61
+ - Each level should be visibly distinct but not jarring.
62
+ - Card backgrounds should be 1-2 levels lighter than the page background.
63
+ - Text hierarchy: #f0f0f8 (primary) → #a0a0b8 (secondary) → #686880 (tertiary)
64
+ - Dividers: #1a1a32 or #1e1e3a (subtle, never bright)
65
+ - NEVER use pure black (#000000) as a background.
66
+ - NEVER use pure white (#ffffff) as text on dark backgrounds.
67
+
68
+ ### Light Theme Palette
69
+ - Background levels: #ffffff → #f9f9fb → #f3f3f7 → #ebebf0
70
+ - Card backgrounds: #ffffff with subtle border (#e4e4ec)
71
+ - Text hierarchy: #111118 (primary) → #55556a (secondary) → #88889a (tertiary)
72
+ - Dividers: #e4e4ec
73
+
74
+ ### Brand Color Usage
75
+ - Primary brand color: buttons, links, badges, icons, active states.
76
+ - NEVER use brand color for large background areas.
77
+ - Brand color for text only in overlines, links, and badges.
78
+ - Hover states: darken brand color by 10%. Active: darken by 15%.
79
+
80
+ ## Components
81
+
82
+ ### Buttons
83
+ - Height: 36px (small), 40px (default), 48px (large), 56px (hero)
84
+ - Horizontal padding: 16px (small), 20px (default), 28px (large), 32px (hero)
85
+ - Corner radius: 8px (default), 10-12px (large/hero)
86
+ - Primary: brand color fill, white text, Semi Bold
87
+ - Secondary: transparent fill, border or muted text, Medium weight
88
+ - Ghost: transparent, text only, Medium weight
89
+ - Always center text both axes in buttons
90
+
91
+ ### Cards
92
+ - Padding: 24-32px (compact), 28-40px (standard)
93
+ - Corner radius: 12-16px
94
+ - Gap between elements inside: 12-20px
95
+ - On dark themes: use a lighter background, no border
96
+ - On light themes: white background + subtle border (#e4e4ec) + optional shadow
97
+ - Cards in a row should all be the same height (use counterAxisAlignItems: "STRETCH" on parent)
98
+
99
+ ### Navigation
100
+ - Height: 64-72px for top nav
101
+ - Logo left, links center or right, CTA button far right
102
+ - Use a spacer frame (FILL sizing) between logo and links to push them apart
103
+ - Nav links: 14px Medium, 24-32px gap between items
104
+ - Active state: brand color or bolder weight
105
+ - Add a 1px divider below the nav
106
+
107
+ ### Metric/Stat Cards
108
+ - Stack: label on top (12-13px, muted, Medium), value below (28-36px, Bold)
109
+ - Optional: change indicator below value (12-13px, green for positive, red for negative)
110
+ - Equal width cards in a horizontal row
111
+ - 20-24px gap between metric cards
112
+
113
+ ### Tables
114
+ - Header row: 40-48px height, uppercase 10-11px labels, muted color, Medium weight
115
+ - Data rows: 48-56px height, 14-15px Regular text
116
+ - Cell padding: 16-20px horizontal
117
+ - Alternating row backgrounds or horizontal dividers (not both)
118
+ - Status badges: small colored pills with 4-6px padding, rounded
119
+
120
+ ### Forms
121
+ - Input height: 40-44px
122
+ - Label: 13-14px, Medium weight, 4-8px gap below label
123
+ - Input: 14-15px Regular, 12-16px horizontal padding
124
+ - Corner radius: 8px
125
+ - Border: 1px, muted color. Focus: brand color border
126
+ - 20-24px gap between field groups
127
+
128
+ ## Section Patterns
129
+
130
+ ### Hero Section
131
+ - Vertical padding: 80-120px
132
+ - Content centered (both axes)
133
+ - Overline badge → Heading (56-72px) → Subtitle (18-20px) → Button row → Social proof
134
+ - Max heading width: ~600px
135
+ - Subtitle max width: ~500px
136
+ - 28-32px gap between heading and subtitle
137
+ - 32-40px gap between subtitle and buttons
138
+
139
+ ### Feature Section
140
+ - Heading + subtitle centered at top
141
+ - 3 cards in a row (or 2 for detailed features)
142
+ - Each card: icon/emoji → title → description → optional link
143
+ - 48px gap between heading group and card row
144
+
145
+ ### Stats/Social Proof
146
+ - Background color shift (one level different from surrounding sections)
147
+ - 3-4 stats in a horizontal row, centered
148
+ - Each stat centered: big number + label below
149
+
150
+ ### CTA Section
151
+ - Often wrapped in a card or a background shift
152
+ - Centered: heading → subtitle → button row
153
+ - Generous padding: 64-96px vertical
154
+
155
+ ### Footer
156
+ - Logo left, copyright right, spacer between
157
+ - Or: multi-column with link groups
158
+ - Divider line above
159
+ - Muted text, smaller font sizes (13px)
160
+
161
+ ## Anti-Patterns (NEVER do these)
162
+ - Never use absolute positioning. Always auto-layout.
163
+ - Never use font sizes that aren't in the type scale.
164
+ - Never use spacing values that aren't multiples of 4 or 8.
165
+ - Never put more than 3-4 cards in a row.
166
+ - Never use pure black or pure white on dark themes.
167
+ - Never make buttons without sufficient padding (minimum 16px horizontal).
168
+ - Never stack more than 4-5 levels of nesting without good reason.
169
+ - Never use inconsistent corner radii on the same page.
170
+ - Never use more than 2-3 distinct background colors per page.
171
+ - Never center-align body paragraphs (center headings only).
172
+ - Never use text smaller than 11px.
173
+ - Never create frames without naming them descriptively.
174
+
175
+ ## Naming Convention
176
+ - Pages: "Landing Page", "Pricing Page", "Dashboard"
177
+ - Sections: "Hero Section", "Features Section", "CTA Section"
178
+ - Components: "Nav CTA", "Feature Card", "Stat Card", "Price Tier"
179
+ - Layout: "Card Row", "Button Row", "Nav Links"
180
+ - Never use "Frame 1", "Rectangle 2", or auto-generated names.`;
181
+ }
package/src/index.js CHANGED
@@ -30,3 +30,4 @@ export {
30
30
  } from './design/intelligence.js';
31
31
 
32
32
  export { exportCSS, exportTailwind, exportSCSS, exportJSON, exportW3CTokens } from './design/exporter.js';
33
+ export { getDesignCraftGuide } from './design/craftguide.js';
package/src/relay.js CHANGED
@@ -15,15 +15,17 @@ import { createServer } from 'node:http';
15
15
  const FIGMA_COMMANDS = new Set([
16
16
  // Create
17
17
  'create_frame', 'create_text', 'create_rect', 'create_section', 'create_component',
18
+ 'create_ellipse', 'create_svg_node',
18
19
  // Layout
19
20
  'set_auto_layout', 'set_constraints', 'apply_grid', 'align_nodes',
20
21
  // Style
21
22
  'set_fills', 'set_strokes', 'set_effects', 'set_corner_radius', 'set_opacity',
22
23
  // Typography
23
- 'set_text_props', 'load_font',
24
+ 'set_text_props', 'load_font', 'style_text_range',
24
25
  // Read
25
26
  'get_selection', 'get_page_info', 'get_styles', 'get_components',
26
27
  'read_node', 'read_tree', 'read_spacing', 'read_colors', 'read_typography',
28
+ 'find_nodes',
27
29
  // Edit
28
30
  'rename_node', 'move_node', 'resize_node', 'delete_node',
29
31
  'clone_node', 'group_nodes', 'ungroup_node', 'reorder_node',
@@ -6,6 +6,7 @@
6
6
 
7
7
  import * as design from '../design/intelligence.js';
8
8
  import * as exporter from '../design/exporter.js';
9
+ import { getDesignCraftGuide } from '../design/craftguide.js';
9
10
 
10
11
  function text(str) {
11
12
  return { content: [{ type: 'text', text: str }] };
@@ -389,6 +390,68 @@ const HANDLERS = {
389
390
  },
390
391
  export_spec(args) { return json({ action: 'generate_spec', nodeId: args.nodeId, format: args.format || 'markdown' }); },
391
392
  export_changelog(args) { return json({ action: 'diff_frames', nodeIdA: args.nodeIdA, nodeIdB: args.nodeIdB, format: args.format || 'markdown' }); },
393
+
394
+ // ═══ DESIGN CRAFT ═══
395
+ get_design_craft_guide() {
396
+ return text(getDesignCraftGuide());
397
+ },
398
+
399
+ // ═══ CREATE (additional) ═══
400
+ create_ellipse(args) {
401
+ return json({
402
+ action: 'create_ellipse',
403
+ name: args.name || 'Ellipse',
404
+ width: args.width, height: args.height,
405
+ fill: args.fill || '#ffffff',
406
+ x: args.x, y: args.y,
407
+ parentId: args.parentId,
408
+ opacity: args.opacity,
409
+ });
410
+ },
411
+
412
+ create_line(args) {
413
+ var dir = args.direction || 'horizontal';
414
+ return json({
415
+ action: 'create_rect',
416
+ name: args.name || 'Divider',
417
+ width: dir === 'horizontal' ? args.length : 1,
418
+ height: dir === 'horizontal' ? 1 : args.length,
419
+ fill: args.color || '#1a1a32',
420
+ parentId: args.parentId,
421
+ });
422
+ },
423
+
424
+ create_svg_node(args) {
425
+ return json({
426
+ action: 'create_svg_node',
427
+ name: args.name || 'SVG',
428
+ svg: args.svg,
429
+ x: args.x, y: args.y,
430
+ parentId: args.parentId,
431
+ });
432
+ },
433
+
434
+ find_nodes(args) {
435
+ return json({
436
+ action: 'find_nodes',
437
+ query: args.query,
438
+ type: args.type,
439
+ parentId: args.parentId,
440
+ });
441
+ },
442
+
443
+ // ═══ TYPOGRAPHY (additional) ═══
444
+ style_text_range(args) {
445
+ return json({
446
+ action: 'style_text_range',
447
+ nodeId: args.nodeId,
448
+ start: args.start,
449
+ end: args.end,
450
+ fontSize: args.fontSize,
451
+ fontWeight: args.fontWeight,
452
+ color: args.color,
453
+ });
454
+ },
392
455
  };
393
456
 
394
457
  // ─── Helpers ───
@@ -5,9 +5,10 @@
5
5
  // Each tool has: name, description, category, inputSchema, handler reference.
6
6
 
7
7
  export const CATEGORIES = {
8
- create: { label: 'Create', icon: '', count: 8 },
8
+ craft: { label: 'Design Craft', icon: '', count: 1 },
9
+ create: { label: 'Create', icon: '⊞', count: 12 },
9
10
  layout: { label: 'Layout', icon: '▤', count: 7 },
10
- typography: { label: 'Typography', icon: '◆', count: 6 },
11
+ typography: { label: 'Typography', icon: '◆', count: 7 },
11
12
  color: { label: 'Color & Style', icon: '◑', count: 7 },
12
13
  components: { label: 'Components', icon: '◎', count: 6 },
13
14
  spacing: { label: 'Spacing & Grid', icon: '◧', count: 6 },
@@ -277,6 +278,33 @@ export const TOOLS = [
277
278
  { name: 'export_changelog', category: 'export',
278
279
  description: 'Diff two frames and export what changed as structured markdown or JSON.',
279
280
  inputSchema: { type: 'object', properties: { nodeIdA: str('First frame (before)'), nodeIdB: str('Second frame (after)'), format: opt(str('markdown or json')) }, required: ['nodeIdA', 'nodeIdB'] } },
281
+
282
+ // ═══ DESIGN CRAFT ═══
283
+ { name: 'get_design_craft_guide', category: 'craft',
284
+ description: 'IMPORTANT: Call this FIRST before creating any design. Returns comprehensive professional design rules covering typography scales, spacing systems, color palettes, component patterns, layout architecture, and anti-patterns. Read and follow these rules to produce production-quality designs.',
285
+ inputSchema: { type: 'object', properties: {}, required: [] } },
286
+
287
+ // ═══ CREATE (additional) ═══
288
+ { name: 'create_ellipse', category: 'create',
289
+ description: 'Create a circle or oval. Use for avatars, status indicators, decorative elements, and icon backgrounds. Set equal width and height for a perfect circle.',
290
+ inputSchema: { type: 'object', properties: { name: opt(str('Element name')), width: num('Width in px'), height: num('Height in px'), fill: opt(str('Fill color hex')), x: opt(num('X position')), y: opt(num('Y position')), parentId: opt(str('Parent frame ID')), opacity: opt(num('Opacity 0-1')) }, required: ['width', 'height'] } },
291
+
292
+ { name: 'create_line', category: 'create',
293
+ description: 'Create a horizontal or vertical line. Use for dividers between sections, separators in navigation, and visual breaks. A line is a rectangle with 1px height (horizontal) or 1px width (vertical).',
294
+ inputSchema: { type: 'object', properties: { name: opt(str('Element name')), length: num('Length in px'), direction: opt(str('horizontal or vertical (default horizontal)')), color: opt(str('Line color hex')), parentId: opt(str('Parent frame ID')) }, required: ['length'] } },
295
+
296
+ { name: 'create_svg_node', category: 'create',
297
+ description: 'Create a vector graphic from raw SVG markup. Use for icons, logos, illustrations, and any custom vector shape. Pass the SVG string directly.',
298
+ inputSchema: { type: 'object', properties: { name: opt(str('Element name')), svg: str('Raw SVG markup string'), x: opt(num('X position')), y: opt(num('Y position')), parentId: opt(str('Parent frame ID')) }, required: ['svg'] } },
299
+
300
+ { name: 'find_nodes', category: 'create',
301
+ description: 'Search for elements by name or type within a frame or the entire page. Returns matching nodes with their IDs, positions, and basic properties. Use to locate elements before editing them.',
302
+ inputSchema: { type: 'object', properties: { query: opt(str('Search by name (partial match)')), type: opt(str('Filter by type: FRAME, TEXT, RECTANGLE, ELLIPSE, COMPONENT, INSTANCE')), parentId: opt(str('Search within this frame only')) }, required: [] } },
303
+
304
+ // ═══ TYPOGRAPHY (additional) ═══
305
+ { name: 'style_text_range', category: 'typography',
306
+ description: 'Apply different styles to specific character ranges within a text node. Use for mixed-weight text (e.g., bold product name within a regular sentence), colored keywords, or size variations within a single text element.',
307
+ inputSchema: { type: 'object', properties: { nodeId: str('Text node ID'), start: num('Start character index'), end: num('End character index'), fontSize: opt(num('Font size for range')), fontWeight: opt(num('Font weight: 400, 500, 600, 700')), color: opt(str('Color hex for range')) }, required: ['nodeId', 'start', 'end'] } },
280
308
  ];
281
309
 
282
310
  export function getToolsByCategory(category) {