figmatk 0.3.0 → 0.3.7
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +49 -14
- package/cli.mjs +2 -0
- package/commands/render.mjs +56 -0
- package/lib/fig-deck.mjs +4 -4
- package/lib/rasterizer/deck-rasterizer.mjs +228 -0
- package/lib/rasterizer/download-font.mjs +57 -0
- package/lib/rasterizer/font-resolver.mjs +602 -0
- package/lib/rasterizer/fonts/DarkerGrotesque-400.ttf +0 -0
- package/lib/rasterizer/fonts/DarkerGrotesque-500.ttf +0 -0
- package/lib/rasterizer/fonts/DarkerGrotesque-600.ttf +0 -0
- package/lib/rasterizer/fonts/Inter-Regular.ttf +0 -0
- package/lib/rasterizer/fonts/Inter-Variable.ttf +0 -0
- package/lib/rasterizer/fonts/Inter.var.woff2 +0 -0
- package/lib/rasterizer/fonts/darker-grotesque-patched-400-normal.woff2 +0 -0
- package/lib/rasterizer/fonts/darker-grotesque-patched-500-normal.woff2 +0 -0
- package/lib/rasterizer/fonts/darker-grotesque-patched-600-normal.woff2 +0 -0
- package/lib/rasterizer/fonts/darker-grotesque-patched-700-normal.woff2 +0 -0
- package/lib/rasterizer/fonts/inter-v3-400-italic.woff2 +0 -0
- package/lib/rasterizer/fonts/inter-v3-400-normal.woff2 +0 -0
- package/lib/rasterizer/fonts/inter-v3-500-normal.woff2 +0 -0
- package/lib/rasterizer/fonts/inter-v3-600-normal.woff2 +0 -0
- package/lib/rasterizer/fonts/inter-v3-700-italic.woff2 +0 -0
- package/lib/rasterizer/fonts/inter-v3-700-normal.woff2 +0 -0
- package/lib/rasterizer/fonts/inter-v3-meta.json +6 -0
- package/lib/rasterizer/render-report-lib.mjs +127 -0
- package/lib/rasterizer/render-report.mjs +25 -0
- package/lib/rasterizer/svg-builder.mjs +571 -0
- package/lib/rasterizer/test-render.mjs +63 -0
- package/lib/template-deck.mjs +573 -148
- package/manifest.json +21 -0
- package/mcp-server.mjs +184 -20
- package/package.json +17 -2
- package/skills/figma-slides-creator/SKILL.md +79 -172
- package/skills/figma-template-builder/SKILL.md +158 -0
|
@@ -6,10 +6,10 @@ description: >
|
|
|
6
6
|
clone or remove slides, or produce a .deck file for Figma Slides.
|
|
7
7
|
Powered by FigmaTK under the hood.
|
|
8
8
|
metadata:
|
|
9
|
-
version: "0.3.
|
|
9
|
+
version: "0.3.7"
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
#
|
|
12
|
+
# FigmaTK Skill
|
|
13
13
|
|
|
14
14
|
## ⚠️ Never open .deck files directly
|
|
15
15
|
|
|
@@ -23,132 +23,39 @@ To let the user view the result: tell them to **open the file in Figma Desktop**
|
|
|
23
23
|
|
|
24
24
|
| Task | Approach |
|
|
25
25
|
|------|----------|
|
|
26
|
-
| Create from scratch |
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
| Inspect structure or read content | `figmatk_inspect`, `figmatk_list_text` |
|
|
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`) |
|
|
31
30
|
|
|
32
31
|
---
|
|
33
32
|
|
|
34
|
-
##
|
|
33
|
+
## Path A — Create from Scratch (High-Level API)
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
Use this when the user wants a new presentation. Write a Node.js script and execute it.
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Use this path when the user provides a `.deck` template file. The output deck inherits all fonts, colors, spacing, and visual design from the template verbatim.
|
|
43
|
-
|
|
44
|
-
### Step 1 — Inspect the template
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
figmatk_list_template_layouts("/path/to/template.deck")
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Returns a catalog of all available slide layouts. Each entry includes:
|
|
51
|
-
- `slideId` — the ID to reference this layout
|
|
52
|
-
- Text fields — editable TEXT nodes with their names and current content
|
|
53
|
-
- Image placeholders — FRAME nodes with IMAGE fill (these need a real image)
|
|
54
|
-
|
|
55
|
-
**Read the catalog carefully before picking layouts:**
|
|
56
|
-
- Match each slide's purpose to your content (the existing text in the template is a strong hint — e.g. "Use this slide to introduce the big problem" → use for your problem statement)
|
|
57
|
-
- Slides with image placeholders need an appropriate image — the surrounding text should describe what's shown in that image
|
|
58
|
-
- Slides with `SHAPE_WITH_TEXT` pill labels (MONTH XX YEAR, TAGLINE, CONFIDENTIAL) cannot be changed programmatically — tell the user to update those in Figma
|
|
59
|
-
|
|
60
|
-
### Step 2 — Create the deck
|
|
61
|
-
|
|
62
|
-
```
|
|
63
|
-
figmatk_create_from_template({
|
|
64
|
-
template: "/path/to/template.deck",
|
|
65
|
-
output: "/tmp/my-deck.deck",
|
|
66
|
-
slides: [
|
|
67
|
-
{ slideId: "1:74", text: { "Title": "My Company" } },
|
|
68
|
-
{ slideId: "1:112", text: { "Header 1": "The problem.", "Body 1": "Description here." } },
|
|
69
|
-
{ slideId: "1:643", text: { "Thank you": "Thank you!" } }
|
|
70
|
-
]
|
|
71
|
-
})
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Only pass text fields that exist in the layout's catalog — extra fields are silently ignored.
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## Path A — Create from Scratch (MCP tool — no template)
|
|
79
|
-
|
|
80
|
-
**Always use this path.** No npm install, no scripts, no workspace setup.
|
|
81
|
-
|
|
82
|
-
Call `figmatk_create_deck` with a structured slide description:
|
|
83
|
-
|
|
84
|
-
```json
|
|
85
|
-
{
|
|
86
|
-
"output": "/tmp/my-deck.deck",
|
|
87
|
-
"title": "My Presentation",
|
|
88
|
-
"theme": "midnight",
|
|
89
|
-
"slides": [
|
|
90
|
-
{ "type": "title", "title": "My Presentation", "subtitle": "A subtitle" },
|
|
91
|
-
{ "type": "bullets", "title": "Key Points", "bullets": ["Point one", "Point two", "Point three"] },
|
|
92
|
-
{ "type": "two-column", "title": "Comparison", "leftText": "Left side content", "rightText": "Right side content" },
|
|
93
|
-
{ "type": "stat", "title": "By the numbers", "stat": "42%", "caption": "of users prefer this" },
|
|
94
|
-
{ "type": "image-full", "image": "/tmp/photo.jpg", "title": "Caption text" },
|
|
95
|
-
{ "type": "closing", "title": "Thank you", "subtitle": "Questions?" }
|
|
96
|
-
]
|
|
97
|
-
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### Slide types
|
|
101
|
-
|
|
102
|
-
| Type | Fields |
|
|
103
|
-
|------|--------|
|
|
104
|
-
| `title` | `title`, `subtitle` |
|
|
105
|
-
| `bullets` | `title`, `bullets` (array) |
|
|
106
|
-
| `two-column` | `title`, `leftText`, `rightText`, `image` (right side) |
|
|
107
|
-
| `stat` | `title`, `stat` (big number), `caption` |
|
|
108
|
-
| `image-full` | `image` (path), `title`, `body` (overlay text) |
|
|
109
|
-
| `closing` | `title`, `subtitle` |
|
|
110
|
-
|
|
111
|
-
### Themes
|
|
112
|
-
|
|
113
|
-
`midnight` · `ocean` · `forest` · `coral` · `terracotta` · `minimal`
|
|
114
|
-
|
|
115
|
-
Each theme handles backgrounds, accent colors, and text colors automatically.
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
## Path A2 — Create from Scratch (Node.js script fallback)
|
|
120
|
-
|
|
121
|
-
Only use this if `figmatk_create_deck` is unavailable or you need layout control beyond what the MCP tool offers.
|
|
122
|
-
|
|
123
|
-
### Step 1 — Set up workspace (MANDATORY — never skip)
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
[ -d /tmp/figmatk-ws/node_modules ] || (mkdir -p /tmp/figmatk-ws && cd /tmp/figmatk-ws && npm init -y && npm install figmatk)
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Step 2 — Write script to `/tmp/figmatk-ws/deck.mjs`
|
|
130
|
-
|
|
131
|
-
**Always use bare specifier** `import { Deck } from 'figmatk'` — never a file path.
|
|
37
|
+
> **Import path:** `figmatk` is an npm package. Import from the installed package:
|
|
38
|
+
> ```javascript
|
|
39
|
+
> import { Deck } from 'figmatk';
|
|
40
|
+
> ```
|
|
132
41
|
|
|
133
42
|
```javascript
|
|
134
43
|
import { Deck } from 'figmatk';
|
|
135
44
|
|
|
136
|
-
function hex(h) {
|
|
137
|
-
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 };
|
|
138
|
-
}
|
|
139
|
-
|
|
140
45
|
const deck = await Deck.create('My Presentation');
|
|
141
|
-
const slide = deck.addBlankSlide();
|
|
142
|
-
slide.setBackground('Black');
|
|
143
|
-
slide.addText('Slide Title', { style: 'Title', color: 'White', x: 64, y: 80, width: 1792, align: 'LEFT' });
|
|
144
|
-
await deck.save('/tmp/my-presentation.deck');
|
|
145
|
-
console.log('Done');
|
|
146
|
-
```
|
|
147
46
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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');
|
|
152
59
|
```
|
|
153
60
|
|
|
154
61
|
### ⚠️ Critical gotchas
|
|
@@ -158,11 +65,9 @@ node /tmp/figmatk-ws/deck.mjs
|
|
|
158
65
|
| `setBackground` with hex | `s.setBackground('#1A1A1A')` | `s.setBackground('Black')` |
|
|
159
66
|
| `setBackground` with raw RGB | `s.setBackground({ r:0.1, g:0.1, b:0.1 })` | `s.setBackground('Black')` — raw RGB silently renders white |
|
|
160
67
|
| Shape method signature | `s.addRectangle({ x:0, y:0, width:100 })` | `s.addRectangle(0, 0, 100, 100, opts)` |
|
|
161
|
-
| Shape fill color | `{ fill:
|
|
68
|
+
| Shape fill color | `{ fill: '#F4900C' }` | `{ fill: hex('#F4900C') }` — use the hex() helper |
|
|
162
69
|
| `addLine` options | `{ strokeColor: ..., strokeWeight: 2 }` | `{ color: 'Black', weight: 2 }` |
|
|
163
70
|
| `align` value | `align: 'left'` | `align: 'LEFT'` (uppercase) |
|
|
164
|
-
| `addImage` without await | `slide.addImage('/tmp/photo.jpg')` | `await slide.addImage('/tmp/photo.jpg')` — async, images silently missing without await |
|
|
165
|
-
| `addImage` old signature | `await slide.addImage(x, y, w, h, path)` | `await slide.addImage(path, { x, y, width, height })` — path is first arg now |
|
|
166
71
|
|
|
167
72
|
### Hex color helper (for shape fills)
|
|
168
73
|
|
|
@@ -186,17 +91,13 @@ function hex(h) {
|
|
|
186
91
|
| `Body 3` | 24pt | Regular | Captions, labels |
|
|
187
92
|
| `Note` | 20pt | Regular | Footnotes, sources |
|
|
188
93
|
|
|
189
|
-
###
|
|
190
|
-
|
|
191
|
-
Accepts named colors, hex strings, or designer aliases — **when using figmatk 0.0.12+ from the workspace install**.
|
|
94
|
+
### Named colors for `setBackground()`
|
|
192
95
|
|
|
193
|
-
|
|
96
|
+
> **Case-sensitive.** `'Black'` works, `'black'` does not.
|
|
194
97
|
|
|
195
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'`
|
|
196
99
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
**Designer aliases** (0.0.12+): `slide.setBackground('navy')`, `slide.setBackground('coral')`, `slide.setBackground('terracotta')` etc.
|
|
100
|
+
Use `'Black'` for dark backgrounds, `'White'` for light. For custom slide backgrounds, use the closest named color — **not hex**.
|
|
200
101
|
|
|
201
102
|
### Slide dimensions
|
|
202
103
|
|
|
@@ -214,8 +115,8 @@ slide.addDiamond(x, y, width, height, opts)
|
|
|
214
115
|
slide.addTriangle(x, y, width, height, opts)
|
|
215
116
|
slide.addStar(x, y, width, height, opts)
|
|
216
117
|
slide.addLine(x1, y1, x2, y2, opts) // opts: color, weight
|
|
217
|
-
|
|
218
|
-
slide.addTable(
|
|
118
|
+
slide.addImage(path, opts) // opts: x, y, width, height
|
|
119
|
+
slide.addTable(data, opts) // 2D string array; opts: x, y, width, colWidths, rowHeight
|
|
219
120
|
slide.addSVG(x, y, width, svgPathOrBuf, opts)
|
|
220
121
|
```
|
|
221
122
|
|
|
@@ -240,7 +141,6 @@ Use this when the user provides a `.deck` file to modify.
|
|
|
240
141
|
|
|
241
142
|
| Tool | Purpose |
|
|
242
143
|
|------|---------|
|
|
243
|
-
| `figmatk_create_deck` | **Create a new deck from scratch** — no npm install needed |
|
|
244
144
|
| `figmatk_inspect` | Node hierarchy tree — structure, node IDs, slide count |
|
|
245
145
|
| `figmatk_list_text` | All text strings and image hashes per slide |
|
|
246
146
|
| `figmatk_list_overrides` | Editable override keys per symbol (component) |
|
|
@@ -249,37 +149,55 @@ Use this when the user provides a `.deck` file to modify.
|
|
|
249
149
|
| `figmatk_clone_slide` | Deep-clone a slide with new text and images |
|
|
250
150
|
| `figmatk_remove_slide` | Mark slides as REMOVED (never deleted) |
|
|
251
151
|
| `figmatk_roundtrip` | Decode + re-encode for pipeline validation |
|
|
152
|
+
| `figmatk_render_slide` | Render a slide to image (inline WebP or saved PNG) |
|
|
252
153
|
|
|
253
154
|
---
|
|
254
155
|
|
|
255
|
-
##
|
|
256
|
-
|
|
257
|
-
Think like a **professional PowerPoint designer**, not an AI generating slides. Every deck must feel like it was made by a human who spent a day on it.
|
|
156
|
+
## Path C — Visual QA (Render + Inspect)
|
|
258
157
|
|
|
259
|
-
|
|
158
|
+
After creating or modifying a deck, **always render and visually inspect** the output. This catches issues that text inspection misses: overflowing text, broken layouts, wrong colors, misaligned elements.
|
|
260
159
|
|
|
261
|
-
|
|
160
|
+
### Workflow
|
|
262
161
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
162
|
+
1. Render each slide at preview size (returns inline WebP image):
|
|
163
|
+
```
|
|
164
|
+
figmatk_render_slide(path: "/tmp/my-deck.deck", slide: 1)
|
|
165
|
+
```
|
|
166
|
+
2. Inspect the returned image for:
|
|
167
|
+
- Text overflowing its bounding box or clipped
|
|
168
|
+
- Layout misalignment or overlapping elements
|
|
169
|
+
- Wrong colors or missing backgrounds
|
|
170
|
+
- Missing images or broken fills
|
|
171
|
+
3. If issues are found, fix them and re-render
|
|
172
|
+
4. For full-resolution export:
|
|
173
|
+
```
|
|
174
|
+
figmatk_render_slide(path: "/tmp/my-deck.deck", slide: 1, output: "/tmp/slide-1.png")
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Render options
|
|
178
|
+
|
|
179
|
+
| Option | Example | Effect |
|
|
180
|
+
|--------|---------|--------|
|
|
181
|
+
| (none) | `slide: 1` | Inline WebP at 800px wide (for QA) |
|
|
182
|
+
| `width` | `width: 400` | Resize to 400px wide (proportional) |
|
|
183
|
+
| `scale` | `scale: "50%"` | Half size (960×540) |
|
|
184
|
+
| `output` | `output: "/tmp/s.png"` | Save full PNG to disk |
|
|
185
|
+
|
|
186
|
+
### CLI alternative
|
|
270
187
|
|
|
271
|
-
|
|
188
|
+
```bash
|
|
189
|
+
figmatk render my-deck.deck -o /tmp/renders/ # all slides
|
|
190
|
+
figmatk render my-deck.deck -o /tmp/renders/ --slide 3 # single slide
|
|
191
|
+
figmatk render my-deck.deck -o /tmp/renders/ --width 400 # thumbnail size
|
|
192
|
+
```
|
|
272
193
|
|
|
273
|
-
|
|
194
|
+
**Important:** Always run visual QA on every deck you create or modify. Do not skip this step.
|
|
274
195
|
|
|
275
|
-
|
|
196
|
+
---
|
|
276
197
|
|
|
277
|
-
|
|
278
|
-
- **Left colour panel**: tall rectangle on the left third, text floats right
|
|
279
|
-
- **Corner badge**: small filled circle or square in bottom-right with slide number or logo
|
|
280
|
-
- **Bottom rule**: thin full-width line at y=1040
|
|
198
|
+
## Design Philosophy
|
|
281
199
|
|
|
282
|
-
|
|
200
|
+
Every deck must look **intentionally designed**, not AI-generated.
|
|
283
201
|
|
|
284
202
|
### Colour
|
|
285
203
|
|
|
@@ -298,29 +216,18 @@ Without a motif, slides look unrelated. With one, the deck feels designed.
|
|
|
298
216
|
| Ocean | `'Blue'` | `hex('#21295C')` | `'White'` |
|
|
299
217
|
| Minimal | `'White'` | `hex('#36454F')` | `'Black'` |
|
|
300
218
|
|
|
301
|
-
### Layout
|
|
302
|
-
|
|
303
|
-
Each content slide should use a **different layout type**. Never repeat the same structure back-to-back.
|
|
219
|
+
### Layout
|
|
304
220
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
| 2×2 or 2×3 grid | Features, icons, categories |
|
|
309
|
-
| Large stat callout | One big number + explanation |
|
|
310
|
-
| Half-background image | Photo-rich slides |
|
|
311
|
-
| Timeline / steps | Process, history, roadmap |
|
|
312
|
-
| Icon + text rows | Lists that need visual weight |
|
|
313
|
-
| Full-bleed image | Impact moment, section break |
|
|
221
|
+
- Every slide needs at least **one visual element** — shape, image, SVG, or table.
|
|
222
|
+
- **Vary layouts** — never repeat the same structure slide after slide.
|
|
223
|
+
- Carry one visual motif through every slide (coloured accent bar, icon circles, etc.).
|
|
314
224
|
|
|
315
|
-
|
|
225
|
+
**Layout options:** two-column, icon+text rows, 2×2/2×3 grid, large stat callout, half-background image, timeline/steps.
|
|
316
226
|
|
|
317
227
|
### Typography
|
|
318
228
|
|
|
319
|
-
- Left-align body text. Centre only titles
|
|
229
|
+
- Left-align body text. Centre only titles.
|
|
320
230
|
- Minimum 64px margin from slide edges. 24–48px between content blocks.
|
|
321
|
-
- Use `Header 2` or `Header 3` for slide titles on content slides (not `Title` — that's for the title slide only).
|
|
322
|
-
- **Body text: max 2 sentences per text block.** Text boxes have fixed heights — overflow gets clipped. If you have more to say, use a bullet list or split across slides.
|
|
323
|
-
- **Bullets: max 6 items, max 8 words per bullet.** Longer bullets wrap and push content off-slide.
|
|
324
231
|
|
|
325
232
|
### Never do
|
|
326
233
|
|
|
@@ -328,17 +235,17 @@ Every slide needs at least **one visual element** — shape, image, SVG, or tabl
|
|
|
328
235
|
- Centre body text
|
|
329
236
|
- Use accent lines under slide titles (hallmark of AI-generated slides)
|
|
330
237
|
- Text-only slides
|
|
331
|
-
- Low-contrast text against background
|
|
332
|
-
- Skip the closing slide — it makes the deck feel unfinished
|
|
333
|
-
- Put long paragraphs in body/caption fields — text overflows the container
|
|
238
|
+
- Low-contrast text against background
|
|
334
239
|
|
|
335
240
|
---
|
|
336
241
|
|
|
337
242
|
## QA
|
|
338
243
|
|
|
339
244
|
1. Self-check: no placeholder text (`lorem ipsum`, `[title here]`) remains
|
|
340
|
-
2.
|
|
341
|
-
3.
|
|
245
|
+
2. **Render every slide** using `figmatk_render_slide` and visually inspect for overflows, clipping, alignment, and color issues
|
|
246
|
+
3. Fix any issues found and re-render to confirm
|
|
247
|
+
4. Tell the user to open the `.deck` in Figma Desktop for final review
|
|
248
|
+
5. Offer to fix anything they report
|
|
342
249
|
|
|
343
250
|
---
|
|
344
251
|
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: figma-template-builder
|
|
3
|
+
description: >
|
|
4
|
+
Author reusable Figma Slides templates as .deck files. Use when the user
|
|
5
|
+
wants to build a template from reference images or examples, derive a new
|
|
6
|
+
template from an existing deck, define reusable layouts, mark editable
|
|
7
|
+
text/image slots, or prepare a draft template for later instantiation.
|
|
8
|
+
metadata:
|
|
9
|
+
version: "0.3.7"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Figma Template Builder
|
|
13
|
+
|
|
14
|
+
Use this skill when the goal is to build or refine the template itself. For the common workflow of taking an existing template and producing a new presentation, use `skills/figma-slides-creator/SKILL.md`.
|
|
15
|
+
|
|
16
|
+
## MCP First
|
|
17
|
+
|
|
18
|
+
In Claude Cowork, keep template authoring inside the MCP plugin.
|
|
19
|
+
|
|
20
|
+
- Do not inspect the installed `figmatk` package to discover template features.
|
|
21
|
+
- Do not write direct Node.js scripts for draft creation, annotation, wrapping, or instantiation when MCP tools exist for those steps.
|
|
22
|
+
- Prefer `figmatk_create_template_draft`, `figmatk_annotate_template_layout`, `figmatk_publish_template_draft`, and `figmatk_list_template_layouts`.
|
|
23
|
+
|
|
24
|
+
Only fall back to direct library code if the MCP server is unavailable or the required capability is missing from the MCP surface.
|
|
25
|
+
|
|
26
|
+
## Skill Boundary
|
|
27
|
+
|
|
28
|
+
Use this skill when the deliverable is a reusable template, not a one-off deck.
|
|
29
|
+
|
|
30
|
+
Stay here when the user wants to:
|
|
31
|
+
|
|
32
|
+
- translate reference images or screenshots into template layouts
|
|
33
|
+
- create a new layout family
|
|
34
|
+
- define placeholder semantics for later sessions
|
|
35
|
+
- turn an ordinary deck into a reusable template
|
|
36
|
+
|
|
37
|
+
Hand off to `skills/figma-slides-creator/SKILL.md` once the template exists and the task becomes simple content population.
|
|
38
|
+
|
|
39
|
+
## Core Model
|
|
40
|
+
|
|
41
|
+
Template work happens in two states:
|
|
42
|
+
|
|
43
|
+
- Draft template: `SLIDE_ROW -> SLIDE -> ...`
|
|
44
|
+
- Published or publish-like template: `SLIDE_ROW -> MODULE -> SLIDE -> ...`
|
|
45
|
+
|
|
46
|
+
Draft templates are easier to author. Publish-like wrapping is the final step before later instantiation.
|
|
47
|
+
|
|
48
|
+
## Design-First Workflow
|
|
49
|
+
|
|
50
|
+
When the user provides reference images, screenshots, or example decks:
|
|
51
|
+
|
|
52
|
+
1. Read the references first and infer the layout family before touching the `.deck`.
|
|
53
|
+
2. Decide which parts are reusable structure versus one-off sample content.
|
|
54
|
+
3. Create only the smallest set of layouts that captures the system.
|
|
55
|
+
4. Use semantic slot names so later sessions can populate them without re-reading the design intent.
|
|
56
|
+
|
|
57
|
+
Do not mirror every visual variation as its own layout unless the content structure changes materially.
|
|
58
|
+
|
|
59
|
+
## Naming Conventions
|
|
60
|
+
|
|
61
|
+
Always use explicit metadata when authoring reusable layouts:
|
|
62
|
+
|
|
63
|
+
- Layouts: `layout:<name>`
|
|
64
|
+
- Text slots: `slot:text:<name>`
|
|
65
|
+
- Image slots: `slot:image:<name>`
|
|
66
|
+
- Decorative fixed imagery: `fixed:image:<name>`
|
|
67
|
+
|
|
68
|
+
These conventions are how later sessions discover what is editable.
|
|
69
|
+
|
|
70
|
+
Prefer semantic names over visual or auto-generated names.
|
|
71
|
+
|
|
72
|
+
Good:
|
|
73
|
+
|
|
74
|
+
- `title`
|
|
75
|
+
- `subtitle`
|
|
76
|
+
- `hero_image`
|
|
77
|
+
- `device_screen_primary`
|
|
78
|
+
- `quote_author`
|
|
79
|
+
|
|
80
|
+
Bad:
|
|
81
|
+
|
|
82
|
+
- `text1`
|
|
83
|
+
- `frame183`
|
|
84
|
+
- `image-left`
|
|
85
|
+
- `rectangle2`
|
|
86
|
+
|
|
87
|
+
## Recommended Flow
|
|
88
|
+
|
|
89
|
+
### 1. Create or inspect a draft template
|
|
90
|
+
|
|
91
|
+
- New draft from scratch: `figmatk_create_template_draft`
|
|
92
|
+
- Existing deck/template: `figmatk_list_template_layouts`
|
|
93
|
+
- Structural inspection: `figmatk_inspect`
|
|
94
|
+
|
|
95
|
+
### 2. Annotate reusable layouts
|
|
96
|
+
|
|
97
|
+
Use `figmatk_annotate_template_layout` to:
|
|
98
|
+
|
|
99
|
+
- rename a slide as a layout
|
|
100
|
+
- mark text nodes as editable text slots
|
|
101
|
+
- mark image-bearing nodes as editable image slots
|
|
102
|
+
- mark decorative imagery as fixed
|
|
103
|
+
|
|
104
|
+
The tool accepts node ID maps, so inspect first if you need the raw node IDs.
|
|
105
|
+
|
|
106
|
+
While annotating:
|
|
107
|
+
|
|
108
|
+
- rename the slide itself to the stable layout name
|
|
109
|
+
- mark only true placeholders as `slot:*`
|
|
110
|
+
- mark decorative or sample imagery as `fixed:image:*`
|
|
111
|
+
- prefer stable semantic names over spatial names like `left_box`
|
|
112
|
+
|
|
113
|
+
### 3. Publish-wrap when the template is ready
|
|
114
|
+
|
|
115
|
+
Use `figmatk_publish_template_draft` to add publish-like `MODULE` wrappers while preserving the slide subtree and internal assets.
|
|
116
|
+
|
|
117
|
+
### 4. Verify the result
|
|
118
|
+
|
|
119
|
+
- `figmatk_list_template_layouts`
|
|
120
|
+
- `figmatk_list_text`
|
|
121
|
+
- `figmatk_roundtrip` if you want a conservative encode/decode check
|
|
122
|
+
- open the wrapped template in Figma Desktop when validating real upload behavior
|
|
123
|
+
|
|
124
|
+
## Practical Rules
|
|
125
|
+
|
|
126
|
+
- Prefer explicit slot names over heuristic placeholders.
|
|
127
|
+
- Do not assume every image fill is editable content.
|
|
128
|
+
- Preserve `Internal Only Canvas` assets.
|
|
129
|
+
- Preserve special nodes such as device mockups and interactive slide elements; do not try to recreate them from scratch unless necessary.
|
|
130
|
+
|
|
131
|
+
## Template Authoring Heuristics
|
|
132
|
+
|
|
133
|
+
- Start with 4-8 reusable layouts, not an exhaustive library.
|
|
134
|
+
- Reuse one layout when only copy length changes; create a new layout when hierarchy or media structure changes.
|
|
135
|
+
- Separate content slots from chrome. For device mockups, the screen is usually the slot and the hardware frame is usually fixed.
|
|
136
|
+
- If a layout has explicit slot metadata, do not rely on heuristic image placeholders for that layout.
|
|
137
|
+
- After publish-wrapping, re-run `figmatk_list_template_layouts` and confirm the layout names and slot names survived unchanged.
|
|
138
|
+
|
|
139
|
+
## Example
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"path": "/tmp/draft-template.deck",
|
|
144
|
+
"output": "/tmp/draft-template-annotated.deck",
|
|
145
|
+
"slideId": "1:42",
|
|
146
|
+
"layoutName": "cover",
|
|
147
|
+
"textSlots": {
|
|
148
|
+
"1:120": "title",
|
|
149
|
+
"1:121": "subtitle"
|
|
150
|
+
},
|
|
151
|
+
"imageSlots": {
|
|
152
|
+
"1:144": "hero_image"
|
|
153
|
+
},
|
|
154
|
+
"fixedImages": {
|
|
155
|
+
"1:199": "background_texture"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|