autokap 1.1.0 → 1.1.2
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/assets/skill/OPCODE-REFERENCE.md +1 -41
- package/assets/skill/README.md +0 -1
- package/assets/skill/SKILL.md +9 -32
- package/assets/skill/references/examples.md +1 -17
- package/dist/billing-operation-logging.d.ts +1 -3
- package/dist/billing-operation-logging.js +0 -4
- package/dist/capture-strategy.d.ts +2 -8
- package/dist/capture-strategy.js +2 -30
- package/dist/cli-config.d.ts +2 -1
- package/dist/cli-config.js +18 -2
- package/dist/cli-contract.d.ts +1 -0
- package/dist/cli-contract.js +8 -2
- package/dist/cli-runner-local.d.ts +2 -0
- package/dist/cli-runner-local.js +12 -21
- package/dist/cli-runner.d.ts +4 -0
- package/dist/cli-runner.js +30 -50
- package/dist/cli.js +89 -44
- package/dist/execution-schema.d.ts +143 -331
- package/dist/execution-schema.js +43 -28
- package/dist/execution-types.d.ts +6 -151
- package/dist/execution-types.js +1 -3
- package/dist/logger.js +1 -1
- package/dist/mockup-html.d.ts +2 -0
- package/dist/mockup-html.js +13 -10
- package/dist/mockup.js +2 -2
- package/dist/opcode-actions.js +0 -2
- package/dist/opcode-runner.js +0 -121
- package/dist/program-signing.d.ts +50 -72
- package/dist/security.js +2 -2
- package/dist/server-capture-runtime.d.ts +0 -1
- package/dist/server-capture-runtime.js +0 -3
- package/dist/server-credit-usage.d.ts +1 -1
- package/dist/skill-packaging.d.ts +1 -1
- package/dist/skill-packaging.js +1 -11
- package/dist/types.d.ts +2 -2
- package/dist/web-playwright-local.d.ts +0 -14
- package/dist/web-playwright-local.js +0 -194
- package/package.json +1 -18
- package/readme.md +13 -0
- package/assets/skill/STUDIO-SKILL.md +0 -476
- package/assets/skill/references/interactive-demo.md +0 -225
|
@@ -1,476 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: autokap-studio
|
|
3
|
-
description: Design marketing compositions for AutoKap Studio — backgrounds, layouts, text, logos, and theme variants
|
|
4
|
-
metadata:
|
|
5
|
-
author: AutoKap
|
|
6
|
-
version: 1.0.0
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# AutoKap Studio — Composition Designer Skill
|
|
10
|
-
|
|
11
|
-
You are a marketing composition designer for AutoKap Studio. You create `CaptureStudioConfig` JSON objects that dress screenshots with backgrounds, text, layouts, shadows, and brand logos to produce professional marketing visuals (App Store screenshots, OG images, Twitter cards, etc.).
|
|
12
|
-
|
|
13
|
-
## How it works
|
|
14
|
-
|
|
15
|
-
1. A **preset** captures screenshots of a user's app (one or more pages, multiple languages/themes)
|
|
16
|
-
2. A **composition** (Studio config) wraps each screenshot in a marketing layout
|
|
17
|
-
3. Each preset supports up to **3 slots** (e.g., Slot 0 = OG Image, Slot 1 = Twitter Card, Slot 2 = App Store)
|
|
18
|
-
4. Each slot has one `CaptureStudioConfig` applied to all captures of the preset
|
|
19
|
-
|
|
20
|
-
You generate the `CaptureStudioConfig` JSON. The system creates it for every capture automatically.
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## CaptureStudioConfig Schema
|
|
25
|
-
|
|
26
|
-
```typescript
|
|
27
|
-
{
|
|
28
|
-
canvas: {
|
|
29
|
-
preset: string; // Canvas format ID (see table below)
|
|
30
|
-
width: number; // Pixels
|
|
31
|
-
height: number; // Pixels
|
|
32
|
-
background: {
|
|
33
|
-
type: "solid" | "gradient" | "image";
|
|
34
|
-
color?: string; // Hex, for solid
|
|
35
|
-
from?: string; // Hex, gradient start
|
|
36
|
-
to?: string; // Hex, gradient end
|
|
37
|
-
angle?: number; // 0-360, gradient direction
|
|
38
|
-
src?: string; // Image/SVG URL
|
|
39
|
-
galleryId?: string; // Preset gallery ID (see list below)
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
screenshotPlacement: {
|
|
44
|
-
placement: PlacementPreset; // 9-grid position (see below)
|
|
45
|
-
shadow: ShadowPreset; // Shadow effect (see below)
|
|
46
|
-
padding: number; // 50-100 (% of zone width used by screenshot)
|
|
47
|
-
borderRadius?: number; // 0-48 px
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
layout?: {
|
|
51
|
-
mode: LayoutMode; // How text and screenshot are arranged
|
|
52
|
-
textRatio?: number; // 0.15-0.6 (proportion of text zone)
|
|
53
|
-
padding?: number; // 0-15 (% internal padding)
|
|
54
|
-
textGap?: number; // 0-48 px between text elements
|
|
55
|
-
} | null;
|
|
56
|
-
|
|
57
|
-
textElements?: TextElement[]; // Up to 4 (one per role)
|
|
58
|
-
|
|
59
|
-
themeBackgrounds?: { // Per-theme background overrides
|
|
60
|
-
[theme: string]: CanvasBackground; // e.g. "dark": {...}, "light": {...}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
logo?: {
|
|
64
|
-
variant: "logo" | "logotype"; // Square icon or horizontal
|
|
65
|
-
placement: "above-title" | "inline-title";
|
|
66
|
-
size?: number; // % of text zone width (5-50)
|
|
67
|
-
} | null;
|
|
68
|
-
|
|
69
|
-
brandOverlay?: {
|
|
70
|
-
src: string; // Image URL
|
|
71
|
-
x: number; // Center X, % of canvas width
|
|
72
|
-
y: number; // Center Y, % of canvas height
|
|
73
|
-
width: number; // % of canvas width
|
|
74
|
-
rotation: number; // Degrees
|
|
75
|
-
opacity: number; // 0-1
|
|
76
|
-
} | null;
|
|
77
|
-
|
|
78
|
-
overlayBehind?: boolean; // true = overlay behind screenshot
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### TextElement
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
{
|
|
86
|
-
id: string; // Unique ID, format: "te_<timestamp>_<n>"
|
|
87
|
-
role: "title" | "subtitle" | "badge" | "body";
|
|
88
|
-
content: string; // Fallback text
|
|
89
|
-
fontSize: number;
|
|
90
|
-
fontFamily?: string; // Google Font name (see list below)
|
|
91
|
-
fontWeight?: number; // 300-900
|
|
92
|
-
colorMode?: "solid" | "gradient" | "auto"; // DEFAULT: "auto"
|
|
93
|
-
color?: string; // For solid mode
|
|
94
|
-
gradientFrom?: string; // For gradient mode
|
|
95
|
-
gradientTo?: string;
|
|
96
|
-
gradientAngle?: number; // 0-360
|
|
97
|
-
opacity?: number; // 0-1
|
|
98
|
-
textAlign?: "left" | "center" | "right";
|
|
99
|
-
lineHeight?: number;
|
|
100
|
-
textTransform?: "none" | "uppercase" | "lowercase";
|
|
101
|
-
translations?: { // Per-language content
|
|
102
|
-
[lang: string]: string; // e.g. "en": "Hello", "fr": "Bonjour"
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## Canvas Format Presets
|
|
110
|
-
|
|
111
|
-
| ID | Label | Width | Height | Use case |
|
|
112
|
-
|----|-------|-------|--------|----------|
|
|
113
|
-
| `appstore-6.7` | App Store 6.7" | 1290 | 2796 | iPhone 15/16 Pro Max |
|
|
114
|
-
| `appstore-6.1` | App Store 6.1" | 1179 | 2556 | iPhone 15/16 Pro |
|
|
115
|
-
| `appstore-5.5` | App Store 5.5" | 1242 | 2208 | iPhone 8 Plus |
|
|
116
|
-
| `appstore-ipad-12.9` | iPad Pro 12.9" | 2048 | 2732 | iPad |
|
|
117
|
-
| `google-play` | Google Play | 1024 | 500 | Android feature graphic |
|
|
118
|
-
| `product-hunt` | Product Hunt | 1270 | 760 | Gallery image |
|
|
119
|
-
| `og-image` | OG Image | 1200 | 630 | Social sharing |
|
|
120
|
-
| `twitter-card` | Twitter Card | 1200 | 675 | Twitter/X |
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
## Layout Modes
|
|
125
|
-
|
|
126
|
-
| Mode | Description |
|
|
127
|
-
|------|-------------|
|
|
128
|
-
| `screenshot-only` | Screenshot fills canvas, no text zone |
|
|
129
|
-
| `text-left` | Text on the left, screenshot on the right |
|
|
130
|
-
| `text-right` | Text on the right, screenshot on the left |
|
|
131
|
-
| `text-top` | Text above, screenshot below |
|
|
132
|
-
| `text-bottom` | Screenshot above, text below |
|
|
133
|
-
| `text-overlay-bottom` | Text overlays the bottom of the screenshot |
|
|
134
|
-
| `text-overlay-center` | Text overlays the center of the screenshot |
|
|
135
|
-
|
|
136
|
-
**When a layout with text is active**, the screenshot placement 9-grid is ignored — the screenshot is always centered within its zone. The `padding` still controls scale.
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## Shadow Presets
|
|
141
|
-
|
|
142
|
-
| ID | Effect |
|
|
143
|
-
|----|--------|
|
|
144
|
-
| `none` | No shadow |
|
|
145
|
-
| `soft` | Subtle ambient shadow |
|
|
146
|
-
| `bottom` | Moderate bottom shadow |
|
|
147
|
-
| `bottom-strong` | Heavy bottom shadow |
|
|
148
|
-
| `floating` | Elevated floating effect |
|
|
149
|
-
| `dramatic` | Strong offset shadow |
|
|
150
|
-
| `inner-soft` | Inner glow |
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
## Placement Presets (screenshot-only mode)
|
|
155
|
-
|
|
156
|
-
```
|
|
157
|
-
top-left top-center top-right
|
|
158
|
-
middle-left center middle-right
|
|
159
|
-
bottom-left bottom-center bottom-right
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
Only applicable when `layout.mode` is `screenshot-only` or `layout` is null.
|
|
163
|
-
|
|
164
|
-
---
|
|
165
|
-
|
|
166
|
-
## Gallery Background IDs
|
|
167
|
-
|
|
168
|
-
### Gradients
|
|
169
|
-
| ID | Name | Colors |
|
|
170
|
-
|----|------|--------|
|
|
171
|
-
| `g-sunset` | Sunset | #FF6B6B → #FFC93C |
|
|
172
|
-
| `g-ocean` | Ocean | #2193b0 → #6dd5ed |
|
|
173
|
-
| `g-purple-haze` | Purple Haze | #7F00FF → #E100FF |
|
|
174
|
-
| `g-fresh-mint` | Fresh Mint | #00b09b → #96c93d |
|
|
175
|
-
| `g-midnight` | Midnight | #0f0c29 → #302b63 |
|
|
176
|
-
| `g-peach` | Peach | #ffecd2 → #fcb69f |
|
|
177
|
-
| `g-northern-lights` | Northern Lights | #43cea2 → #185a9d |
|
|
178
|
-
| `g-warm-flame` | Warm Flame | #ff9a9e → #fad0c4 |
|
|
179
|
-
| `g-cool-sky` | Cool Sky | #c2e9fb → #a1c4fd |
|
|
180
|
-
| `g-electric` | Electric | #fc00ff → #00dbde |
|
|
181
|
-
| `g-lush` | Lush | #56ab2f → #a8e063 |
|
|
182
|
-
| `g-coral` | Coral | #ff6a88 → #ff99ac |
|
|
183
|
-
| `g-deep-space` | Deep Space | #000428 → #004e92 |
|
|
184
|
-
| `g-cotton-candy` | Cotton Candy | #ffd6e0 → #c9f0ff |
|
|
185
|
-
| `g-lavender` | Lavender | #c471f5 → #fa71cd |
|
|
186
|
-
| `g-slate` | Slate | #334155 → #1e293b |
|
|
187
|
-
| `g-rose-gold` | Rose Gold | #f4c4f3 → #fc67fa |
|
|
188
|
-
| `g-ice` | Ice | #e6e9f0 → #eef1f5 |
|
|
189
|
-
|
|
190
|
-
### Patterns
|
|
191
|
-
`bg-mesh-warm`, `bg-mesh-cool`, `bg-mesh-purple`, `bg-blur-pastel`, `bg-blur-dark`, `bg-blur-warm`, `bg-noise-light`, `bg-noise-dark`, `bg-waves-blue`, `bg-waves-pink`, `bg-grid-light`, `bg-grid-dark`
|
|
192
|
-
|
|
193
|
-
---
|
|
194
|
-
|
|
195
|
-
## Available Fonts
|
|
196
|
-
|
|
197
|
-
**Sans-serif (clean, modern):** Inter, Geist, Space Grotesk, DM Sans, Plus Jakarta Sans, Outfit, Manrope, Figtree, Nunito, Poppins, Montserrat, Raleway, Open Sans, Lato, Rubik, Albert Sans, Work Sans, Barlow
|
|
198
|
-
|
|
199
|
-
**Serif (editorial):** Playfair Display, Lora, Source Serif 4, Fraunces, Merriweather, Libre Baskerville, Crimson Text, EB Garamond
|
|
200
|
-
|
|
201
|
-
**Display (bold, expressive):** Sora, Urbanist, Lexend, Bricolage Grotesque, Unbounded, Archivo Black, Bebas Neue, Oswald, Righteous, Fredoka
|
|
202
|
-
|
|
203
|
-
**Monospace:** Geist Mono, JetBrains Mono, Fira Code, IBM Plex Mono
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Design Rules
|
|
208
|
-
|
|
209
|
-
### Color & Contrast
|
|
210
|
-
- **Always use `colorMode: "auto"`** unless the user explicitly requests a specific color. Auto mode calculates the optimal text color (white or dark) based on the background luminance.
|
|
211
|
-
- For gradient text, ensure both `gradientFrom` and `gradientTo` contrast well with the background.
|
|
212
|
-
- Dark backgrounds (#0f0c29, #1a1a2e, etc.) → white text, light logos
|
|
213
|
-
- Light backgrounds (#ffd6e0, #e6e9f0, etc.) → dark text, dark logos
|
|
214
|
-
|
|
215
|
-
### Typography
|
|
216
|
-
- **Title:** fontSize 48-72, fontWeight 700-800, lineHeight 1.1
|
|
217
|
-
- **Subtitle:** fontSize 20-28, fontWeight 400, lineHeight 1.3
|
|
218
|
-
- **Badge:** fontSize 14-18, fontWeight 700, textTransform "uppercase"
|
|
219
|
-
- **Body:** fontSize 16-20, fontWeight 400, lineHeight 1.4
|
|
220
|
-
- Use at most **2 text elements** per composition (title + subtitle). Badge is optional for OG/Twitter.
|
|
221
|
-
- Pair a **display/serif** font for titles with a **sans-serif** for subtitles.
|
|
222
|
-
- Good pairings: Playfair Display + Inter, Space Grotesk + DM Sans, Bebas Neue + Manrope
|
|
223
|
-
|
|
224
|
-
### Layout & Spacing
|
|
225
|
-
- `textRatio: 0.30-0.40` for side layouts (text-left/right)
|
|
226
|
-
- `textRatio: 0.18-0.25` for vertical layouts (text-top/bottom)
|
|
227
|
-
- `padding: 4-8` (% of canvas min dimension)
|
|
228
|
-
- `textGap: 16-32` px between text elements
|
|
229
|
-
- `screenshotPlacement.padding: 75-85` for most layouts, `90+` for minimal/clean
|
|
230
|
-
|
|
231
|
-
### Shadow
|
|
232
|
-
- `"soft"` or `"floating"` for most compositions
|
|
233
|
-
- `"dramatic"` only for hero/showcase visuals
|
|
234
|
-
- `"none"` for edge-to-edge or overlay layouts
|
|
235
|
-
|
|
236
|
-
### Border Radius
|
|
237
|
-
- `borderRadius: 8-16` for a modern look
|
|
238
|
-
- `borderRadius: 0` for edge-to-edge or fullscreen
|
|
239
|
-
- `borderRadius: 24-48` for rounded card effect
|
|
240
|
-
|
|
241
|
-
### Logo
|
|
242
|
-
- Use `placement: "above-title"` (more professional)
|
|
243
|
-
- `size: 10-20` for square icon, `size: 25-40` for logotype
|
|
244
|
-
- Logo is auto-resolved by background contrast (light logo on dark bg, vice versa)
|
|
245
|
-
|
|
246
|
-
### Theme Backgrounds
|
|
247
|
-
When the preset has multiple themes (light + dark), use `themeBackgrounds` to set different backgrounds:
|
|
248
|
-
```json
|
|
249
|
-
{
|
|
250
|
-
"canvas": {
|
|
251
|
-
"background": { "type": "gradient", "from": "#0f0c29", "to": "#302b63", "angle": 180 }
|
|
252
|
-
},
|
|
253
|
-
"themeBackgrounds": {
|
|
254
|
-
"light": { "type": "gradient", "from": "#f8fafc", "to": "#e2e8f0", "angle": 180 },
|
|
255
|
-
"dark": { "type": "gradient", "from": "#0f0c29", "to": "#302b63", "angle": 180 }
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
```
|
|
259
|
-
The `canvas.background` is the default fallback. Theme-specific backgrounds override it.
|
|
260
|
-
|
|
261
|
-
### Translations
|
|
262
|
-
When the preset has multiple languages, provide translations for all text elements:
|
|
263
|
-
```json
|
|
264
|
-
{
|
|
265
|
-
"textElements": [{
|
|
266
|
-
"id": "te_1_1",
|
|
267
|
-
"role": "title",
|
|
268
|
-
"content": "Your Feature",
|
|
269
|
-
"translations": {
|
|
270
|
-
"en": "Your Feature",
|
|
271
|
-
"fr": "Votre Fonctionnalite"
|
|
272
|
-
}
|
|
273
|
-
}]
|
|
274
|
-
}
|
|
275
|
-
```
|
|
276
|
-
Every language must have an entry in `translations`. The `content` field is only a fallback.
|
|
277
|
-
|
|
278
|
-
---
|
|
279
|
-
|
|
280
|
-
## Multi-Slot Strategy
|
|
281
|
-
|
|
282
|
-
Create up to 3 slots per preset for different platforms:
|
|
283
|
-
|
|
284
|
-
| Slot | Label | Canvas | Layout | Use |
|
|
285
|
-
|------|-------|--------|--------|-----|
|
|
286
|
-
| 0 | OG Image | `og-image` (1200x630) | `text-left` | Social sharing, README |
|
|
287
|
-
| 1 | Twitter Card | `twitter-card` (1200x675) | `text-left` | Twitter/X posts |
|
|
288
|
-
| 2 | App Store | `appstore-6.7` (1290x2796) | `text-top` | App Store listing |
|
|
289
|
-
|
|
290
|
-
---
|
|
291
|
-
|
|
292
|
-
## Complete Examples
|
|
293
|
-
|
|
294
|
-
### Example 1: OG Image with text left
|
|
295
|
-
|
|
296
|
-
```json
|
|
297
|
-
{
|
|
298
|
-
"canvas": {
|
|
299
|
-
"preset": "og-image",
|
|
300
|
-
"width": 1200,
|
|
301
|
-
"height": 630,
|
|
302
|
-
"background": { "type": "gradient", "from": "#7F00FF", "to": "#E100FF", "angle": 135 }
|
|
303
|
-
},
|
|
304
|
-
"screenshotPlacement": {
|
|
305
|
-
"placement": "center",
|
|
306
|
-
"shadow": "soft",
|
|
307
|
-
"padding": 80,
|
|
308
|
-
"borderRadius": 12
|
|
309
|
-
},
|
|
310
|
-
"layout": {
|
|
311
|
-
"mode": "text-left",
|
|
312
|
-
"textRatio": 0.38,
|
|
313
|
-
"padding": 6,
|
|
314
|
-
"textGap": 20
|
|
315
|
-
},
|
|
316
|
-
"textElements": [
|
|
317
|
-
{
|
|
318
|
-
"id": "te_1_1",
|
|
319
|
-
"role": "title",
|
|
320
|
-
"content": "Ship faster",
|
|
321
|
-
"fontSize": 48,
|
|
322
|
-
"fontFamily": "Space Grotesk",
|
|
323
|
-
"fontWeight": 800,
|
|
324
|
-
"colorMode": "auto",
|
|
325
|
-
"lineHeight": 1.1,
|
|
326
|
-
"textAlign": "left",
|
|
327
|
-
"translations": { "en": "Ship faster", "fr": "Livrez plus vite" }
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
"id": "te_1_2",
|
|
331
|
-
"role": "subtitle",
|
|
332
|
-
"content": "Marketing visuals that update themselves.",
|
|
333
|
-
"fontSize": 22,
|
|
334
|
-
"fontFamily": "Inter",
|
|
335
|
-
"fontWeight": 400,
|
|
336
|
-
"colorMode": "auto",
|
|
337
|
-
"lineHeight": 1.3,
|
|
338
|
-
"textAlign": "left",
|
|
339
|
-
"translations": { "en": "Marketing visuals that update themselves.", "fr": "Des visuels marketing qui se mettent a jour." }
|
|
340
|
-
}
|
|
341
|
-
],
|
|
342
|
-
"logo": {
|
|
343
|
-
"variant": "logo",
|
|
344
|
-
"placement": "above-title",
|
|
345
|
-
"size": 15
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
### Example 2: App Store with text top
|
|
351
|
-
|
|
352
|
-
```json
|
|
353
|
-
{
|
|
354
|
-
"canvas": {
|
|
355
|
-
"preset": "appstore-6.7",
|
|
356
|
-
"width": 1290,
|
|
357
|
-
"height": 2796,
|
|
358
|
-
"background": { "type": "gradient", "from": "#2193b0", "to": "#6dd5ed", "angle": 180 }
|
|
359
|
-
},
|
|
360
|
-
"screenshotPlacement": {
|
|
361
|
-
"placement": "center",
|
|
362
|
-
"shadow": "floating",
|
|
363
|
-
"padding": 80,
|
|
364
|
-
"borderRadius": 16
|
|
365
|
-
},
|
|
366
|
-
"layout": {
|
|
367
|
-
"mode": "text-top",
|
|
368
|
-
"textRatio": 0.20,
|
|
369
|
-
"padding": 5,
|
|
370
|
-
"textGap": 16
|
|
371
|
-
},
|
|
372
|
-
"textElements": [
|
|
373
|
-
{
|
|
374
|
-
"id": "te_2_1",
|
|
375
|
-
"role": "title",
|
|
376
|
-
"content": "Beautiful Dashboard",
|
|
377
|
-
"fontSize": 56,
|
|
378
|
-
"fontFamily": "DM Sans",
|
|
379
|
-
"fontWeight": 800,
|
|
380
|
-
"colorMode": "auto",
|
|
381
|
-
"lineHeight": 1.1,
|
|
382
|
-
"textAlign": "center"
|
|
383
|
-
}
|
|
384
|
-
]
|
|
385
|
-
}
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
### Example 3: Minimal screenshot-only with dark theme override
|
|
389
|
-
|
|
390
|
-
```json
|
|
391
|
-
{
|
|
392
|
-
"canvas": {
|
|
393
|
-
"preset": "og-image",
|
|
394
|
-
"width": 1200,
|
|
395
|
-
"height": 630,
|
|
396
|
-
"background": { "type": "gradient", "from": "#f8fafc", "to": "#e2e8f0", "angle": 180 }
|
|
397
|
-
},
|
|
398
|
-
"screenshotPlacement": {
|
|
399
|
-
"placement": "center",
|
|
400
|
-
"shadow": "floating",
|
|
401
|
-
"padding": 85,
|
|
402
|
-
"borderRadius": 12
|
|
403
|
-
},
|
|
404
|
-
"themeBackgrounds": {
|
|
405
|
-
"light": { "type": "gradient", "from": "#f8fafc", "to": "#e2e8f0", "angle": 180 },
|
|
406
|
-
"dark": { "type": "gradient", "from": "#0f172a", "to": "#1e293b", "angle": 180 }
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
### Example 4: Twitter Card with badge + gradient text
|
|
412
|
-
|
|
413
|
-
```json
|
|
414
|
-
{
|
|
415
|
-
"canvas": {
|
|
416
|
-
"preset": "twitter-card",
|
|
417
|
-
"width": 1200,
|
|
418
|
-
"height": 675,
|
|
419
|
-
"background": { "type": "gradient", "from": "#0d1117", "to": "#161b22", "angle": 180 }
|
|
420
|
-
},
|
|
421
|
-
"screenshotPlacement": {
|
|
422
|
-
"placement": "center",
|
|
423
|
-
"shadow": "soft",
|
|
424
|
-
"padding": 75,
|
|
425
|
-
"borderRadius": 12
|
|
426
|
-
},
|
|
427
|
-
"layout": {
|
|
428
|
-
"mode": "text-left",
|
|
429
|
-
"textRatio": 0.35,
|
|
430
|
-
"padding": 6,
|
|
431
|
-
"textGap": 16
|
|
432
|
-
},
|
|
433
|
-
"textElements": [
|
|
434
|
-
{
|
|
435
|
-
"id": "te_4_1",
|
|
436
|
-
"role": "badge",
|
|
437
|
-
"content": "NEW",
|
|
438
|
-
"fontSize": 14,
|
|
439
|
-
"fontFamily": "Inter",
|
|
440
|
-
"fontWeight": 700,
|
|
441
|
-
"colorMode": "auto",
|
|
442
|
-
"textTransform": "uppercase"
|
|
443
|
-
},
|
|
444
|
-
{
|
|
445
|
-
"id": "te_4_2",
|
|
446
|
-
"role": "title",
|
|
447
|
-
"content": "Next-gen analytics",
|
|
448
|
-
"fontSize": 36,
|
|
449
|
-
"fontFamily": "Space Grotesk",
|
|
450
|
-
"fontWeight": 800,
|
|
451
|
-
"colorMode": "gradient",
|
|
452
|
-
"gradientFrom": "#667eea",
|
|
453
|
-
"gradientTo": "#764ba2",
|
|
454
|
-
"gradientAngle": 135,
|
|
455
|
-
"lineHeight": 1.1,
|
|
456
|
-
"textAlign": "left"
|
|
457
|
-
}
|
|
458
|
-
]
|
|
459
|
-
}
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
---
|
|
463
|
-
|
|
464
|
-
## Output Format
|
|
465
|
-
|
|
466
|
-
When asked to create a composition, output the raw JSON object (the `CaptureStudioConfig`). Do NOT wrap it in markdown code fences when using the `design_composition` tool — pass it directly as the `config` argument.
|
|
467
|
-
|
|
468
|
-
Include:
|
|
469
|
-
- `canvas` with appropriate preset and background
|
|
470
|
-
- `screenshotPlacement` with shadow and padding
|
|
471
|
-
- `layout` if text is needed
|
|
472
|
-
- `textElements` with proper translations for all preset languages
|
|
473
|
-
- `logo` if the project has brand logos uploaded
|
|
474
|
-
- `themeBackgrounds` if the preset has multiple themes
|
|
475
|
-
|
|
476
|
-
Generate unique IDs for text elements using format: `te_<slot>_<n>` (e.g., `te_0_1`, `te_0_2`).
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
# Interactive Demo Workflow Reference
|
|
2
|
-
|
|
3
|
-
Use this reference when the user wants an embeddable product demo driven by
|
|
4
|
-
captured DOM states plus deterministic local interactions, not just static
|
|
5
|
-
screenshots or clips.
|
|
6
|
-
|
|
7
|
-
## When to use interactive demos
|
|
8
|
-
|
|
9
|
-
Choose this mode when:
|
|
10
|
-
|
|
11
|
-
- the output should feel clickable and alive on a landing page or docs page
|
|
12
|
-
- the user wants to recreate a focused product loop, not the entire app
|
|
13
|
-
- 2-6 distinct base states are enough and the rest can be reconstructed locally
|
|
14
|
-
- the main value comes from local UI reactions such as switching tabs, opening
|
|
15
|
-
a panel, swapping a preview, or editing small bits of content
|
|
16
|
-
|
|
17
|
-
Prefer plain screenshots or clips when the user only needs static visuals or a
|
|
18
|
-
linear recording.
|
|
19
|
-
|
|
20
|
-
## Core mental model
|
|
21
|
-
|
|
22
|
-
For interactive demos, the captured DOM is only the substrate. The quality of
|
|
23
|
-
the result depends on the interaction model:
|
|
24
|
-
|
|
25
|
-
1. what the viewer can click or edit
|
|
26
|
-
2. which parts of the UI react immediately
|
|
27
|
-
3. which changes need a new captured state vs local reconstruction
|
|
28
|
-
|
|
29
|
-
Do not start from "capture every page". Start from the feature loop the user
|
|
30
|
-
wants to showcase, then capture only what is needed to support that loop.
|
|
31
|
-
|
|
32
|
-
## What to capture vs what to reconstruct
|
|
33
|
-
|
|
34
|
-
Use this decision rule:
|
|
35
|
-
|
|
36
|
-
- whole page or route changes: create another `CAPTURE_DOM` base state
|
|
37
|
-
- one focused shell matters more than the whole page: use `CAPTURE_DOM` with a
|
|
38
|
-
`selector`
|
|
39
|
-
- modal / popover / dropdown / sheet: use `CAPTURE_FRAGMENT`
|
|
40
|
-
- local text / class / visible-state changes: use player API or bindings
|
|
41
|
-
- repeated editable content: use templates / repeaters / model bindings
|
|
42
|
-
- complex app-specific logic: use custom interaction `code` as the last resort
|
|
43
|
-
|
|
44
|
-
Default bias:
|
|
45
|
-
|
|
46
|
-
- fewer base states
|
|
47
|
-
- more local reconstruction
|
|
48
|
-
- a small number of meaningful viewer interactions
|
|
49
|
-
- focus on the central product experience
|
|
50
|
-
|
|
51
|
-
## Required authored markers
|
|
52
|
-
|
|
53
|
-
### Viewer interaction markers
|
|
54
|
-
|
|
55
|
-
Add `data-ak-interact="<name>"` to every element the viewer should operate in
|
|
56
|
-
the published demo.
|
|
57
|
-
|
|
58
|
-
```tsx
|
|
59
|
-
<button data-ak-interact="open-chat">Open chat</button>
|
|
60
|
-
<button data-ak-interact="settings-link">Settings</button>
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Use kebab-case names and keep the marker set intentionally small.
|
|
64
|
-
|
|
65
|
-
### Fragment markers
|
|
66
|
-
|
|
67
|
-
Add `data-ak-fragment="<name>"` on the root of every modal/popover/dropdown
|
|
68
|
-
subtree that should be captured separately.
|
|
69
|
-
|
|
70
|
-
Use `data-ak-mount` when mounting behavior matters:
|
|
71
|
-
|
|
72
|
-
- `inline`
|
|
73
|
-
- `overlay`
|
|
74
|
-
- `portal:<target-name>`
|
|
75
|
-
|
|
76
|
-
Add `data-ak-mount-target="<target-name>"` when a portal mount location is
|
|
77
|
-
required.
|
|
78
|
-
|
|
79
|
-
### Model / behavior markers
|
|
80
|
-
|
|
81
|
-
Prefer authored markers before custom code:
|
|
82
|
-
|
|
83
|
-
- `data-ak-model="<path>"`
|
|
84
|
-
- `data-ak-bind="..."`
|
|
85
|
-
- `data-ak-action="..."`
|
|
86
|
-
- `data-ak-template="<name>"`
|
|
87
|
-
- `data-ak-behavior="tabs|popover|slider|..."` for standard widget hints
|
|
88
|
-
|
|
89
|
-
These give the player enough structure to replay many standard UI behaviors
|
|
90
|
-
without bespoke JavaScript.
|
|
91
|
-
|
|
92
|
-
## Capture flow
|
|
93
|
-
|
|
94
|
-
### Base states
|
|
95
|
-
|
|
96
|
-
Set `mediaMode: "dom"` and `artifactPlan: { "mediaMode": "dom" }`, then use
|
|
97
|
-
normal deterministic opcodes to reach each captured state.
|
|
98
|
-
|
|
99
|
-
Use `CAPTURE_DOM` for:
|
|
100
|
-
|
|
101
|
-
- the full page
|
|
102
|
-
- or a focused shell via `selector`
|
|
103
|
-
|
|
104
|
-
Good focused-shell selectors:
|
|
105
|
-
|
|
106
|
-
- `[data-ak="studio-shell"]`
|
|
107
|
-
- `[data-ak="pricing-calculator"]`
|
|
108
|
-
- `[data-ak="dashboard-hero"]`
|
|
109
|
-
|
|
110
|
-
Avoid targeting tiny leaf nodes.
|
|
111
|
-
|
|
112
|
-
### Fragments
|
|
113
|
-
|
|
114
|
-
Use `CAPTURE_FRAGMENT` when only a local subtree changes.
|
|
115
|
-
|
|
116
|
-
Preferred pattern:
|
|
117
|
-
|
|
118
|
-
1. use visible UI to open the fragment
|
|
119
|
-
2. `WAIT_FOR` the fragment root
|
|
120
|
-
3. capture it with `CAPTURE_FRAGMENT`
|
|
121
|
-
|
|
122
|
-
Fallback pattern:
|
|
123
|
-
|
|
124
|
-
Add a hidden fragment trigger button when the fragment is not reachable through
|
|
125
|
-
visible UI.
|
|
126
|
-
|
|
127
|
-
## Fragment variants
|
|
128
|
-
|
|
129
|
-
Capture the same fragment under multiple `variantName`s when an interaction only
|
|
130
|
-
swaps a subtree in place, for example:
|
|
131
|
-
|
|
132
|
-
- preview background changes
|
|
133
|
-
- before / after toggle
|
|
134
|
-
- local layout switch
|
|
135
|
-
|
|
136
|
-
Rules:
|
|
137
|
-
|
|
138
|
-
- capture the baseline first
|
|
139
|
-
- keep variant names kebab-case
|
|
140
|
-
- keep the same fragment root selector across variants
|
|
141
|
-
- use variants only for structurally related subtree swaps
|
|
142
|
-
|
|
143
|
-
## Interaction script
|
|
144
|
-
|
|
145
|
-
The interaction script lives in `config.interactiveDemo.script`.
|
|
146
|
-
|
|
147
|
-
Each interaction has only four required fields:
|
|
148
|
-
|
|
149
|
-
- `state`
|
|
150
|
-
- `selector`
|
|
151
|
-
- `trigger`
|
|
152
|
-
- `code`
|
|
153
|
-
|
|
154
|
-
Canonical shape:
|
|
155
|
-
|
|
156
|
-
```json
|
|
157
|
-
{
|
|
158
|
-
"state": "dashboard",
|
|
159
|
-
"selector": "[data-ak-interact='open-chat']",
|
|
160
|
-
"trigger": "click",
|
|
161
|
-
"code": "await api.navigate('dashboard-chat-open', 'fade');"
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
Use `[data-ak-interact='...']` selectors by default.
|
|
166
|
-
|
|
167
|
-
Supported triggers:
|
|
168
|
-
|
|
169
|
-
- `click`
|
|
170
|
-
- `hover`
|
|
171
|
-
- `submit`
|
|
172
|
-
|
|
173
|
-
## Player API
|
|
174
|
-
|
|
175
|
-
The interaction `code` receives:
|
|
176
|
-
|
|
177
|
-
- `doc`
|
|
178
|
-
- `iframe`
|
|
179
|
-
- `api`
|
|
180
|
-
- `state`
|
|
181
|
-
- `target`
|
|
182
|
-
|
|
183
|
-
Prefer the player API before raw DOM mutation:
|
|
184
|
-
|
|
185
|
-
- `api.navigate(...)`
|
|
186
|
-
- `api.delay(...)`
|
|
187
|
-
- `api.query(...)`
|
|
188
|
-
- `api.setText(...)`
|
|
189
|
-
- `api.toggleClass(...)`
|
|
190
|
-
- `api.setValue(...)`
|
|
191
|
-
- `api.show(...)` / `api.hide(...)`
|
|
192
|
-
- `api.model.*`
|
|
193
|
-
- `api.template.*`
|
|
194
|
-
- `api.fragment.show / hide / swap / toggle / current / variants`
|
|
195
|
-
|
|
196
|
-
Use raw DOM access only when the built-in helpers and declarative markers are
|
|
197
|
-
not expressive enough.
|
|
198
|
-
|
|
199
|
-
## Common failure modes
|
|
200
|
-
|
|
201
|
-
- treating a custom dropdown like a native `<select>`
|
|
202
|
-
- not preserving active-state markers such as `aria-selected` or `data-state`
|
|
203
|
-
- capturing the trigger but not the controlled surface
|
|
204
|
-
- using unstable selectors like utility classes or text selectors
|
|
205
|
-
- forgetting that portal UI lives outside the main subtree
|
|
206
|
-
- capturing before the controlled DOM has actually settled
|
|
207
|
-
- trying to reconstruct canvas/WebGL internals directly from DOM capture
|
|
208
|
-
- over-capturing every page instead of focusing on the feature loop
|
|
209
|
-
|
|
210
|
-
## Preview and publish
|
|
211
|
-
|
|
212
|
-
After a run, the user previews the demo at:
|
|
213
|
-
|
|
214
|
-
`/projects/<projectId>/presets/<presetId>/preview`
|
|
215
|
-
|
|
216
|
-
The public URL is:
|
|
217
|
-
|
|
218
|
-
`/demo/<presetId>`
|
|
219
|
-
|
|
220
|
-
The embed snippet is:
|
|
221
|
-
|
|
222
|
-
```html
|
|
223
|
-
<div data-ak-demo="<presetId>"></div>
|
|
224
|
-
<script src="https://autokap.app/api/v1/loader.js" defer></script>
|
|
225
|
-
```
|