figura-cli 0.8.1 → 0.8.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "figura-cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Command-line client for the Figura visualization SaaS",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,11 +28,13 @@
|
|
|
28
28
|
"node": ">=20"
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
|
+
"gen-skill": "bun run scripts/gen-skill-reference.ts",
|
|
31
32
|
"build": "bun run scripts/bundle-skill.mjs && bun build src/index.ts --target=node --minify --outfile=dist/index.js && bun build ../mcp/src/index.ts --target=node --minify --outfile=dist/mcp.js",
|
|
32
33
|
"dev": "bun run src/index.ts",
|
|
33
34
|
"prepublishOnly": "bun run build"
|
|
34
35
|
},
|
|
35
36
|
"devDependencies": {
|
|
37
|
+
"@panofm/figura-core": "workspace:*",
|
|
36
38
|
"@types/node": "^20.14.0",
|
|
37
39
|
"axios": "^1.7.9",
|
|
38
40
|
"postgres": "^3.4.9",
|
|
@@ -5,6 +5,9 @@ argument-hint: '<what to visualize>'
|
|
|
5
5
|
allowed-tools: 'Bash(figura *), Bash(bunx figura-cli *)'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
<!-- GENERATED — do not edit by hand. Source of truth: packages/core/src/fig/* via
|
|
9
|
+
packages/cli/scripts/gen-skill-reference.ts (run `bun run gen-skill`). -->
|
|
10
|
+
|
|
8
11
|
# Figura Fig
|
|
9
12
|
|
|
10
13
|
Generate ONE self-contained, on-brand HTML fig and persist it to the user's Figura team.
|
|
@@ -77,9 +80,10 @@ bunx figura-cli brand --json
|
|
|
77
80
|
This returns `{ name, appDescription, tokensBlock, forbidden, surfaces, isCustom }`
|
|
78
81
|
(`forbidden` is a string, `surfaces` is a string[]).
|
|
79
82
|
|
|
80
|
-
- If **`isCustom: true`** —
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
- If **`isCustom: true`** — treat the returned `tokensBlock` as the **design system that
|
|
84
|
+
wins conflicts** (palette, type, spacing, icon language) and render for `name` /
|
|
85
|
+
`appDescription`. If anything in the request conflicts with the design system, the design
|
|
86
|
+
system takes priority. Never invent off-brand values.
|
|
83
87
|
- If **`isCustom: false`** (no brand set) — render with **neutral defaults**: read
|
|
84
88
|
`reference/brand-tokens.md` (next to this file). It is a clean, brand-neutral baseline —
|
|
85
89
|
understated and professional, NOT any specific company's look.
|
|
@@ -97,7 +101,7 @@ engine's own generator does):
|
|
|
97
101
|
|
|
98
102
|
**Pick the platform** from the request:
|
|
99
103
|
|
|
100
|
-
- **`mobile`** (default) — an iPhone
|
|
104
|
+
- **`mobile`** (default) — an iPhone app screen.
|
|
101
105
|
- **`web`** — a browser-framed web/desktop UI (a marketing page, dashboard, SaaS screen).
|
|
102
106
|
Choose this when the product is a website/web app rather than a phone screen.
|
|
103
107
|
|
|
@@ -121,15 +125,29 @@ Produce ONE complete, self-contained HTML document. Whatever the platform, it MU
|
|
|
121
125
|
its state with CSS alone (it runs in a sandboxed iframe).
|
|
122
126
|
- Use the resolved brand's tokens for all color/type/spacing — never invent off-brand values.
|
|
123
127
|
- Represent every icon as **inline stroke SVG** via `<symbol>`/`<use>` (currentColor,
|
|
124
|
-
width ~1.6) — **
|
|
128
|
+
width ~1.6) — **NO emojis anywhere**.
|
|
125
129
|
- Set `<title>` to a short screen name, include `<meta name="figura:context" content="…">`
|
|
126
130
|
(one-line design-intent summary), and an `<h1>` naming the screen.
|
|
127
131
|
|
|
128
|
-
**Mobile platform
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
132
|
+
**Mobile platform — FRAMLESS device screen.** Render the **screen contents only, at EXACTLY
|
|
133
|
+
the device's logical screen size, with NO drawn phone bezel / outer border / rounded outer
|
|
134
|
+
frame / notch or Dynamic-Island cutout** — the Figura viewer draws the physical device frame
|
|
135
|
+
+ Dynamic Island around your output, so a fig fits a real phone 1:1.
|
|
136
|
+
|
|
137
|
+
- Portrait: render at **393×852** logical px. Landscape: **852×393**.
|
|
138
|
+
- Lock the body to that size and fill it edge-to-edge (no outer page padding):
|
|
139
|
+
`body { margin:0; width:393px; height:852px; background:#0A0A0A; overflow:hidden; }` (swap W/H for landscape).
|
|
140
|
+
- Reserve the OS-chrome safe areas: keep the top ~59px (status bar / Dynamic
|
|
141
|
+
Island) and bottom ~34px (home indicator) clear of critical controls
|
|
142
|
+
(landscape: top ~59px, bottom ~21px).
|
|
143
|
+
- **Emit `<meta name="figura:artboard" content="393x852">`** (the exact W×H you
|
|
144
|
+
rendered to) so the viewer can frame it. A `.preview` media area is OPTIONAL — include it
|
|
145
|
+
only if the design calls for a hero/media region, sized to the design (any aspect ratio).
|
|
146
|
+
- Hand-roll controls with the pill/capsule convention (see `reference/brand-tokens.md`); do
|
|
147
|
+
not rely on system/OS chrome.
|
|
148
|
+
|
|
149
|
+
(`compare` and `both` are multi-screen comparison layouts — render each screen at the size
|
|
150
|
+
above on a canvas that grows to fit them all, and do NOT emit a single `figura:artboard` meta.)
|
|
133
151
|
|
|
134
152
|
**Web platform** — render a **browser window** instead (no phone frame):
|
|
135
153
|
|
|
@@ -141,6 +159,19 @@ not rely on system/OS chrome.
|
|
|
141
159
|
.frame-web .viewport { /* full-bleed RESPONSIVE content — nav, hero, sections */ }
|
|
142
160
|
```
|
|
143
161
|
|
|
162
|
+
**Hard rules (apply to every fig):**
|
|
163
|
+
|
|
164
|
+
- NO emojis anywhere. Represent every icon as inline stroke SVG via <symbol>/<use> (currentColor, width ~1.6).
|
|
165
|
+
- Plain HTML + INLINE CSS ONLY (a single <style> in <head>). No external stylesheets, no fonts loaded over the network, no frameworks.
|
|
166
|
+
- ABSOLUTELY NO <script> tags and NO on* event handlers (onclick, onload, etc.). The fig must be fully static and render its state with CSS alone. It runs in a sandboxed iframe.
|
|
167
|
+
|
|
168
|
+
**Visual quality (intentional and crafted — never generic "AI" UI):**
|
|
169
|
+
|
|
170
|
+
- Color: 3–5 colors total, drawn from the design system — one primary, 2–3 neutrals, 1–2 accents; never exceed 5. If you override a background color, also override its text color for contrast.
|
|
171
|
+
- Type: at most 2 font families (headings + body). No decorative fonts for body. Clear hierarchy.
|
|
172
|
+
- NEVER add filler decoration: no gradient circles, blurry blobs, or abstract shapes as ornament. Avoid gradients unless the design system calls for them; prefer solid colors.
|
|
173
|
+
- Real, specific content (no lorem ipsum, no "Title goes here"). Generous, consistent spacing. A clear visual identity — not a bland gray/white template.
|
|
174
|
+
|
|
144
175
|
### 4. Persist (and optionally publish) to the Figura team
|
|
145
176
|
|
|
146
177
|
**Generating the HTML is not "creating the fig" — the fig only exists once it's saved to the
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Figura Fig — neutral default tokens (no team brand set)
|
|
2
2
|
|
|
3
|
+
<!-- GENERATED — do not edit by hand. Source of truth: packages/core/src/fig/* via
|
|
4
|
+
packages/cli/scripts/gen-skill-reference.ts (run `bun run gen-skill`). -->
|
|
5
|
+
|
|
3
6
|
Use this baseline ONLY when `figura brand --json` returns `isCustom: false` (the team
|
|
4
7
|
hasn't set its own brand). It is a clean, modern, accessible, brand-NEUTRAL default — never
|
|
5
8
|
any specific company's look. The moment a team sets tokens, use those instead.
|
|
@@ -10,7 +13,7 @@ Keep it understated and professional.
|
|
|
10
13
|
|
|
11
14
|
| Role | Value | Usage |
|
|
12
15
|
|------|-------|-------|
|
|
13
|
-
| Canvas | `#
|
|
16
|
+
| Canvas | `#0A0A0A` | Near-black base background (the fig screen). |
|
|
14
17
|
| Surface | `#161618` | Cards / raised surfaces. |
|
|
15
18
|
| Text | `#F4F4F6` | Primary text. |
|
|
16
19
|
| Text muted | `#9aa0ad` | Secondary text, captions. |
|
|
@@ -37,43 +40,33 @@ An 8px spacing rhythm; 12–16px corner radii; 1px hairline borders; restrained
|
|
|
37
40
|
|
|
38
41
|
## Icon language
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
`stroke-width` ~1.6). **NEVER emoji.**
|
|
42
|
-
|
|
43
|
-
## iPhone device frame — CSS conventions
|
|
44
|
-
|
|
45
|
-
Reuse these class names + proportions so every mobile fig reads as one house style.
|
|
43
|
+
Inline SVG icons — define <symbol> elements in a hidden <svg> at the top of <body> and reference with <use href="#id"/>. Stroke icons (currentColor stroke, width ~1.6). NO emojis anywhere.
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
```css
|
|
50
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
51
|
-
body { background: #161618; color: #F4F4F6; font-family: Inter, -apple-system, BlinkMacSystemFont, system-ui, sans-serif; padding: 30px; }
|
|
52
|
-
.page { display: flex; flex-direction: column; align-items: center; gap: 14px; }
|
|
53
|
-
.row { display: flex; gap: 30px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
|
|
54
|
-
.col { display: flex; flex-direction: column; align-items: center; gap: 11px; }
|
|
55
|
-
.col-label { font-size: 11px; letter-spacing: .6px; text-transform: uppercase; color: #9aa0ad; font-weight: 600; }
|
|
56
|
-
```
|
|
45
|
+
## Framless iPhone screen — CSS conventions
|
|
57
46
|
|
|
58
|
-
**
|
|
47
|
+
Mobile figs are **FRAMLESS**: render the screen contents ONLY, at the device's exact logical
|
|
48
|
+
screen size, with **NO drawn phone bezel / outer border / rounded outer frame / notch or
|
|
49
|
+
Dynamic-Island cutout** — the Figura viewer draws the physical device frame + island around
|
|
50
|
+
your output, so a fig fits a real phone 1:1. Lock the body to the screen size and emit a
|
|
51
|
+
`<meta name="figura:artboard" content="WxH">` with that size.
|
|
59
52
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
53
|
+
| Orientation | Logical screen | Safe area top | Safe area bottom |
|
|
54
|
+
|-------------|----------------|---------------|------------------|
|
|
55
|
+
| Portrait | 393×852 | 59px | 34px |
|
|
56
|
+
| Landscape | 852×393 | 59px | 21px |
|
|
64
57
|
|
|
65
|
-
**
|
|
58
|
+
**Reset + body (lock to the screen size, fill edge-to-edge):**
|
|
66
59
|
|
|
67
60
|
```css
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
62
|
+
body { margin: 0; width: 393px; height: 852px; background: #0A0A0A; color: #F4F4F6; font-family: Inter, -apple-system, BlinkMacSystemFont, system-ui, sans-serif; overflow: hidden; } /* swap W/H for landscape */
|
|
70
63
|
```
|
|
71
64
|
|
|
72
|
-
**Screen + OPTIONAL media area** (include `.preview` only if the design needs a
|
|
73
|
-
region — size it to the design, any aspect ratio; there is no fixed film ratio):
|
|
65
|
+
**Screen surface + OPTIONAL media area** (include `.preview` only if the design needs a
|
|
66
|
+
hero/media region — size it to the design, any aspect ratio; there is no fixed film ratio):
|
|
74
67
|
|
|
75
68
|
```css
|
|
76
|
-
.screen { position: absolute; inset: 0; background: #
|
|
69
|
+
.screen { position: absolute; inset: 0; background: #0A0A0A; color: #F4F4F6; overflow: hidden; }
|
|
77
70
|
.preview { position: absolute; background: #18181b; } /* optional media/hero region */
|
|
78
71
|
.scrim { position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(0,0,0,.45), transparent 22%, transparent 70%, rgba(0,0,0,.55)); }
|
|
79
72
|
```
|
|
@@ -88,31 +81,35 @@ region — size it to the design, any aspect ratio; there is no fixed film ratio
|
|
|
88
81
|
.badge { min-width: 15px; height: 15px; padding: 0 4px; background: var(--accent, #4C8DFF); border-radius: 999px; font-size: 9px; font-weight: 700; color: #fff; display: flex; align-items: center; justify-content: center; } /* a quiet count, never a red alarm */
|
|
89
82
|
```
|
|
90
83
|
|
|
91
|
-
**Annotation chips — yellow callouts pinned over the
|
|
84
|
+
**Annotation chips — yellow callouts pinned over the screen (label intent):**
|
|
92
85
|
|
|
93
86
|
```css
|
|
94
87
|
.annot { position: absolute; font-size: 9px; font-weight: 500; color: #ffe066; background: rgba(0,0,0,.82); border: 1px solid rgba(255,224,102,.45); padding: 3px 6px; border-radius: 4px; pointer-events: none; z-index: 20; max-width: 180px; line-height: 1.3; }
|
|
95
88
|
```
|
|
96
89
|
|
|
97
|
-
**Inline SVG icons:** define
|
|
98
|
-
and reference with `<use href="#id"/>`. Stroke icons (`stroke="currentColor"`,
|
|
99
|
-
`stroke-width` ~1.6).
|
|
90
|
+
**Inline SVG icons:** Inline SVG icons — define <symbol> elements in a hidden <svg> at the top of <body> and reference with <use href="#id"/>. Stroke icons (currentColor stroke, width ~1.6). NO emojis anywhere.
|
|
100
91
|
|
|
101
92
|
## Hard rules (non-negotiable)
|
|
102
93
|
|
|
103
|
-
-
|
|
104
|
-
|
|
105
|
-
-
|
|
94
|
+
- Render the screen contents at EXACTLY the chosen orientation's logical size with NO device
|
|
95
|
+
frame/bezel/notch — the Figura viewer draws the physical phone frame around your output.
|
|
96
|
+
- Emit `<meta name="figura:artboard" content="WxH">` with the exact logical screen size.
|
|
97
|
+
- NO emojis anywhere. Represent every icon as inline stroke SVG via <symbol>/<use> (currentColor, width ~1.6).
|
|
106
98
|
- Hand-roll every control with the pill/capsule convention above — do not rely on system/OS
|
|
107
99
|
chrome or platform glass effects.
|
|
108
|
-
- Plain HTML + INLINE CSS ONLY (a single
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
100
|
+
- Plain HTML + INLINE CSS ONLY (a single <style> in <head>). No external stylesheets, no fonts loaded over the network, no frameworks.
|
|
101
|
+
- ABSOLUTELY NO <script> tags and NO on* event handlers (onclick, onload, etc.). The fig must be fully static and render its state with CSS alone. It runs in a sandboxed iframe.
|
|
102
|
+
|
|
103
|
+
## Visual quality (intentional and crafted — never generic "AI" UI)
|
|
104
|
+
|
|
105
|
+
- Color: 3–5 colors total, drawn from the design system — one primary, 2–3 neutrals, 1–2 accents; never exceed 5. If you override a background color, also override its text color for contrast.
|
|
106
|
+
- Type: at most 2 font families (headings + body). No decorative fonts for body. Clear hierarchy.
|
|
107
|
+
- NEVER add filler decoration: no gradient circles, blurry blobs, or abstract shapes as ornament. Avoid gradients unless the design system calls for them; prefer solid colors.
|
|
108
|
+
- Real, specific content (no lorem ipsum, no "Title goes here"). Generous, consistent spacing. A clear visual identity — not a bland gray/white template.
|
|
112
109
|
|
|
113
110
|
## Document contract
|
|
114
111
|
|
|
115
|
-
- Respond with a complete HTML document
|
|
116
|
-
-
|
|
117
|
-
-
|
|
112
|
+
- Respond with ONLY a complete HTML document. Start at <!DOCTYPE html>. No markdown code fences, no backticks, no prose before or after.
|
|
113
|
+
- Set <title> to a short, descriptive fig title.
|
|
114
|
+
- Include a meta tag summarizing the design intent: <meta name="figura:context" content="...">.
|
|
118
115
|
- An `<h1>` naming the screen.
|
|
@@ -10,11 +10,13 @@ self-contained HTML document and persists it to the Figura team via `bunx figura
|
|
|
10
10
|
|
|
11
11
|
**Resolved scope:** area `settings`, orientation `portrait`.
|
|
12
12
|
|
|
13
|
-
**Generated document:** a
|
|
14
|
-
|
|
13
|
+
**Generated document:** a FRAMLESS portrait screen rendered at exactly 393×852 (no drawn phone
|
|
14
|
+
bezel — the viewer frames it), with `<meta name="figura:artboard" content="393x852">`. Inside,
|
|
15
|
+
a `.screen`: a "Settings" header + a search field, then grouped rows (Account, Notifications,
|
|
15
16
|
Privacy) — each row a label + an inline stroke-SVG glyph + a control (chevron, or a CSS-only
|
|
16
17
|
toggle in the accent color). A sticky bottom save bar ("3 unsaved changes" + Save / Discard)
|
|
17
|
-
pinned over the screen. No `.preview` media area
|
|
18
|
+
pinned over the screen, kept clear of the ~34px bottom safe area. No `.preview` media area
|
|
19
|
+
(this screen has none).
|
|
18
20
|
|
|
19
21
|
A `.annot` chip points at the toggles: "active = accent #4C8DFF". `<title>` = "Settings —
|
|
20
22
|
account & notifications"; `<meta name="figura:context">` summarizes the unsaved-changes
|