figmatk 0.0.7 → 0.0.9

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.
@@ -13,7 +13,7 @@
13
13
  {
14
14
  "name": "figmatk",
15
15
  "description": "Inspect and modify Figma Slides .deck files natively",
16
- "version": "0.0.6",
16
+ "version": "0.0.8",
17
17
  "author": {
18
18
  "name": "FigmaTK Contributors"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figmatk",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "Create and edit Figma Slides .deck files programmatically — no Figma API required",
5
5
  "author": {
6
6
  "name": "FigmaTK Contributors"
package/lib/api.mjs CHANGED
@@ -1667,12 +1667,15 @@ function parseColor(fd, color) {
1667
1667
  if (typeof color === 'string') {
1668
1668
  // Hex string
1669
1669
  if (/^#?[0-9a-fA-F]{6}$/.test(color)) return _hexToRgb(color);
1670
- // Designer alias (case-insensitive)
1670
+ // Figma theme variable first (exact match, preserves colorVar binding for slides)
1671
+ try {
1672
+ const variable = resolveColorVariable(fd, color);
1673
+ return { r: variable.r, g: variable.g, b: variable.b, _guid: variable.guid };
1674
+ } catch (_) {}
1675
+ // Designer alias fallback (case-insensitive)
1671
1676
  const alias = DESIGNER_COLORS[color.toLowerCase()];
1672
1677
  if (alias) return _hexToRgb(alias);
1673
- // Figma theme variable
1674
- const variable = resolveColorVariable(fd, color);
1675
- return { r: variable.r, g: variable.g, b: variable.b, _guid: variable.guid };
1678
+ throw new Error(`Unknown color: "${color}". Use a Light Slides name ('Black', 'Teal'), a designer alias ('navy', 'coral'), or a hex string ('#E63946').`);
1676
1679
  }
1677
1680
  throw new Error(`Invalid color: ${JSON.stringify(color)}`);
1678
1681
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figmatk",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "Figma Toolkit — Swiss-army knife CLI for Figma .deck and .fig files",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,213 @@
1
+ ---
2
+ name: figma-slides-creator
3
+ description: >
4
+ Create, edit, and inspect Figma Slides .deck files. Use when the user asks to
5
+ create a presentation, build a slide deck, edit slides, update text or images,
6
+ clone or remove slides, or produce a .deck file for Figma Slides.
7
+ Powered by FigmaTK under the hood.
8
+ metadata:
9
+ version: "0.0.8"
10
+ ---
11
+
12
+ # FigmaTK Skill
13
+
14
+ ## ⚠️ Never open .deck files directly
15
+
16
+ `.deck` files are binary ZIP archives. **Never open, read, or display a `.deck` file** — it will show garbage bytes in the panel. To inspect or modify a `.deck` file, always use the CLI commands or Node.js API shown below.
17
+
18
+ To let the user view the result: tell them to **open the file in Figma Desktop** (`File → Open` or double-click the `.deck` file).
19
+
20
+ ---
21
+
22
+ ## Quick Reference
23
+
24
+ | Task | Approach |
25
+ |------|----------|
26
+ | Create a new deck from scratch | Use the high-level JS API (`lib/api.mjs`) |
27
+ | Edit text or images in an existing deck | Use MCP tools (`figmatk_update_text`, `figmatk_insert_image`) |
28
+ | Clone, remove, or restructure slides | Use MCP tools (`figmatk_clone_slide`, `figmatk_remove_slide`) |
29
+ | Inspect structure or read content | Use MCP tools (`figmatk_inspect`, `figmatk_list_text`) |
30
+
31
+ ---
32
+
33
+ ## Path A — Create from Scratch (High-Level API)
34
+
35
+ Use this when the user wants a new presentation. Write a Node.js script and execute it.
36
+
37
+ > **Import path:** `figmatk` is an npm package. Import from the installed package:
38
+ > ```javascript
39
+ > import { Deck } from 'figmatk';
40
+ > ```
41
+
42
+ ```javascript
43
+ import { Deck } from 'figmatk';
44
+
45
+ const deck = await Deck.create('My Presentation');
46
+
47
+ const slide = deck.addBlankSlide(); // template blank slide auto-removed
48
+ slide.setBackground('Black'); // named color — see list below
49
+ slide.addText('Slide Title', {
50
+ style: 'Title', color: 'White',
51
+ x: 64, y: 80, width: 1792, align: 'LEFT'
52
+ });
53
+ slide.addText('Subtitle', {
54
+ style: 'Body 1', color: 'Grey',
55
+ x: 64, y: 240, width: 1200, align: 'LEFT'
56
+ });
57
+
58
+ await deck.save('/path/to/output.deck');
59
+ ```
60
+
61
+ ### ⚠️ Critical gotchas
62
+
63
+ | Issue | Wrong | Right |
64
+ |-------|-------|-------|
65
+ | `setBackground` with hex | `s.setBackground('#1A1A1A')` | `s.setBackground('Black')` |
66
+ | `setBackground` with raw RGB | `s.setBackground({ r:0.1, g:0.1, b:0.1 })` | `s.setBackground('Black')` — raw RGB silently renders white |
67
+ | Shape method signature | `s.addRectangle({ x:0, y:0, width:100 })` | `s.addRectangle(0, 0, 100, 100, opts)` |
68
+ | Shape fill color | `{ fill: '#F4900C' }` | `{ fill: hex('#F4900C') }` — use the hex() helper |
69
+ | `addLine` options | `{ strokeColor: ..., strokeWeight: 2 }` | `{ color: 'Black', weight: 2 }` |
70
+ | `align` value | `align: 'left'` | `align: 'LEFT'` (uppercase) |
71
+
72
+ ### Hex color helper (for shape fills)
73
+
74
+ ```javascript
75
+ function hex(h) {
76
+ return { r: parseInt(h.slice(1,3),16)/255, g: parseInt(h.slice(3,5),16)/255, b: parseInt(h.slice(5,7),16)/255 };
77
+ }
78
+ // Usage: s.addRectangle(0, 0, 200, 50, { fill: hex('#F4900C') })
79
+ ```
80
+
81
+ ### Text styles
82
+
83
+ | Style | Size | Weight | Use for |
84
+ |-------|------|--------|---------|
85
+ | `Title` | 96pt | Bold | Slide title |
86
+ | `Header 1` | 60pt | Bold | Section headers |
87
+ | `Header 2` | 48pt | Bold | Sub-headers |
88
+ | `Header 3` | 36pt | Bold | In-slide headings |
89
+ | `Body 1` | 36pt | Regular | Primary body text |
90
+ | `Body 2` | 30pt | Regular | Secondary body text |
91
+ | `Body 3` | 24pt | Regular | Captions, labels |
92
+ | `Note` | 20pt | Regular | Footnotes, sources |
93
+
94
+ ### Named colors for `setBackground()`
95
+
96
+ > **Case-sensitive.** `'Black'` works, `'black'` does not.
97
+
98
+ `'Black'`, `'White'`, `'Grey'`, `'Blue'`, `'Red'`, `'Yellow'`, `'Green'`, `'Orange'`, `'Pink'`, `'Purple'`, `'Teal'`, `'Violet'`, `'Persimmon'`, `'Pale Pink'`, `'Pale Blue'`, `'Pale Green'`, `'Pale Teal'`, `'Pale Purple'`, `'Pale Persimmon'`, `'Pale Violet'`, `'Pale Red'`, `'Pale Yellow'`
99
+
100
+ Use `'Black'` for dark backgrounds, `'White'` for light. For custom slide backgrounds, use the closest named color — **not hex**.
101
+
102
+ ### Slide dimensions
103
+
104
+ 1920 × 1080px. All positions and sizes in pixels.
105
+
106
+ ### Slide methods (correct signatures)
107
+
108
+ ```javascript
109
+ slide.setBackground(namedColor) // named color only — hex/raw RGB render white
110
+ slide.addText(text, opts) // opts: style, color (named or hex('#...')), x, y, width, align, bold, italic, fontSize
111
+ slide.addFrame(opts) // auto-layout: stackMode, spacing, x, y, width, height
112
+ slide.addRectangle(x, y, width, height, opts) // opts: fill (named or {r,g,b}), opacity, cornerRadius
113
+ slide.addEllipse(x, y, width, height, opts) // opts: fill, opacity
114
+ slide.addDiamond(x, y, width, height, opts)
115
+ slide.addTriangle(x, y, width, height, opts)
116
+ slide.addStar(x, y, width, height, opts)
117
+ slide.addLine(x1, y1, x2, y2, opts) // opts: color, weight
118
+ slide.addImage(path, opts) // opts: x, y, width, height
119
+ slide.addTable(data, opts) // 2D string array; opts: x, y, width, colWidths, rowHeight
120
+ slide.addSVG(x, y, width, svgPathOrBuf, opts)
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Path B — Edit an Existing Deck (MCP Tools)
126
+
127
+ Use this when the user provides a `.deck` file to modify.
128
+
129
+ ### Workflow
130
+
131
+ 1. `figmatk_inspect` — understand the deck structure (node IDs, slide count, symbols)
132
+ 2. `figmatk_list_text` — read current text and images per slide
133
+ 3. `figmatk_list_overrides` — find the override keys for each symbol (what's editable)
134
+ 4. `figmatk_update_text` — apply text changes
135
+ 5. `figmatk_insert_image` — apply image changes
136
+ 6. `figmatk_clone_slide` — duplicate a slide and populate it
137
+ 7. `figmatk_remove_slide` — mark unwanted slides as REMOVED
138
+ 8. Always write to a **new output path** — never overwrite the source
139
+
140
+ ### MCP tool reference
141
+
142
+ | Tool | Purpose |
143
+ |------|---------|
144
+ | `figmatk_inspect` | Node hierarchy tree — structure, node IDs, slide count |
145
+ | `figmatk_list_text` | All text strings and image hashes per slide |
146
+ | `figmatk_list_overrides` | Editable override keys per symbol (component) |
147
+ | `figmatk_update_text` | Set text overrides on a slide instance |
148
+ | `figmatk_insert_image` | Set image fill override (handles SHA-1 hashing + thumbnail) |
149
+ | `figmatk_clone_slide` | Deep-clone a slide with new text and images |
150
+ | `figmatk_remove_slide` | Mark slides as REMOVED (never deleted) |
151
+ | `figmatk_roundtrip` | Decode + re-encode for pipeline validation |
152
+
153
+ ---
154
+
155
+ ## Design Philosophy
156
+
157
+ Every deck must look **intentionally designed**, not AI-generated.
158
+
159
+ ### Colour
160
+
161
+ - Pick a bold palette for the **specific topic** — not a generic one.
162
+ - One dominant colour (60–70%) + 1–2 supporting tones + one sharp accent.
163
+ - Dark backgrounds on title/conclusion slides, light on content ("sandwich") — or fully dark for premium feel.
164
+
165
+ **Starter palettes** (use nearest named color for `setBackground`, hex helper for shapes):
166
+
167
+ | Theme | Background | Shape accent | Text |
168
+ |-------|-----------|-------------|------|
169
+ | Midnight | `'Black'` | `hex('#CADCFC')` | `'White'` |
170
+ | Forest | `'Green'` | `hex('#97BC62')` | `'White'` |
171
+ | Coral | `'Persimmon'` | `hex('#2F3C7E')` | `'White'` |
172
+ | Terracotta | `'Persimmon'` | `hex('#E7E8D1')` | `'White'` |
173
+ | Ocean | `'Blue'` | `hex('#21295C')` | `'White'` |
174
+ | Minimal | `'White'` | `hex('#36454F')` | `'Black'` |
175
+
176
+ ### Layout
177
+
178
+ - Every slide needs at least **one visual element** — shape, image, SVG, or table.
179
+ - **Vary layouts** — never repeat the same structure slide after slide.
180
+ - Carry one visual motif through every slide (coloured accent bar, icon circles, etc.).
181
+
182
+ **Layout options:** two-column, icon+text rows, 2×2/2×3 grid, large stat callout, half-background image, timeline/steps.
183
+
184
+ ### Typography
185
+
186
+ - Left-align body text. Centre only titles.
187
+ - Minimum 64px margin from slide edges. 24–48px between content blocks.
188
+
189
+ ### Never do
190
+
191
+ - Repeat the same layout slide after slide
192
+ - Centre body text
193
+ - Use accent lines under slide titles (hallmark of AI-generated slides)
194
+ - Text-only slides
195
+ - Low-contrast text against background
196
+
197
+ ---
198
+
199
+ ## QA
200
+
201
+ 1. Self-check: no placeholder text (`lorem ipsum`, `[title here]`) remains
202
+ 2. Tell the user to open the `.deck` in Figma Desktop to catch rendering issues
203
+ 3. Offer to fix anything they report
204
+
205
+ ---
206
+
207
+ ## Critical Format Rules
208
+
209
+ - Blank text must be `" "` (space), never `""` — empty string crashes Figma
210
+ - Image overrides need both a full-image hash and thumbnail hash (40-char hex SHA-1)
211
+ - Removed nodes: set `phase: 'REMOVED'`, never delete from `nodeChanges`
212
+ - Chunk 1 of `canvas.fig` must be zstd-compressed
213
+ - `thumbHash` must be `new Uint8Array(0)`, never `{}`
@@ -1,188 +0,0 @@
1
- ---
2
- name: figmatk
3
- description: >
4
- Create, edit, and inspect Figma Slides .deck files. Use when the user asks to
5
- create a presentation, build a slide deck, edit slides, update text or images,
6
- clone or remove slides, or produce a .deck file for Figma Slides.
7
- metadata:
8
- version: "0.0.6"
9
- ---
10
-
11
- # FigmaTK Skill
12
-
13
- ## Quick Reference
14
-
15
- | Task | Approach |
16
- |------|----------|
17
- | Create a new deck from scratch | Use the high-level JS API (`lib/api.mjs`) |
18
- | Edit text or images in an existing deck | Use MCP tools (`figmatk_update_text`, `figmatk_insert_image`) |
19
- | Clone, remove, or restructure slides | Use MCP tools (`figmatk_clone_slide`, `figmatk_remove_slide`) |
20
- | Inspect structure or read content | Use MCP tools (`figmatk_inspect`, `figmatk_list_text`) |
21
-
22
- ---
23
-
24
- ## Path A — Create from Scratch (High-Level API)
25
-
26
- Use this when the user wants a new presentation. Write a Node.js script and execute it.
27
-
28
- ```javascript
29
- import { Deck } from 'figmatk';
30
-
31
- const deck = await Deck.create('My Presentation');
32
- const slide = deck.addBlankSlide();
33
-
34
- slide.setBackground('slate');
35
- slide.addText('Slide Title', { style: 'Title', color: 'white', x: 64, y: 80, width: 1792 });
36
- slide.addText('Subtitle or tagline here', { style: 'Body 1', color: 'light-gray', x: 64, y: 240, width: 1200 });
37
-
38
- await deck.save('/path/to/output.deck');
39
- ```
40
-
41
- ### Text styles
42
-
43
- | Style | Size | Weight | Use for |
44
- |-------|------|--------|---------|
45
- | `Title` | 96pt | Bold | Slide title |
46
- | `Header 1` | 60pt | Bold | Section headers |
47
- | `Header 2` | 48pt | Bold | Sub-headers |
48
- | `Header 3` | 36pt | Bold | In-slide headings |
49
- | `Body 1` | 36pt | Regular | Primary body text |
50
- | `Body 2` | 30pt | Regular | Secondary body text |
51
- | `Body 3` | 24pt | Regular | Captions, labels |
52
- | `Note` | 20pt | Regular | Footnotes, sources |
53
-
54
- ### Colors
55
-
56
- Use **names** — never RGB values. The API accepts:
57
-
58
- | Type | Example |
59
- |------|---------|
60
- | Designer name | `'teal'`, `'coral'`, `'navy'`, `'midnight'`, `'forest'`, `'charcoal'`, `'cream'`, `'gold'`, `'terracotta'`, `'sage'`, `'cobalt'`, `'rose'`, `'indigo'`, `'burgundy'`, `'sand'`... |
61
- | Hex string | `'#E63946'` |
62
- | Light Slides theme | `'Blue'`, `'Red'`, `'Green'`, `'Yellow'`, `'Orange'`, `'Pink'`, `'Purple'`, `'Slate'`, `'White'`, `'Black'` |
63
-
64
- Pick colors by feeling: "warm terracotta on cream", "midnight blue with coral accent". Let the design drive the choice, then pick the closest name.
65
-
66
- ### Slide dimensions
67
-
68
- 1920 × 1080px. Position and size all elements in pixels.
69
-
70
- ### Available slide methods
71
-
72
- ```javascript
73
- slide.setBackground(color) // named color or hex
74
- slide.addText(text, opts) // opts: style, color, x, y, width, align, bold, italic, fontSize
75
- slide.addFrame(opts) // auto-layout frame: stackMode, spacing, x, y, width, height
76
- slide.addRectangle(opts) // opts: x, y, width, height, fill, opacity, cornerRadius
77
- slide.addEllipse(opts) // circle/ellipse: x, y, width, height, fill
78
- slide.addDiamond(opts) // diamond shape
79
- slide.addTriangle(opts) // triangle
80
- slide.addStar(opts) // 5-pointed star
81
- slide.addLine(x1, y1, x2, y2, opts) // line: strokeColor, strokeWeight
82
- slide.addImage(path, opts) // freestanding image: x, y, width, height
83
- slide.addTable(data, opts) // 2D array of strings: x, y, width, colWidths, rowHeight
84
- slide.addSVG(x, y, width, svgPathOrBuf, opts) // import SVG vector graphic
85
- ```
86
-
87
- ---
88
-
89
- ## Path B — Edit an Existing Deck (MCP Tools)
90
-
91
- Use this when the user provides a `.deck` file to modify.
92
-
93
- ### Workflow
94
-
95
- 1. `figmatk_inspect` — understand the deck structure (node IDs, slide count, symbols)
96
- 2. `figmatk_list_text` — read current text and images per slide
97
- 3. `figmatk_list_overrides` — find the override keys for each symbol (what's editable)
98
- 4. `figmatk_update_text` — apply text changes
99
- 5. `figmatk_insert_image` — apply image changes
100
- 6. `figmatk_clone_slide` — duplicate a slide and populate it
101
- 7. `figmatk_remove_slide` — mark unwanted slides as REMOVED
102
- 8. Always write to a **new output path** — never overwrite the source
103
-
104
- ### MCP tool reference
105
-
106
- | Tool | Purpose |
107
- |------|---------|
108
- | `figmatk_inspect` | Node hierarchy tree — structure, node IDs, slide count |
109
- | `figmatk_list_text` | All text strings and image hashes per slide |
110
- | `figmatk_list_overrides` | Editable override keys per symbol (component) |
111
- | `figmatk_update_text` | Set text overrides on a slide instance |
112
- | `figmatk_insert_image` | Set image fill override (handles SHA-1 hashing + thumbnail) |
113
- | `figmatk_clone_slide` | Deep-clone a slide with new text and images |
114
- | `figmatk_remove_slide` | Mark slides as REMOVED (never deleted) |
115
- | `figmatk_roundtrip` | Decode + re-encode for pipeline validation |
116
-
117
- ---
118
-
119
- ## Design Philosophy
120
-
121
- Every deck must look **intentionally designed**, not AI-generated. Follow these rules on every presentation task.
122
-
123
- ### Colour
124
-
125
- - Pick a bold palette that reflects the **specific topic**. If the same palette would suit a completely different presentation, it's not specific enough.
126
- - Use **one dominant colour** (60–70% visual weight) + 1–2 supporting tones + one sharp accent.
127
- - Use dark backgrounds on title and conclusion slides, light on content slides ("sandwich" structure) — or commit fully to dark for a premium feel.
128
-
129
- **Starter palettes:**
130
-
131
- | Theme | Background | Accent | Text |
132
- |-------|-----------|--------|------|
133
- | Midnight | `navy` | `sky` | `white` |
134
- | Forest | `forest` | `sage` | `white` |
135
- | Coral | `coral` | `indigo` | `white` |
136
- | Terracotta | `terracotta` | `sand` | `white` |
137
- | Ocean | `cobalt` | `midnight` | `white` |
138
- | Minimal | `smoke` | `charcoal` | `black` |
139
-
140
- ### Layout
141
-
142
- - Every slide needs at least **one visual element** — shape, image, SVG icon, or table. Text-only slides are forgettable.
143
- - **Vary layouts** — never use the same structure slide after slide.
144
- - Pick one visual motif (e.g. rounded image frames, coloured icon circles, thick side accent bars) and carry it through every slide.
145
-
146
- **Layout options per slide:**
147
-
148
- - Two-column (text left, visual right)
149
- - Icon + text rows (icon in coloured circle, bold header, description)
150
- - 2×2 or 2×3 grid of cards
151
- - Large stat callout (big number + small label)
152
- - Half-background image with text overlay
153
- - Timeline / numbered steps
154
-
155
- ### Typography
156
-
157
- - Left-align body text. Centre only titles.
158
- - **Font sizes:** titles use `Title` style (96pt); section headers `Header 1` (60pt); body `Body 1` or `Body 2`; captions `Body 3` or `Note`.
159
- - Minimum 64px margin from slide edges. 24–48px gap between content blocks.
160
-
161
- ### Things to never do
162
-
163
- - Repeat the same layout slide after slide
164
- - Centre body text
165
- - Use accent lines under slide titles (hallmark of AI-generated slides — use colour or whitespace instead)
166
- - Create text-only slides
167
- - Use low-contrast text — always check text against its background
168
- - Default to generic blue — pick colours that reflect the topic
169
-
170
- ---
171
-
172
- ## QA
173
-
174
- After generating or editing a deck:
175
-
176
- 1. **Self-check:** confirm all placeholder text has been replaced, no `lorem ipsum` or `[title here]` remains
177
- 2. **Tell the user** to upload the `.deck` to Figma Slides and review visually — this is the only way to catch rendering issues
178
- 3. **Offer to fix** any issues the user reports after upload
179
-
180
- ---
181
-
182
- ## Critical Format Rules
183
-
184
- - Blank text fields must use `" "` (space), **never** empty string — empty string crashes Figma
185
- - Image overrides require both a full-image hash and a ~320px thumbnail hash (40-char hex SHA-1)
186
- - Removed nodes use `phase: 'REMOVED'` — never delete from `nodeChanges`
187
- - Chunk 1 of `canvas.fig` must be zstd-compressed — Figma silently rejects deflateRaw
188
- - `thumbHash` must be `new Uint8Array(0)`, never `{}`