figura-cli 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/index.js +84 -63
- package/package.json +3 -2
- package/skills/figura-fig/SKILL.md +230 -0
- package/skills/figura-fig/reference/brand-tokens.md +118 -0
- package/skills/figura-fig/reference/examples.md +104 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "figura-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Command-line client for the Figura visualization SaaS",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -21,13 +21,14 @@
|
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"dist",
|
|
24
|
+
"skills",
|
|
24
25
|
"README.md"
|
|
25
26
|
],
|
|
26
27
|
"engines": {
|
|
27
28
|
"node": ">=20"
|
|
28
29
|
},
|
|
29
30
|
"scripts": {
|
|
30
|
-
"build": "bun build src/index.ts --target=node --minify --outfile=dist/index.js",
|
|
31
|
+
"build": "bun run scripts/bundle-skill.mjs && bun build src/index.ts --target=node --minify --outfile=dist/index.js",
|
|
31
32
|
"dev": "bun run src/index.ts",
|
|
32
33
|
"prepublishOnly": "bun run build"
|
|
33
34
|
},
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: figura-fig
|
|
3
|
+
description: "Generate an on-brand, device- or browser-framed HTML fig using your Figura team's design system, save it to your team, and (optionally) publish a shareable link. iPhone frame by default; browser frame for web/desktop UIs. Use when asked to mock up a screen, build a fig, or visualize a UI state."
|
|
4
|
+
argument-hint: '<what to visualize>'
|
|
5
|
+
allowed-tools: 'Bash(figura *), Bash(bunx figura-cli *)'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Figura Fig
|
|
9
|
+
|
|
10
|
+
Generate ONE self-contained, on-brand HTML fig and persist it to the user's Figura team.
|
|
11
|
+
It renders with the **team's brand profile** (their design tokens). When the team hasn't set
|
|
12
|
+
a brand, Figura is brand-neutral by construction — render with clean, modern, accessible
|
|
13
|
+
**neutral defaults**, never another company's brand.
|
|
14
|
+
|
|
15
|
+
The argument (`$ARGUMENTS`) is what to visualize, e.g. "the settings screen with a sticky
|
|
16
|
+
save bar" or "the pricing page".
|
|
17
|
+
|
|
18
|
+
## Prerequisites
|
|
19
|
+
|
|
20
|
+
The user needs the `figura` CLI installed once…
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
curl -fsSL https://figura.so/install.sh | bash # or, with a runtime: bun add -g figura-cli / npm i -g figura-cli
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
…and an authenticated session, established once:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
figura login
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`figura login` opens a short browser authorize page — a **device flow**, so there's no
|
|
33
|
+
token to paste, no localhost port, and it works over SSH. Approve there and the CLI writes
|
|
34
|
+
the credential to `~/.figura/config.json` (it also honors the `FIGURA_TOKEN` env var for
|
|
35
|
+
CI/headless). **Never mint or fabricate a token yourself.**
|
|
36
|
+
|
|
37
|
+
If the CLI is missing or the user isn't logged in, you'll hit it at the **persist** step
|
|
38
|
+
([§4](#4-persist-and-optionally-publish-to-the-figura-team)) — handle it there: guide them
|
|
39
|
+
through install / `figura login`, then retry. (If `figura` isn't on PATH, use
|
|
40
|
+
`bunx figura-cli` in its place everywhere below.)
|
|
41
|
+
|
|
42
|
+
## Workflow
|
|
43
|
+
|
|
44
|
+
### 0. New fig or a revision?
|
|
45
|
+
|
|
46
|
+
Decide this first. If the request **iterates on an existing or just-made fig** — "make
|
|
47
|
+
the earlier settings screen darker", "tweak that pricing page", "same screen but landscape"
|
|
48
|
+
— it's a **REVISION**: jump to [§4b](#4b-persist-a-revision) instead of creating a new fig.
|
|
49
|
+
Otherwise fall through and create a new fig as normal. When genuinely unsure, default to a
|
|
50
|
+
new `fig create`.
|
|
51
|
+
|
|
52
|
+
**Resolve the prior fig id** (priority order):
|
|
53
|
+
|
|
54
|
+
1. The id printed by a `fig create`/`fig revise` earlier **in this session** — use it directly.
|
|
55
|
+
2. An id, a `*.figura.so` URL, or a slug the **user pasted/named** — extract the id from it.
|
|
56
|
+
3. Otherwise list and match: `bunx figura-cli fig list --json` (optionally `--area <area>`),
|
|
57
|
+
then match by title / area / tags / recency. If **more than one** plausibly matches, ASK
|
|
58
|
+
(cite id + title) — never silently revise the wrong fig.
|
|
59
|
+
|
|
60
|
+
**Fetch the prior HTML** so you can edit on top of it rather than regenerating from scratch:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
bunx figura-cli fig open <priorFigId> --print
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This round-trips the stored document to stdout. Apply the user's change on top of it,
|
|
67
|
+
keeping the brand tokens and overall structure stable.
|
|
68
|
+
|
|
69
|
+
### 1. Resolve the brand + platform
|
|
70
|
+
|
|
71
|
+
**Fetch the team's brand profile first:**
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
bunx figura-cli brand --json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This returns `{ name, appDescription, tokensBlock, isCustom }`.
|
|
78
|
+
|
|
79
|
+
- If **`isCustom: true`** — use the returned `tokensBlock` as the ground-truth design
|
|
80
|
+
system (palette, type, spacing, icon language) and render for `name` / `appDescription`.
|
|
81
|
+
Never invent off-brand values.
|
|
82
|
+
- If **`isCustom: false`** (no brand set) — render with **neutral defaults**: read
|
|
83
|
+
`reference/brand-tokens.md` (next to this file). It is a clean, brand-neutral baseline —
|
|
84
|
+
understated and professional, NOT any specific company's look.
|
|
85
|
+
|
|
86
|
+
**Pick the platform** from the request:
|
|
87
|
+
|
|
88
|
+
- **`mobile`** (default) — an iPhone-framed app screen.
|
|
89
|
+
- **`web`** — a browser-framed web/desktop UI (a marketing page, dashboard, SaaS screen).
|
|
90
|
+
Choose this when the product is a website/web app rather than a phone screen.
|
|
91
|
+
|
|
92
|
+
Optionally skim `reference/examples.md` for worked prompt → output pairs.
|
|
93
|
+
|
|
94
|
+
### 2. Confirm scope (only if ambiguous)
|
|
95
|
+
|
|
96
|
+
- **area** — the part of the product this screen belongs to (e.g. `feed`, `profile`,
|
|
97
|
+
`settings`, `onboarding`, or `other`). It's a free-form hint that grounds the design; pick
|
|
98
|
+
what the prompt implies.
|
|
99
|
+
- **orientation** — `landscape` / `portrait` / `both` (mobile only; web is responsive).
|
|
100
|
+
|
|
101
|
+
Pick what the prompt implies; confirm only if you genuinely can't.
|
|
102
|
+
|
|
103
|
+
### 3. Generate the HTML
|
|
104
|
+
|
|
105
|
+
Produce ONE complete, self-contained HTML document. Whatever the platform, it MUST:
|
|
106
|
+
|
|
107
|
+
- Start at `<!DOCTYPE html>` — a full document, inline CSS only (one `<style>` in `<head>`).
|
|
108
|
+
- Contain **NO `<script>` tags** and **NO `on*` event handlers**. Fully static; it renders
|
|
109
|
+
its state with CSS alone (it runs in a sandboxed iframe).
|
|
110
|
+
- Use the resolved brand's tokens for all color/type/spacing — never invent off-brand values.
|
|
111
|
+
- Represent every icon as **inline stroke SVG** via `<symbol>`/`<use>` (currentColor,
|
|
112
|
+
width ~1.6) — **NEVER emoji**.
|
|
113
|
+
- Set `<title>` to a short screen name, include `<meta name="figura:context" content="…">`
|
|
114
|
+
(one-line design-intent summary), and an `<h1>` naming the screen.
|
|
115
|
+
|
|
116
|
+
**Mobile platform** — render an **iPhone device frame** (`.device-port` for portrait,
|
|
117
|
+
`.device-land` for landscape) with a dynamic island, per the reference. A `.preview` media
|
|
118
|
+
area is OPTIONAL — include it only if the design calls for a hero/media region, and size it
|
|
119
|
+
to the design (any aspect ratio). Hand-roll controls with the pill/capsule convention; do
|
|
120
|
+
not rely on system/OS chrome.
|
|
121
|
+
|
|
122
|
+
**Web platform** — render a **browser window** instead (no phone frame):
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
.frame-web { width: 980px; max-width: 100%; border: 1px solid #2a2a2c; border-radius: 12px; overflow: hidden; }
|
|
126
|
+
.frame-web .bar { display: flex; gap: 8px; align-items: center; height: 40px; padding: 0 14px; }
|
|
127
|
+
.frame-web .dot { width: 12px; height: 12px; border-radius: 50%; } /* r/y/g window controls */
|
|
128
|
+
.frame-web .urlbar { flex: 1; height: 22px; border-radius: 6px; } /* address pill */
|
|
129
|
+
.frame-web .viewport { /* full-bleed RESPONSIVE content — nav, hero, sections */ }
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 4. Persist (and optionally publish) to the Figura team
|
|
133
|
+
|
|
134
|
+
**Generating the HTML is not "creating the fig" — the fig only exists once it's saved to the
|
|
135
|
+
user's team and the CLI returns an id.** Always upload the HTML straight to Figura; **never**
|
|
136
|
+
write it to a local file or leave it only in the conversation as the result. Pipe the
|
|
137
|
+
generated document into the CLI over stdin:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
cat <<'HTML' | bunx figura-cli fig create \
|
|
141
|
+
--title "Settings — account & notifications" \
|
|
142
|
+
--area settings \
|
|
143
|
+
--orientation portrait \
|
|
144
|
+
--tags settings,toggles \
|
|
145
|
+
--publish
|
|
146
|
+
<!DOCTYPE html>
|
|
147
|
+
… the generated document …
|
|
148
|
+
HTML
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**If the upload fails because the user isn't authenticated** — a 401, "No Figura token", or
|
|
152
|
+
"token validation failed" — they haven't logged in. Run `figura login` (the browser device
|
|
153
|
+
flow from [Prerequisites](#prerequisites)), then **retry the same `fig create`**. Don't
|
|
154
|
+
report the fig as done and don't fall back to writing the HTML to a local file — it isn't a
|
|
155
|
+
fig until the persist succeeds and returns an id. (Same for a missing CLI: point them at the
|
|
156
|
+
install one-liner, then retry.)
|
|
157
|
+
|
|
158
|
+
- `--publish` (recommended when the user wants to share it) flips the fig public and returns
|
|
159
|
+
a **shareable `*.figura.so` URL**. It requires an active subscription (any paid tier); on a
|
|
160
|
+
free team the CLI reports the fig is saved privately. Omit `--publish` to keep the fig
|
|
161
|
+
private to the team.
|
|
162
|
+
- Do NOT use `--file` or `mktemp`/temp files — stream the HTML via stdin so no local copy is
|
|
163
|
+
left behind.
|
|
164
|
+
- `--title` matches the `<title>`; `--area` / `--orientation` are the confirmed facets;
|
|
165
|
+
`--tags` is a short comma-separated list.
|
|
166
|
+
- The token resolves automatically from `FIGURA_TOKEN` or `~/.figura/config.json`.
|
|
167
|
+
|
|
168
|
+
The command prints the result as JSON. When published it includes the shareable `url` —
|
|
169
|
+
surface that to the user. To publish a fig created earlier: `bunx figura-cli fig publish <id>`.
|
|
170
|
+
|
|
171
|
+
### 4b. Persist a revision
|
|
172
|
+
|
|
173
|
+
When the request iterates on an existing fig (resolved in [§0](#0-new-fig-or-a-revision)),
|
|
174
|
+
persist the updated HTML as a **new linked version** with `fig revise <priorFigId>`:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
cat <<'HTML' | bunx figura-cli fig revise <priorFigId> \
|
|
178
|
+
--title "Settings — darker theme" \
|
|
179
|
+
--tags settings,toggles,dark \
|
|
180
|
+
--publish
|
|
181
|
+
<!DOCTYPE html>
|
|
182
|
+
… the full updated document …
|
|
183
|
+
HTML
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
- `revise` creates a NEW row on the SAME root chain with an incremented `version` — it does
|
|
187
|
+
NOT edit the prior fig in place. `<priorFigId>` is a positional argument.
|
|
188
|
+
- `--area` / `--orientation` are **inherited from the parent** unless you override them — a
|
|
189
|
+
refine keeps the same surface. Pass the same Create options otherwise (`--title`, `--tags`,
|
|
190
|
+
`--publish`).
|
|
191
|
+
- The result JSON includes `id`, `version`, and `rootFigId`. Surface it as
|
|
192
|
+
"revision vN of \<root\>" plus the shareable URL when `--publish` was used.
|
|
193
|
+
- To inspect the chain: `bunx figura-cli fig revisions <id>` (any id in the chain; oldest to
|
|
194
|
+
newest).
|
|
195
|
+
|
|
196
|
+
### 4c. Request a teammate's feedback
|
|
197
|
+
|
|
198
|
+
When the user wants a specific person to look at a fig — "I want Adam's feedback on this",
|
|
199
|
+
"get Sara's eyes on it", "ask Maya to review this" — request feedback on the fig. The teammate
|
|
200
|
+
gets a notification (in-app bell, web push, email) and the discussion happens in the fig's
|
|
201
|
+
comment thread on Figura. Use the fig id from this session (the one you just created/revised),
|
|
202
|
+
or resolve it via [§0](#0-new-fig-or-a-revision) first.
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
bunx figura-cli fig request-feedback <figId> --from "Adam" --note "does the empty state read right?"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
- `--from` is the teammate by **name or email**, resolved within your team. If it's ambiguous
|
|
209
|
+
or not found, the CLI says so — relay that and ask the user to clarify (or invite them first).
|
|
210
|
+
- `--note` is optional; pass along whatever the user wants reviewed.
|
|
211
|
+
- This is the entry point for "tell Claude Code → teammate notified → chat on the figura page".
|
|
212
|
+
Report the teammate asked + the fig URL it prints.
|
|
213
|
+
|
|
214
|
+
### MCP fast path
|
|
215
|
+
|
|
216
|
+
If a `figura` **MCP server** is connected, prefer its tools over shelling out to the CLI:
|
|
217
|
+
|
|
218
|
+
- New fig → `figura_create_fig` (fields: html, title, area, orientation, tags, `publish`).
|
|
219
|
+
- **Revision** of an existing fig → `figura_revise_fig` (fields: `id`, html, title?, tags?,
|
|
220
|
+
area?, orientation?, `publish`?) — mirrors how `figura_create_fig` is preferred for new figs.
|
|
221
|
+
- Inspect the chain → `figura_list_revisions` (field: `id`).
|
|
222
|
+
- **Request a teammate's feedback** → `figura_request_feedback` (fields: `id`, `from`, `note?`).
|
|
223
|
+
|
|
224
|
+
Prefer the MCP tools when available; fall back to the CLI otherwise.
|
|
225
|
+
|
|
226
|
+
## Output
|
|
227
|
+
|
|
228
|
+
Report back the persisted fig — the shareable URL if published, otherwise that it was saved
|
|
229
|
+
privately to the team — plus a one-line description of what was rendered. Do not paste the
|
|
230
|
+
full HTML into the conversation unless the user asks to see it.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Figura Fig — neutral default tokens (no team brand set)
|
|
2
|
+
|
|
3
|
+
Use this baseline ONLY when `figura brand --json` returns `isCustom: false` (the team
|
|
4
|
+
hasn't set its own brand). It is a clean, modern, accessible, brand-NEUTRAL default — never
|
|
5
|
+
any specific company's look. The moment a team sets tokens, use those instead.
|
|
6
|
+
|
|
7
|
+
Keep it understated and professional.
|
|
8
|
+
|
|
9
|
+
## Colors (neutral defaults — keep to ONE accent)
|
|
10
|
+
|
|
11
|
+
| Role | Value | Usage |
|
|
12
|
+
|------|-------|-------|
|
|
13
|
+
| Canvas | `#0E0E10` | Near-black base background. |
|
|
14
|
+
| Surface | `#161618` | Cards / raised surfaces. |
|
|
15
|
+
| Text | `#F4F4F6` | Primary text. |
|
|
16
|
+
| Text muted | `#9aa0ad` | Secondary text, captions. |
|
|
17
|
+
| Hairline | `rgba(255,255,255,.10)` | 1px borders / dividers. |
|
|
18
|
+
| Accent | `#4C8DFF` | ONE calm blue accent — primary actions, active state, focus. |
|
|
19
|
+
|
|
20
|
+
No more than one accent hue. No decorative gradients unless the prompt asks. Status tints
|
|
21
|
+
only when genuinely needed: amber `#E8A33D` (warn), green `#3ee07a` (success), error `#ff5f57`.
|
|
22
|
+
|
|
23
|
+
## Type
|
|
24
|
+
|
|
25
|
+
System / neutral sans only — declare stacks, never load fonts over the network:
|
|
26
|
+
|
|
27
|
+
| Role | CSS stack |
|
|
28
|
+
|------|-----------|
|
|
29
|
+
| Sans (everything) | `Inter, -apple-system, BlinkMacSystemFont, system-ui, sans-serif` |
|
|
30
|
+
| Mono (numbers/code) | `ui-monospace, SFMono-Regular, 'JetBrains Mono', monospace` |
|
|
31
|
+
|
|
32
|
+
Clear hierarchy: ~13px body, semibold headings, generous line-height.
|
|
33
|
+
|
|
34
|
+
## Spacing & shape
|
|
35
|
+
|
|
36
|
+
An 8px spacing rhythm; 12–16px corner radii; 1px hairline borders; restrained shadows.
|
|
37
|
+
|
|
38
|
+
## Icon language
|
|
39
|
+
|
|
40
|
+
Every icon is **inline stroke SVG** via `<symbol>`/`<use>` (`stroke="currentColor"`,
|
|
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.
|
|
46
|
+
|
|
47
|
+
**Reset + page:**
|
|
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
|
+
```
|
|
57
|
+
|
|
58
|
+
**PORTRAIT phone (the common case):**
|
|
59
|
+
|
|
60
|
+
```css
|
|
61
|
+
.device-port { position: relative; width: 300px; height: 640px; background: #000; border-radius: 44px; border: 6px solid #2a2a2a; box-shadow: 0 18px 40px rgba(0,0,0,.5), inset 0 0 0 2px #000; overflow: hidden; }
|
|
62
|
+
.device-port .island { position: absolute; top: 9px; left: 50%; transform: translateX(-50%); width: 92px; height: 26px; background: #000; border-radius: 15px; z-index: 8; }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**LANDSCAPE phone (wide window, side island):**
|
|
66
|
+
|
|
67
|
+
```css
|
|
68
|
+
.device-land { position: relative; width: 660px; height: 318px; background: #000; border-radius: 44px; border: 6px solid #2a2a2a; box-shadow: 0 24px 50px rgba(0,0,0,.55), inset 0 0 0 2px #000; overflow: hidden; }
|
|
69
|
+
.device-land .island { position: absolute; left: 9px; top: 50%; transform: translateY(-50%); width: 26px; height: 96px; background: #000; border-radius: 16px; z-index: 8; }
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Screen + OPTIONAL media area** (include `.preview` only if the design needs a hero/media
|
|
73
|
+
region — size it to the design, any aspect ratio; there is no fixed film ratio):
|
|
74
|
+
|
|
75
|
+
```css
|
|
76
|
+
.screen { position: absolute; inset: 0; background: #0E0E10; color: #F4F4F6; overflow: hidden; }
|
|
77
|
+
.preview { position: absolute; background: #18181b; } /* optional media/hero region */
|
|
78
|
+
.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
|
+
```
|
|
80
|
+
|
|
81
|
+
**Capsule chrome — pill controls, count badge (all fully rounded):**
|
|
82
|
+
|
|
83
|
+
```css
|
|
84
|
+
.time-pill { position: absolute; background: rgba(0,0,0,.55); border-radius: 999px; padding: 4px 11px; font-size: 9.5px; color: #fff; display: inline-flex; gap: 6px; align-items: center; }
|
|
85
|
+
.tool-tabs { position: absolute; display: inline-flex; gap: 4px; background: rgba(0,0,0,.5); border-radius: 999px; padding: 3px 4px; }
|
|
86
|
+
.tool-tabs span { font-size: 8.5px; color: rgba(255,255,255,.6); width: 18px; height: 18px; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
|
|
87
|
+
.tool-tabs span.on { background: rgba(255,255,255,.92); color: #111; font-weight: 700; width: auto; padding: 0 7px; }
|
|
88
|
+
.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
|
+
```
|
|
90
|
+
|
|
91
|
+
**Annotation chips — yellow callouts pinned over the frame (label intent):**
|
|
92
|
+
|
|
93
|
+
```css
|
|
94
|
+
.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
|
+
```
|
|
96
|
+
|
|
97
|
+
**Inline SVG icons:** define `<symbol>` elements in a hidden `<svg>` at the top of `<body>`
|
|
98
|
+
and reference with `<use href="#id"/>`. Stroke icons (`stroke="currentColor"`,
|
|
99
|
+
`stroke-width` ~1.6).
|
|
100
|
+
|
|
101
|
+
## Hard rules (non-negotiable)
|
|
102
|
+
|
|
103
|
+
- Lay the screen out to fill the chosen orientation; use whatever media/aspect ratios the
|
|
104
|
+
design needs — there is no fixed aspect-ratio requirement.
|
|
105
|
+
- NO emojis anywhere. Every icon is inline stroke SVG.
|
|
106
|
+
- Hand-roll every control with the pill/capsule convention above — do not rely on system/OS
|
|
107
|
+
chrome or platform glass effects.
|
|
108
|
+
- Plain HTML + INLINE CSS ONLY (a single `<style>` in `<head>`). No external stylesheets,
|
|
109
|
+
no network fonts, no frameworks.
|
|
110
|
+
- ABSOLUTELY NO `<script>` tags and NO `on*` event handlers. Fully static; renders state
|
|
111
|
+
with CSS alone (runs in a sandboxed iframe).
|
|
112
|
+
|
|
113
|
+
## Document contract
|
|
114
|
+
|
|
115
|
+
- Respond with a complete HTML document starting at `<!DOCTYPE html>`.
|
|
116
|
+
- `<title>` = short screen name.
|
|
117
|
+
- `<meta name="figura:context" content="…">` = one-line design-intent summary.
|
|
118
|
+
- An `<h1>` naming the screen.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Figura Fig — Examples
|
|
2
|
+
|
|
3
|
+
Two worked examples of a prompt → what gets generated and saved. Each produces ONE
|
|
4
|
+
self-contained HTML document and persists it to the Figura team via `bunx figura-cli fig create`.
|
|
5
|
+
(These use the neutral default tokens; with a custom team brand, swap in its palette/type.)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Example 1 — "mock up a settings screen with a sticky save bar" (mobile)
|
|
10
|
+
|
|
11
|
+
**Resolved scope:** area `settings`, orientation `portrait`.
|
|
12
|
+
|
|
13
|
+
**Generated document:** a `.device-port` iPhone frame with a top dynamic-island. Inside, a
|
|
14
|
+
`.screen`: a "Settings" header + a search field, then grouped rows (Account, Notifications,
|
|
15
|
+
Privacy) — each row a label + an inline stroke-SVG glyph + a control (chevron, or a CSS-only
|
|
16
|
+
toggle in the accent color). A sticky bottom save bar ("3 unsaved changes" + Save / Discard)
|
|
17
|
+
pinned over the screen. No `.preview` media area (this screen has none).
|
|
18
|
+
|
|
19
|
+
A `.annot` chip points at the toggles: "active = accent #4C8DFF". `<title>` = "Settings —
|
|
20
|
+
account & notifications"; `<meta name="figura:context">` summarizes the unsaved-changes
|
|
21
|
+
state; `<h1>` reads "Settings".
|
|
22
|
+
|
|
23
|
+
**Persisted (and shared):**
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
cat <<'HTML' | bunx figura-cli fig create \
|
|
27
|
+
--title "Settings — account & notifications" \
|
|
28
|
+
--area settings \
|
|
29
|
+
--orientation portrait \
|
|
30
|
+
--tags settings,toggles,save-bar \
|
|
31
|
+
--publish
|
|
32
|
+
… the generated document …
|
|
33
|
+
HTML
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then report the returned shareable `url`.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Example 2 — "the pricing page, three tiers" (web)
|
|
41
|
+
|
|
42
|
+
**Resolved scope:** platform `web` (a marketing page, not a phone screen).
|
|
43
|
+
|
|
44
|
+
**Generated document:** a `.frame-web` browser window (r/y/g window dots + an address pill)
|
|
45
|
+
around a responsive `.viewport`: a top nav (wordmark + links + a CTA button in the accent),
|
|
46
|
+
a centered headline + subhead, then a 3-column pricing grid — each card a name, price,
|
|
47
|
+
feature list with inline stroke-SVG checks, and a button (the middle/recommended card
|
|
48
|
+
emphasized with the accent border). Neutral near-black canvas, one accent hue, system sans,
|
|
49
|
+
8px rhythm. No phone frame, no fixed aspect ratio — responsive content fills the frame.
|
|
50
|
+
|
|
51
|
+
A `.annot` chip marks the recommended card. `<title>` = "Pricing — three tiers";
|
|
52
|
+
`<meta name="figura:context">` summarizes the comparison; `<h1>` reads "Pricing".
|
|
53
|
+
|
|
54
|
+
**Persisted (private — omit `--publish` to keep it team-only):**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cat <<'HTML' | bunx figura-cli fig create \
|
|
58
|
+
--title "Pricing — three tiers" \
|
|
59
|
+
--area other \
|
|
60
|
+
--tags pricing,marketing,web
|
|
61
|
+
… the generated document …
|
|
62
|
+
HTML
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then report the fig (saved privately, or the shareable `url` if you added `--publish`).
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Example 3 — "make the earlier settings screen darker" (revision)
|
|
70
|
+
|
|
71
|
+
**Resolved as a revision** (it iterates on a fig from Example 1, not a new screen).
|
|
72
|
+
|
|
73
|
+
**Resolve the prior id:** if the settings fig was created earlier in this session, reuse the
|
|
74
|
+
id it printed. Otherwise list and match by title/area:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
bunx figura-cli fig list --json --area settings
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Pick the matching row's `id` (ask if more than one plausibly matches). Then fetch its HTML:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
bunx figura-cli fig open <priorFigId> --print
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Edit on top of it:** keep the same structure (header, grouped rows, sticky save bar) and
|
|
87
|
+
re-tint the surfaces to neutral **dark** values — near-black canvas, raised dark surfaces for
|
|
88
|
+
the cards/rows, light text — keeping the SAME single accent hue for active toggles. Don't
|
|
89
|
+
regenerate from scratch; preserve the design system.
|
|
90
|
+
|
|
91
|
+
**Persist as a new version:**
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
cat <<'HTML' | bunx figura-cli fig revise <priorFigId> \
|
|
95
|
+
--title "Settings — darker theme" \
|
|
96
|
+
--tags settings,toggles,dark \
|
|
97
|
+
--publish
|
|
98
|
+
… the updated document …
|
|
99
|
+
HTML
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The result JSON includes `version` (e.g. `2`) and `rootFigId`. Report it as "revision v2 of
|
|
103
|
+
\<root\>" plus the shareable `url` if published. `--area`/`--orientation` were inherited from
|
|
104
|
+
the parent, so they didn't need to be passed again.
|