wand-kit 0.3.2 → 0.5.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/PROMPT.md +221 -19
- package/SKILL.md +100 -20
- package/START-HERE.md +12 -1
- package/brands/current/tokens.json +10 -2
- package/brands/interim/assets/avatar.svg +1 -0
- package/brands/interim/assets/closing-art.png +0 -0
- package/brands/interim/assets/cover-art.png +0 -0
- package/brands/interim/assets/cover-portrait-art.png +0 -0
- package/brands/interim/assets/divider-art.png +0 -0
- package/brands/interim/assets/glyphs/README.md +29 -0
- package/brands/interim/assets/glyphs/activity.svg +15 -0
- package/brands/interim/assets/glyphs/atom.svg +17 -0
- package/brands/interim/assets/glyphs/badge-check.svg +16 -0
- package/brands/interim/assets/glyphs/bell.svg +16 -0
- package/brands/interim/assets/glyphs/blocks.svg +16 -0
- package/brands/interim/assets/glyphs/book-open.svg +16 -0
- package/brands/interim/assets/glyphs/bot.svg +20 -0
- package/brands/interim/assets/glyphs/boxes.svg +26 -0
- package/brands/interim/assets/glyphs/brain.svg +23 -0
- package/brands/interim/assets/glyphs/briefcase.svg +16 -0
- package/brands/interim/assets/glyphs/building-2.svg +21 -0
- package/brands/interim/assets/glyphs/calendar.svg +18 -0
- package/brands/interim/assets/glyphs/chart-column.svg +18 -0
- package/brands/interim/assets/glyphs/chart-line.svg +16 -0
- package/brands/interim/assets/glyphs/chart-pie.svg +16 -0
- package/brands/interim/assets/glyphs/circle-check.svg +16 -0
- package/brands/interim/assets/glyphs/clipboard-check.svg +17 -0
- package/brands/interim/assets/glyphs/clock.svg +16 -0
- package/brands/interim/assets/glyphs/cloud.svg +15 -0
- package/brands/interim/assets/glyphs/code.svg +15 -0
- package/brands/interim/assets/glyphs/coins.svg +18 -0
- package/brands/interim/assets/glyphs/compass.svg +16 -0
- package/brands/interim/assets/glyphs/cpu.svg +24 -0
- package/brands/interim/assets/glyphs/database.svg +17 -0
- package/brands/interim/assets/glyphs/eye.svg +16 -0
- package/brands/interim/assets/glyphs/file-check.svg +17 -0
- package/brands/interim/assets/glyphs/filter.svg +15 -0
- package/brands/interim/assets/glyphs/fingerprint.svg +23 -0
- package/brands/interim/assets/glyphs/flag.svg +16 -0
- package/brands/interim/assets/glyphs/gauge.svg +16 -0
- package/brands/interim/assets/glyphs/gavel.svg +19 -0
- package/brands/interim/assets/glyphs/git-branch.svg +18 -0
- package/brands/interim/assets/glyphs/globe.svg +17 -0
- package/brands/interim/assets/glyphs/graduation-cap.svg +17 -0
- package/brands/interim/assets/glyphs/handshake.svg +19 -0
- package/brands/interim/assets/glyphs/hexagon.svg +15 -0
- package/brands/interim/assets/glyphs/index.json +177 -0
- package/brands/interim/assets/glyphs/infinity.svg +15 -0
- package/brands/interim/assets/glyphs/key.svg +17 -0
- package/brands/interim/assets/glyphs/landmark.svg +20 -0
- package/brands/interim/assets/glyphs/layers.svg +17 -0
- package/brands/interim/assets/glyphs/lightbulb.svg +17 -0
- package/brands/interim/assets/glyphs/link.svg +16 -0
- package/brands/interim/assets/glyphs/list-checks.svg +19 -0
- package/brands/interim/assets/glyphs/lock.svg +16 -0
- package/brands/interim/assets/glyphs/map.svg +17 -0
- package/brands/interim/assets/glyphs/megaphone.svg +16 -0
- package/brands/interim/assets/glyphs/message-square.svg +15 -0
- package/brands/interim/assets/glyphs/milestone.svg +17 -0
- package/brands/interim/assets/glyphs/network.svg +19 -0
- package/brands/interim/assets/glyphs/orbit.svg +19 -0
- package/brands/interim/assets/glyphs/package.svg +18 -0
- package/brands/interim/assets/glyphs/plug.svg +18 -0
- package/brands/interim/assets/glyphs/puzzle.svg +15 -0
- package/brands/interim/assets/glyphs/radar.svg +22 -0
- package/brands/interim/assets/glyphs/receipt.svg +17 -0
- package/brands/interim/assets/glyphs/refresh-cw.svg +18 -0
- package/brands/interim/assets/glyphs/rocket.svg +18 -0
- package/brands/interim/assets/glyphs/route.svg +17 -0
- package/brands/interim/assets/glyphs/scale.svg +19 -0
- package/brands/interim/assets/glyphs/search.svg +16 -0
- package/brands/interim/assets/glyphs/server.svg +18 -0
- package/brands/interim/assets/glyphs/settings.svg +16 -0
- package/brands/interim/assets/glyphs/share-2.svg +19 -0
- package/brands/interim/assets/glyphs/shield-check.svg +16 -0
- package/brands/interim/assets/glyphs/shuffle.svg +19 -0
- package/brands/interim/assets/glyphs/sparkles.svg +19 -0
- package/brands/interim/assets/glyphs/square-stack.svg +17 -0
- package/brands/interim/assets/glyphs/target.svg +17 -0
- package/brands/interim/assets/glyphs/trending-up.svg +16 -0
- package/brands/interim/assets/glyphs/triangle-alert.svg +17 -0
- package/brands/interim/assets/glyphs/trophy.svg +20 -0
- package/brands/interim/assets/glyphs/users.svg +18 -0
- package/brands/interim/assets/glyphs/wallet.svg +16 -0
- package/brands/interim/assets/glyphs/wand-sparkles.svg +22 -0
- package/brands/interim/assets/glyphs/workflow.svg +17 -0
- package/brands/interim/assets/glyphs/zap.svg +15 -0
- package/brands/interim/assets/mark.svg +1 -0
- package/brands/interim/assets/social/composition.json +6833 -0
- package/brands/interim/assets/spark-lavender.png +0 -0
- package/brands/interim/assets/spark-violet.png +0 -0
- package/brands/interim/assets/statement-art.png +0 -0
- package/brands/interim/assets/story/agent-alpha.png +0 -0
- package/brands/interim/assets/story/agent.png +0 -0
- package/brands/interim/assets/story/economy-alpha.png +0 -0
- package/brands/interim/assets/story/economy.png +0 -0
- package/brands/interim/assets/story/index.json +214 -0
- package/brands/interim/assets/story/learning-alpha.png +0 -0
- package/brands/interim/assets/story/learning.png +0 -0
- package/brands/interim/assets/story/organization-alpha.png +0 -0
- package/brands/interim/assets/story/organization.png +0 -0
- package/brands/interim/assets/story/worker-alpha.png +0 -0
- package/brands/interim/assets/story/worker-light.png +0 -0
- package/brands/interim/assets/story/worker.png +0 -0
- package/brands/interim/assets/wordmark-on-dark.png +0 -0
- package/brands/interim/assets/wordmark-on-dark.svg +1 -0
- package/brands/interim/assets/wordmark-on-light.png +0 -0
- package/brands/interim/assets/wordmark-on-light.svg +1 -0
- package/brands/interim/fonts/Geist-Book.ttf +0 -0
- package/brands/interim/fonts/Geist-Medium.ttf +0 -0
- package/brands/interim/fonts/Geist-Regular.ttf +0 -0
- package/brands/interim/fonts/Geist-SemiBold.ttf +0 -0
- package/brands/interim/fonts/Newsreader-Italic.ttf +0 -0
- package/brands/interim/fonts/Newsreader-Medium.ttf +0 -0
- package/brands/interim/fonts/Newsreader-MediumItalic.ttf +0 -0
- package/brands/interim/fonts/Newsreader-Regular.ttf +0 -0
- package/brands/interim/fonts/OFL-Geist.txt +93 -0
- package/brands/interim/fonts/OFL-Newsreader.txt +93 -0
- package/brands/interim/fonts/faces.json +12 -0
- package/brands/interim/lib/composition.js +169 -0
- package/brands/interim/lib/composition.mjs +101 -0
- package/brands/interim/lib/glyphs.js +89 -0
- package/brands/interim/lib/measure.js +121 -0
- package/brands/interim/lib/pdf.js +597 -0
- package/brands/interim/lib/ttf.py +169 -0
- package/brands/interim/lib/wandxml.py +37 -0
- package/brands/interim/tokens.json +299 -0
- package/brands/next/tokens.json +14 -2
- package/examples/social/social.json +23 -0
- package/lib/audit.js +142 -0
- package/lib/brand.js +12 -7
- package/lib/components.js +42 -10
- package/lib/engine.js +72 -9
- package/lib/library.js +180 -0
- package/lib/pptx.js +1 -1
- package/lib/social.js +366 -0
- package/lib/talk.js +37 -4
- package/library/index.json +629 -0
- package/library/interim/avatar-800x800.png +0 -0
- package/library/interim/icons/apple-touch-icon.png +0 -0
- package/library/interim/icons/favicon-16.png +0 -0
- package/library/interim/icons/favicon-32.png +0 -0
- package/library/interim/icons/favicon-48.png +0 -0
- package/library/interim/icons/favicon.ico +0 -0
- package/library/interim/icons/favicon.svg +1 -0
- package/library/interim/icons/icon-192.png +0 -0
- package/library/interim/icons/icon-512.png +0 -0
- package/library/interim/icons/icon-tags.html +5 -0
- package/library/interim/icons/site.webmanifest +19 -0
- package/library/interim/linkedin-banner-1584x396.png +0 -0
- package/library/interim/linkedin-company-1128x191.png +0 -0
- package/library/interim/open-agent-discovery-share-1200x630.png +0 -0
- package/library/interim/open-agent-discovery-share-head-tags.html +17 -0
- package/library/interim/wand-ai-share-1200x630.png +0 -0
- package/library/interim/wand-ai-share-head-tags.html +17 -0
- package/library/interim/x-header-1500x500.png +0 -0
- package/package.json +2 -2
- package/templates/card.mjs +6 -2
- package/templates/page.mjs +1 -1
- package/templates/slide.mjs +1 -1
- package/templates/storyboard.mjs +1 -1
- package/wand.js +65 -6
package/PROMPT.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# Wand Power Prompt — Studio (v0.1)
|
|
2
2
|
|
|
3
3
|
One design surface for every material a sales or marketing team needs, on
|
|
4
|
-
|
|
4
|
+
any of the three Wand brands. The page is HTML; it is composed from a component library on
|
|
5
5
|
brand tokens; Chromium renders it; every gate measures that render; and every
|
|
6
6
|
export (PDF, PNG, PowerPoint, a one-file HTML) is read from it, so nothing can
|
|
7
7
|
drift from what was reviewed on screen.
|
|
8
8
|
|
|
9
9
|
This document is the design system and the pipeline, and the source of truth
|
|
10
|
-
on every design question. `brand/BRAND.md
|
|
10
|
+
on every design question. `brand/BRAND.md`, `brand-next/BRAND.md` and
|
|
11
|
+
`brand-interim/BRAND.md` win on
|
|
11
12
|
values (a hex, a face, an asset); `STATUS.md` is state; `SKILL.md` is procedure.
|
|
12
13
|
|
|
13
14
|
**Why this exists.** The outputs that reviewed best in October 2026 (the
|
|
@@ -22,24 +23,27 @@ components, gates, exports.
|
|
|
22
23
|
|
|
23
24
|
## 0. Ground truth
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
Three brands, one component set.
|
|
26
27
|
|
|
27
28
|
| Brand | Directory | Faces | Guideline |
|
|
28
29
|
|---|---|---|---|
|
|
29
30
|
| `current` | `brand/` | Geist | the Kearney leadership deck; `brand/BRAND.md` |
|
|
30
|
-
| `next` | `brand-next/` | FK Roman Standard Light, Overused Grotesk | the website, read 2026-10-05; `brand-next/BRAND.md` |
|
|
31
|
+
| `next` | `brand-next/` | FK Roman Standard Light, Overused Grotesk | the staging website, read 2026-10-05; `brand-next/BRAND.md` |
|
|
32
|
+
| `interim` | `brand-interim/` | Geist, Newsreader | the live wand.ai, read 2026-10-21, and the social design approved on it 2026-10-22, which wins where they differ; `brand-interim/BRAND.md` |
|
|
31
33
|
|
|
32
34
|
Each directory's `tokens.json` carries the brand as values a kit can draw with:
|
|
33
35
|
`swatch` (the measured hexes), `roles` (what each value is for, once per
|
|
34
36
|
ground), `faces` (the files and their PowerPoint names), `shape` (radius,
|
|
35
|
-
strokes
|
|
37
|
+
strokes, and `artShade`, the shade the kit lays over a dark page's art, 0.3
|
|
38
|
+
unless a brand says otherwise) and `art` (which file plays which role). A component asks for a role
|
|
36
39
|
(`--ink`, `--accent`, `--emph`) and never for a hex. Where a hex in
|
|
37
40
|
`tokens.json` and `BRAND.md` differ, `BRAND.md` is right and `tokens.json` has
|
|
38
41
|
drifted.
|
|
39
42
|
|
|
40
|
-
`current` is the default while the
|
|
41
|
-
user asks for the new brand
|
|
42
|
-
|
|
43
|
+
`current` is the default while the brands overlap; a job is on `next` when the
|
|
44
|
+
user asks for the new brand and on `interim` when they ask for the interim
|
|
45
|
+
brand or the live site's look. The default is one constant, `DEFAULT_BRAND`
|
|
46
|
+
in `kit/lib/brand.js`, and `doctor` prints the rule from it. The FK Roman
|
|
43
47
|
Standard licence for documents is still to be confirmed
|
|
44
48
|
(`brand-next/fonts/LICENSE-FONTS.md`).
|
|
45
49
|
|
|
@@ -80,13 +84,47 @@ the ground's values, so one component draws on both.
|
|
|
80
84
|
| `label` | 6C5CE7 | A78BFA | tags, section numbers |
|
|
81
85
|
| `emph` / `emphInk` / `emphText` / `emphAccent` | 251C63 / FFF / DCD6F5 / AA9BFF | 4D2E8C / FFF / DCD6F5 / C4B5F4 | the emphasis card and what sits on it |
|
|
82
86
|
| `stroke` / `rule` / `track` / `surface` | E4E0F2 / E4E0F2 / E9E6F5 / EBE8F8 | 5B4BB0 / 3A2E63 / 1A1033 / 1A1033 | card strokes, hairlines, meter tracks, tiles |
|
|
87
|
+
| `second` / `secondSm` | 6C5CE7 / 6C5CE7 | 9481FF / 9481FF | a title's phrase, large / small (on this brand, the accent itself) |
|
|
88
|
+
| `gradeLow` / `gradeHigh` | 240F48 / F8F6FB | the same | the photograph grade: where blacks lift to, where highlights settle |
|
|
83
89
|
|
|
84
90
|
The next brand fills the same roles from the website (gold the one accent,
|
|
85
|
-
violets as grounds, beige as paper); see `brand-next/tokens.json`.
|
|
91
|
+
violets as grounds, beige as paper); see `brand-next/tokens.json`. Its
|
|
92
|
+
`second` is a quiet tone, not gold (7B7B79 on light, 9D99A8 on dark, large
|
|
93
|
+
type only; `secondSm`, the text grey, below that size).
|
|
94
|
+
|
|
95
|
+
The interim brand fills them from the live site and the social design
|
|
96
|
+
approved on it (2026-10-22), which wins where they differ: the approved
|
|
97
|
+
ground (`14101C`) is the dark ground, with ink `F7F5F9` and lavender
|
|
98
|
+
(`D4BCE8`) the accent for what is drawn; stone (`F5F3EF`) the light ground
|
|
99
|
+
with strong violet (`6D41B3`) the accent; a title's phrase is `violet`
|
|
100
|
+
(`C2A1EF`) on dark, on every page including the art pages (`accentText`), and
|
|
101
|
+
`765098` on light, the site's own `h1 em` colours; the spark takes the
|
|
102
|
+
phrase's colour. See `brand-interim/BRAND.md`.
|
|
86
103
|
|
|
87
104
|
**Rules.**
|
|
88
105
|
- One accent. The accent phrase in a title is the single most recognisable
|
|
89
106
|
device in the system: one per title, never two, the sentence period in ink.
|
|
107
|
+
- **On the next brand a title has two tones and gold is rare.** The phrase
|
|
108
|
+
takes `second`, a quieter tone of the ink; gold stays for the pages that
|
|
109
|
+
carry the brand's art (the cover, a statement, the close), for figures and
|
|
110
|
+
for the spark. The website's own headings carry no gold at all, and the
|
|
111
|
+
wand.ai rebuild (October 2026) read as a template while every heading's
|
|
112
|
+
second line was gold: when gold is everywhere it means nothing. On the
|
|
113
|
+
current brand `second` is the accent, so nothing changes there.
|
|
114
|
+
- **On the interim brand a title's phrase changes face, not weight.** `<em>`
|
|
115
|
+
sets in Newsreader at the display's weight, the site's own `h1 em`; on the
|
|
116
|
+
pages that carry the art (the cover, a statement, the close) it is the
|
|
117
|
+
italic, as the hero's and the approved lockup's are. Its colour is one
|
|
118
|
+
violet on dark, the art pages too, as the approved banners set it; the
|
|
119
|
+
lavender accent stays for what is drawn, the figures and nothing else.
|
|
120
|
+
- **On the interim brand the cover is the approved composition.** The planet's
|
|
121
|
+
rim, four trails sweeping under the title to their dots and up through the
|
|
122
|
+
hero's oval, drawn unshaded (`shape.artShade` 0) with the title untracked
|
|
123
|
+
(`faces.display.coverTracking` 0). The composition itself
|
|
124
|
+
(`brand-interim/assets/social/composition.json`, drawn by
|
|
125
|
+
`brand-interim/lib/composition.mjs`) is what a link preview or a social
|
|
126
|
+
banner on this brand is cut from: a window of it at one scale, never its
|
|
127
|
+
parts re-proportioned.
|
|
90
128
|
- One emphasis card per row, at most one or two per page.
|
|
91
129
|
- Light pages carry no art. Dark pages carry art on the cover, the closing and
|
|
92
130
|
a statement; a dark content page is flat.
|
|
@@ -101,11 +139,16 @@ Three face roles per brand: `display` (titles, figures, the lockup), `body`
|
|
|
101
139
|
Tracking and leading travel with the face in `tokens.json`; the CSS sets them
|
|
102
140
|
from the same values.
|
|
103
141
|
|
|
104
|
-
| Role | current | next |
|
|
105
|
-
|
|
106
|
-
| display | Geist SemiBold, −0.02em | FK Roman Standard Light, −0.07em, 1.06 |
|
|
107
|
-
| body | Geist Regular | Overused Grotesk, −0.02em |
|
|
108
|
-
| label | Geist SemiBold, +0.18em, caps | FK Roman Standard Light, caps |
|
|
142
|
+
| Role | current | next | interim |
|
|
143
|
+
|---|---|---|---|
|
|
144
|
+
| display | Geist SemiBold, −0.02em | FK Roman Standard Light, −0.07em, 1.06 | Geist Medium (500), untracked, 1.025 |
|
|
145
|
+
| body | Geist Regular | Overused Grotesk, −0.02em | Geist Regular |
|
|
146
|
+
| label | Geist SemiBold, +0.18em, caps | FK Roman Standard Light, caps | Geist Medium, +0.11em, caps |
|
|
147
|
+
| phrase | the display face | the display face | Newsreader Medium (500, optical size 72), untracked; italic on the art pages |
|
|
148
|
+
|
|
149
|
+
A brand that sets a title's phrase in another face declares `faces.phrase`;
|
|
150
|
+
the CSS reads it as `--face-phrase` and friends, and a brand without it leaves
|
|
151
|
+
the phrase in the title's face, unchanged.
|
|
109
152
|
|
|
110
153
|
**Weight carries no hierarchy on the next brand** (the serif ships one weight);
|
|
111
154
|
the face does. Components therefore never rely on bold to separate levels, and
|
|
@@ -120,7 +163,8 @@ Figures are tabular (`font-variant-numeric: tabular-nums` on the page).
|
|
|
120
163
|
## 4. Chrome
|
|
121
164
|
|
|
122
165
|
Drawn by `c.page()` on every page: eyebrow (`job.tag | eyebrow`), mark, footer
|
|
123
|
-
(`job.footer`, page number
|
|
166
|
+
(`job.footer`, page number; a page's own `footer` replaces the line, for a
|
|
167
|
+
source note such as "Illustrative operating sequence"). The cover and closing pages are `c.cover()` and
|
|
124
168
|
`c.closing()`, which place the brand art and the lockup; a job gives them
|
|
125
169
|
words, never styling. Every piece of chrome is `.deco` or chrome-classed, so
|
|
126
170
|
the gates know what is content and what is frame.
|
|
@@ -142,6 +186,7 @@ The components (`node wand.js components`; `kit/lib/components.js`):
|
|
|
142
186
|
| `quote({ text, by, emph })`, `who` | testimonial cards, name over role, no photographs |
|
|
143
187
|
| `stats`, `delta(from, to)` | figures, before-and-after |
|
|
144
188
|
| `steps(items)` | next steps with arrows |
|
|
189
|
+
| `photo(name, { pos })` | a brand photograph filling its box, with the brand's grade |
|
|
145
190
|
| `callout`, `list`, `chapter`, `img`, `icon`, `tile` | the rest |
|
|
146
191
|
| `enter(kind, i)`, `step(n, html)`, `countup(text)`, `stat({ count })` | motion in a talk (§12) |
|
|
147
192
|
| `video({ src, poster })`, `demo({ src, poster })` | a clip or a live page on a slide (§12) |
|
|
@@ -163,8 +208,30 @@ decide, and that make or break a page:
|
|
|
163
208
|
ground.
|
|
164
209
|
- **Short lines in cards.** One sentence and an outcome. The card's body is
|
|
165
210
|
never the place for the argument.
|
|
211
|
+
- **Two lines a paragraph on a slide, at most** (Carlos, 2026-10-27: past two
|
|
212
|
+
"it breaks a lot", in PowerPoint and Google Slides above all). Keep the
|
|
213
|
+
words and give them room: two by two instead of four across, a ruled row
|
|
214
|
+
(the title left, the line right) instead of a narrow column, a band for a
|
|
215
|
+
unit, a lead under its title. The `lines` gate counts each block's lines
|
|
216
|
+
from the browser's own line boxes; it warns on every deck and fails a job
|
|
217
|
+
that sets `maxLines`. Titles balance and paragraphs wrap pretty
|
|
218
|
+
(`text-wrap`), so no word sits alone on a line.
|
|
166
219
|
- **Equal heights in a row** (`stretch`), titles at one height, and the empty
|
|
167
220
|
space at the foot of a page shared by its sections, never left under one.
|
|
221
|
+
- **One arc.** Night, then day, then first light: the dark cover with its
|
|
222
|
+
art, the argument on light pages, one dark statement where the piece turns,
|
|
223
|
+
and the close. A piece that switches ground on every page reads as a
|
|
224
|
+
slideshow of boxes.
|
|
225
|
+
- **No composition three pages running.** The same heading, then the same
|
|
226
|
+
three cards, page after page, is what makes a set of pages read as a
|
|
227
|
+
template; the variety gate names the run. Vary it: a statement set large,
|
|
228
|
+
a split with a photograph, a figure, a page that is one exhibit.
|
|
229
|
+
- **Photographs large or not at all**, through `photo()`: full bleed or a full
|
|
230
|
+
column, never a thumbnail; architecture and light from the brand's set,
|
|
231
|
+
never stock (a person at a desk, a stethoscope, a form, a highway). Every
|
|
232
|
+
photograph takes the brand's one grade, so they read as one shoot.
|
|
233
|
+
- **An exhibit on hairlines, not in a box.** A diagram or a flow sits on the
|
|
234
|
+
ground with rules; a frame around it reads as a dashboard widget.
|
|
168
235
|
- **A slide balances and sizes itself.** Its body sits in the space under the
|
|
169
236
|
title, not in the top quarter; a slide whose content fills under 55% of it
|
|
170
237
|
takes the type scale a step up (`.big`) when that still fits, and the space
|
|
@@ -191,7 +258,12 @@ new ─▶ argue ─▶ content ─▶ compose ─▶ build ─▶ review ─▶
|
|
|
191
258
|
per page, the contact sheet. `watch` does this on every save in under a
|
|
192
259
|
second with the browser kept warm.
|
|
193
260
|
6. **review** — look at `out/sheet.png`, then at any page the gates named.
|
|
194
|
-
Read the pages as the reader will: does each carry its claim?
|
|
261
|
+
Read the pages as the reader will: does each carry its claim? Then read
|
|
262
|
+
the sheet as a creative director would, the questions the build prints
|
|
263
|
+
under it: is one page memorable, and which; is the accent rare;
|
|
264
|
+
are photographs large or absent; are hairlines and type doing the
|
|
265
|
+
separating. A piece where no page would stop someone who has seen a
|
|
266
|
+
hundred decks is not finished: make one page that does.
|
|
195
267
|
7. **ship** — `node wand.js ship <job> [--pptx]`: the build, the one-file HTML,
|
|
196
268
|
the PowerPoint. A deck's HTML is a talk (§12), a storyboard's plays (§13),
|
|
197
269
|
and either runtime is driven before it ships. `--brand next` (or `current`)
|
|
@@ -204,6 +276,7 @@ new ─▶ argue ─▶ content ─▶ compose ─▶ build ─▶ review ─▶
|
|
|
204
276
|
|---|---|---|
|
|
205
277
|
| fit | anything in the content box runs past it, under the footer, or off the sides | a page that fits and reads badly |
|
|
206
278
|
| space (warn, slides) | a slide still uses under 40% of its content area after sizing itself | whether the content deserves the slide |
|
|
279
|
+
| variety (warn) | three pages running share one composition (the same blocks in the same order) | two pages composed alike but far apart |
|
|
207
280
|
| coverage | a line of `content.txt` is not on the page (whole, or in its declared parts), less the `cut` lines | a line that is present and in the wrong place |
|
|
208
281
|
| overlap | one text box sits on another | text on art |
|
|
209
282
|
| brand | a computed colour, border or fill that is not a token or a declared theme colour | gradients and images |
|
|
@@ -214,13 +287,17 @@ new ─▶ argue ─▶ content ─▶ compose ─▶ build ─▶ review ─▶
|
|
|
214
287
|
| pdf text | the PDF's text misses a line, or carries an em dash | |
|
|
215
288
|
| contrast (warn) | text under WCAG AA against its background, chrome excepted | |
|
|
216
289
|
| measure (warn) | a paragraph over the surface's characters-per-line | |
|
|
217
|
-
|
|
|
290
|
+
| lines (warn; hard with `maxLines`) | a block of text on a slide that sets in more than two lines (or the job's `maxLines`), counted from its line boxes; autosizing never steps a slide up past it | a two-line paragraph that reads badly |
|
|
291
|
+
| crop (warn, og) | a share image's words leave the centre square, which Slack and WhatsApp cut as their thumbnail | the chrome, and how the image reads at 128pt |
|
|
292
|
+
| images | an image did not load, or is drawn at another shape than its own (stretched or squeezed past 2%; only `object-fit` cover, contain or none may change a box's shape) | an image that loaded and is the wrong one |
|
|
218
293
|
| media | a demo, a clip or its poster is missing | a demo that loads and misbehaves |
|
|
219
294
|
| console | a page error | |
|
|
220
295
|
| runtime (ship, decks) | a slide or step the keyboard cannot reach, the overview or notes not opening, the presenter view out of step, a demo that never loads | how the motion feels |
|
|
221
296
|
| timing (warn, boards) | the board is more than 10% off its `target` | the real voiceover's pace |
|
|
222
297
|
| frames (warn, boards) | a frame is still to draw | a frame that is drawn and wrong |
|
|
223
298
|
| player (ship, boards) | the player does not run, scrub, or caption | |
|
|
299
|
+
| social (each image) | the lockup leaves its place or the centre square, the ring is cut, type under the floor, a share image over 300 KB | how it reads at 128pt: the review questions |
|
|
300
|
+
| library (`--check`) | a library file is not the one approved, or the kit no longer draws it within its tolerance | a file that was approved and is wrong |
|
|
224
301
|
|
|
225
302
|
The gates read the DOM Chromium laid out for the PDF; nothing is inferred from
|
|
226
303
|
the spec. What no gate sees: the argument, the pacing, and whether the right
|
|
@@ -274,7 +351,9 @@ component was chosen. That is the review.
|
|
|
274
351
|
4. **A scratch voice.** The Wand OS film timed its board against a voice from
|
|
275
352
|
macOS `say`; the chat sandbox has none, so timing here is words at `wpm`.
|
|
276
353
|
A recorded voiceover passed as `audio` leads the player.
|
|
277
|
-
|
|
354
|
+
5. **Email surfaces**: declared in §1's spirit, not yet in the table. Banners
|
|
355
|
+
exist on the interim brand, drawn from its composition (§14); on the other
|
|
356
|
+
brands they are still to come.
|
|
278
357
|
|
|
279
358
|
## 12. Talks: motion and the presenter
|
|
280
359
|
|
|
@@ -293,7 +372,11 @@ figure final, every poster.
|
|
|
293
372
|
- **Kinds.** `rise` (the default), `fade`, `pop` for a mark or a figure,
|
|
294
373
|
`grow` for a bar going up, `widen` for a bar going across, `draw` for a
|
|
295
374
|
line that tells a trend (an SVG path with `pathLength="1"`), `count` for a
|
|
296
|
-
figure the room should watch arrive (`stat({ count: true })`, `countup()`)
|
|
375
|
+
figure the room should watch arrive (`stat({ count: true })`, `countup()`),
|
|
376
|
+
`words` for a title whose words rise out of their lines (every title does
|
|
377
|
+
this under `motion: "auto"`), `lit` for a statement that lights word by
|
|
378
|
+
word, `window` for a photograph that opens like a window. A page's art
|
|
379
|
+
(the cover's light, a statement, the close) comes up like first light.
|
|
297
380
|
- **Steps** when the order of the argument is the point: `step(1, html)`, then
|
|
298
381
|
2, then 3. Never more than four on a slide. Going back undoes the last step.
|
|
299
382
|
- **Notes on every slide of a talk**, and `seconds` on each when the talk has a
|
|
@@ -342,3 +425,122 @@ direction (the line, camera, motion, on screen, sound, into next).
|
|
|
342
425
|
- **Both brands:** the board is one job; `--brand next` builds it on the
|
|
343
426
|
website's brand beside the first. Frames drawn as sketches or on brand roles
|
|
344
427
|
follow; an image frame is per brand when it shows the brand.
|
|
428
|
+
|
|
429
|
+
## 14. Social images
|
|
430
|
+
|
|
431
|
+
A brand that carries an approved composition draws its social images from it
|
|
432
|
+
(`node wand.js social <social.json>`, `kit/lib/social.js`), not from a page.
|
|
433
|
+
The interim brand does: its X header, LinkedIn banner, LinkedIn company
|
|
434
|
+
banner and avatar (approved 2026-10-22) measured into one artwork in master
|
|
435
|
+
units (`brand-interim/assets/social/composition.json`: the planet and its
|
|
436
|
+
glow, four trails with their tint and fade, eight dots, the hero's oval, the
|
|
437
|
+
lockup, the marks), drawn by `brand-interim/lib/composition.js`. Every format
|
|
438
|
+
is a window onto it at one scale (`formats`), so a part never changes its
|
|
439
|
+
proportion to the others. Redrawn from it, the three approved banners match
|
|
440
|
+
their exports within 2.5 to 3.8 levels in 255.
|
|
441
|
+
|
|
442
|
+
| Kind | Size (export) | How it sits on the composition |
|
|
443
|
+
|---|---|---|
|
|
444
|
+
| `linkedin-banner` | 1584 × 396 (2x) | the approved banner's window |
|
|
445
|
+
| `x-header` | 1500 × 500 (2x) | the approved header's: lockup 28 higher, ring 38 left |
|
|
446
|
+
| `linkedin-company` | 1128 × 191 (2x) | the approved company banner's |
|
|
447
|
+
| `share` | 1200 × 630 | the art from the planet's rim to past the ring; the lockup set on its own in the centre square |
|
|
448
|
+
| `square` | 1080 × 1080 | the art's right half on its diagonal; the lockup in the corner it leaves |
|
|
449
|
+
| `avatar` | 800 × 800 | `avatar.svg` full bleed; every platform cuts its own circle |
|
|
450
|
+
| `profile-photo` | 800 × 800 | the banner's art behind the profile photo's circle, continued below the banner's edge, a cut-out of the person over it in the brand's photo grade |
|
|
451
|
+
| `icons` | 16, 32, 48, 180, 192, 512 | `avatar.svg` set at each size: the favicons as the disc on transparent, the apple-touch and manifest icons full bleed (iOS and Android cut their own shape); `favicon.ico` (16, 32, 48), `favicon.svg`, `site.webmanifest` |
|
|
452
|
+
|
|
453
|
+
**Start from what is live.** Before redrawing a page's preview, read it as
|
|
454
|
+
the feeds do: `node wand.js social --audit <url> [more urls]` reads each
|
|
455
|
+
page's og: and twitter: tags and its image, and shows that image in
|
|
456
|
+
LinkedIn's compact card, Slack's square, X's 2:1 and WhatsApp's thumbnail,
|
|
457
|
+
with the centre square outlined (`audit/audit.png`). Its rows name what the
|
|
458
|
+
2026-10-23 fix found by hand: no image, missing tags, an em dash, an
|
|
459
|
+
og:title that repeats the image, one image for every page, a file over 300
|
|
460
|
+
KB or off 1.91:1. A chat without web access is told so and passes a saved
|
|
461
|
+
page and its image instead (`--image`). A share card's `before` (the image
|
|
462
|
+
live now) puts the old image above the new one in the preview.
|
|
463
|
+
|
|
464
|
+
**A share image (og:image) is seen small and cut** (Hope Frank's feedback,
|
|
465
|
+
2026-10-23, on Rotem Alaluf's post and a Slack unfurl; `runs/2026-10-23-wand-og-fix`):
|
|
466
|
+
|
|
467
|
+
- Slack and WhatsApp show a square cut from the image's centre, so the
|
|
468
|
+
wordmark and the words sit inside the centre square (x 285 to 915 of 1200),
|
|
469
|
+
24px clear of it; the composition's gate and, on a page, the crop row hold
|
|
470
|
+
it. The banners' wide, stepped lockup does not survive that cut: the share
|
|
471
|
+
image sets it left-aligned without the step.
|
|
472
|
+
- LinkedIn shows a link in a post with text as a compact card, the whole
|
|
473
|
+
image about 128pt wide: the words as large as the square allows (64px for
|
|
474
|
+
the site's line), the wordmark at 1.5x the lockup's ratio, and no small
|
|
475
|
+
print at all.
|
|
476
|
+
- One image per page. An article carries its own headline, verbatim (X now
|
|
477
|
+
shows a link card's image with only the domain over it). The site's own
|
|
478
|
+
image carries its line.
|
|
479
|
+
- The `og:title` does not repeat the image's words (the site's became
|
|
480
|
+
`Wand AI`), and nothing in the tags carries an em dash. `head-tags.html`
|
|
481
|
+
holds each page's block: the image's absolute https URL, type, size and alt,
|
|
482
|
+
and one `twitter:card` with the X tags.
|
|
483
|
+
- Every upload goes to a new file name or folder, since every platform caches
|
|
484
|
+
an image by its URL; then LinkedIn Post Inspector, and Slack after its
|
|
485
|
+
cache (about 30 minutes). A post made before keeps its old preview.
|
|
486
|
+
|
|
487
|
+
**The hand-over carries its own instructions.** Every `social` job writes
|
|
488
|
+
`INSTALL.md` beside the images: where each file goes (the banner's pencil,
|
|
489
|
+
the company page's header, the upload folder), the Post Inspector and Sharing
|
|
490
|
+
Debugger links for each page, the cache to wait out, and that nothing is
|
|
491
|
+
verified until it is live. With the PNGs, `head-tags.html` and `preview.png`,
|
|
492
|
+
it goes into one zip (`<name>-<date>.zip`), which is what a web developer or
|
|
493
|
+
a social lead receives. The build prints review questions under the preview,
|
|
494
|
+
the ones that settled the 2026-10-23 cards: does the lockup read at 128pt,
|
|
495
|
+
does Slack's square keep it whole, does the phrase end where the dots meet
|
|
496
|
+
it, is the ring whole and clear, is the banner's lockup clear of the photo.
|
|
497
|
+
|
|
498
|
+
**A profile photo that continues the banner** needs a cut-out of the person
|
|
499
|
+
(a PNG with a transparent ground): Photos or Preview on a Mac lift a subject
|
|
500
|
+
in one step. The kit does not cut a person out itself; from a plain photo it
|
|
501
|
+
asks for the cut-out rather than guess an edge. Its circle is placed where
|
|
502
|
+
LinkedIn's desktop profile puts it; on mobile the photo sits elsewhere and the
|
|
503
|
+
art lines up only roughly, which the dark ground hides.
|
|
504
|
+
|
|
505
|
+
On a brand without a composition, social cards are pages on the `square` and
|
|
506
|
+
`og` surfaces; the crop row warns when a share image's words leave the
|
|
507
|
+
centre square.
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
## 15. The library: approved files, handed out as they are
|
|
511
|
+
|
|
512
|
+
Most asks for a Wand file are not design jobs: "send me the LinkedIn
|
|
513
|
+
banner", "the logo on dark", "the favicon set for the site". The answer is
|
|
514
|
+
the file a person approved, not a new drawing of it. The kit carries those
|
|
515
|
+
files in `library/` (`kit/library/index.json`): on the interim brand the
|
|
516
|
+
LinkedIn banner, the X header, the company banner, the avatar, the share
|
|
517
|
+
images for wand.ai and the NandaIndex article with their tags, and the
|
|
518
|
+
site's icons; on both live brands the wordmark, the mark and the slide art,
|
|
519
|
+
which it names inside the brand folders rather than copying.
|
|
520
|
+
|
|
521
|
+
- **List, then hand over.** `node wand.js library [words]` lists what there
|
|
522
|
+
is; `node wand.js library get <id> --to <folder>` copies it and prints where
|
|
523
|
+
each file goes and who approved it. It needs no browser. A bare name
|
|
524
|
+
(`wordmark`) resolves on the brand the rule gives; a vague one lists the
|
|
525
|
+
candidates.
|
|
526
|
+
- **Never redraw an approved file** to hand it over, never re-export or
|
|
527
|
+
recompress it, never retouch it. If the file asked for is not in the
|
|
528
|
+
library, say so and offer to make it (`social`, or a page): what the kit
|
|
529
|
+
makes is a candidate until a person approves it.
|
|
530
|
+
- **One file, one record.** Each carries its size, use, approval and
|
|
531
|
+
sha256; `get` refuses a copy that does not match.
|
|
532
|
+
- **The library and the kit cannot drift.** `node wand.js library --check`
|
|
533
|
+
proves every file is the one approved (its sha256), then draws again every
|
|
534
|
+
file the kit can draw, from the recipes in the index, and compares: within
|
|
535
|
+
its tolerance it passes; a visible difference warns (a 2px move of the
|
|
536
|
+
share image's lockup does); past 4 levels in 255 or 2% of pixels visibly
|
|
537
|
+
off it fails (a 6px move does). The share images are the files delivered
|
|
538
|
+
on 2026-10-23, drawn at 2x and reduced, which the kit's 1x redraw matches
|
|
539
|
+
within 0.75 levels; every other file is the kit's own, matched exactly.
|
|
540
|
+
- **A file enters only once approved**, through `tools/library.mjs` in the
|
|
541
|
+
repo (`add` for a file, `build` to draw the recipes and rewrite each
|
|
542
|
+
record). A changed sha256 is a changed approved file: the CHANGELOG says so.
|
|
543
|
+
|
|
544
|
+
What is deliberately not in it: the square card and the light-ground
|
|
545
|
+
versions (never approved), profile photos (one person's), and the next
|
|
546
|
+
brand (no approved social design, and its face's licence is open).
|
package/SKILL.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wand-design
|
|
3
|
-
description: Rebrand or create Wand
|
|
3
|
+
description: Rebrand or create Wand decks, documents, storyboards and social images on any Wand brand, or hand out approved Wand files (logos, banners, link previews, icons). Use for branded work or a Wand asset.
|
|
4
4
|
compatibility: Requires Node.js 18+, code execution enabled in claude.ai (Settings > Features), and a Chromium the kit can find (Playwright's cache or the system). No network needed once installed. Python 3 embeds fonts in the .pptx; without it the deck ships with the faces named, not embedded.
|
|
5
5
|
license: Proprietary - Wand AI
|
|
6
6
|
metadata:
|
|
7
|
-
version: "0.
|
|
7
|
+
version: "0.5.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
|
|
@@ -25,7 +25,9 @@ node wand.js doctor
|
|
|
25
25
|
|
|
26
26
|
Every row must be clear, and `chromium` must name a binary. If it does not,
|
|
27
27
|
**stop and say so**: nothing renders without a browser, and never report checks
|
|
28
|
-
you did not run.
|
|
28
|
+
you did not run. The one exception is handing over an approved file
|
|
29
|
+
(`library`, below), which needs no browser. Every path below is relative to
|
|
30
|
+
the kit folder.
|
|
29
31
|
|
|
30
32
|
## Whichever Wand skill brought you here
|
|
31
33
|
|
|
@@ -57,31 +59,56 @@ page. `node wand.js components` lists the vocabulary.
|
|
|
57
59
|
|
|
58
60
|
## Which brand
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
the
|
|
62
|
+
Three brands, one kit: `current` (Geist), `next` (the staging website's) and
|
|
63
|
+
`interim` (the live wand.ai's as its approved social design sets it: Geist
|
|
64
|
+
and Newsreader on a near-black ground, the metallic oval and its trails). `doctor` ends
|
|
65
|
+
with the brand rule: which one is the default, and the words that ask for
|
|
66
|
+
each of the others. Follow it as printed. When the user names no brand, build
|
|
67
|
+
on the default without asking; when their words ask for another, pass
|
|
64
68
|
`--brand` to `new`. One brand per piece, never a mix, and the review note
|
|
65
69
|
says which. The rule lives in the kit, not here, so it can change without
|
|
66
70
|
anyone reinstalling the skill.
|
|
67
71
|
|
|
68
|
-
**The same piece on
|
|
69
|
-
(or `current`) builds the job again on that brand, into
|
|
70
|
-
beside the first. Nothing in the job changes.
|
|
72
|
+
**The same piece on another brand:** `node wand.js ship <job> --brand next`
|
|
73
|
+
(or `interim`, or `current`) builds the job again on that brand, into
|
|
74
|
+
`out-<brand>/` beside the first. Nothing in the job changes.
|
|
71
75
|
|
|
72
76
|
## Read only what the job needs
|
|
73
77
|
|
|
74
78
|
| Job | Read |
|
|
75
79
|
|---|---|
|
|
80
|
+
| An existing Wand file: a logo, a banner, a link preview, the icons, slide art | nothing: `node wand.js library` (PROMPT.md §15 if in doubt) |
|
|
76
81
|
| A document, a two-pager, a case study | `PROMPT.md` §5 and `templates/page.mjs`; `examples/overview/job.mjs` for a finished one |
|
|
77
82
|
| A deck | §5 and `templates/slide.mjs` |
|
|
78
83
|
| An animated deck, a talk, a live demo | §12 and `templates/slide.mjs`; `examples/talk/job.mjs` for a finished one |
|
|
79
84
|
| A storyboard from a script | §13 and `templates/storyboard.mjs`; `examples/storyboard/job.mjs` |
|
|
80
|
-
| Social
|
|
85
|
+
| Social images on the interim brand: banners, link previews, icons, a profile photo | PROMPT.md §14 and `examples/social/social.json` |
|
|
86
|
+
| Social cards on another brand | `templates/card.mjs` |
|
|
81
87
|
| Edit a job this kit built | the job's `job.mjs` only, then `build` |
|
|
82
88
|
|
|
83
89
|
## The jobs
|
|
84
90
|
|
|
91
|
+
### Ask for an existing file (the cheapest job: start here when it fits)
|
|
92
|
+
|
|
93
|
+
"The LinkedIn banner", "our logo on dark", "the favicon for the site", "the
|
|
94
|
+
image wand.ai shares as": these are approved files, and the library hands
|
|
95
|
+
them over as they are (PROMPT.md §15).
|
|
96
|
+
|
|
97
|
+
1. `node wand.js library <words>` (for example `library banner`, `library
|
|
98
|
+
logo`) lists what matches; `node wand.js library` lists everything.
|
|
99
|
+
2. `node wand.js library get <id> --to <folder>`: the folder the chat
|
|
100
|
+
delivers files from (in claude.ai, `/mnt/user-data/outputs`). A bare
|
|
101
|
+
`wordmark`, `mark` or `slide-art` takes the brand the rule gives; if it
|
|
102
|
+
names several, pick by the brand rule or ask which.
|
|
103
|
+
3. Deliver the files with the `use` line it prints (where each goes) and its
|
|
104
|
+
size. For a share image, its tags file goes with it and the install steps
|
|
105
|
+
of PROMPT.md §14 apply.
|
|
106
|
+
|
|
107
|
+
Never redraw, re-export, resize or recompress a library file to hand it over.
|
|
108
|
+
If what they ask for is not there, say so and offer to make it (the social
|
|
109
|
+
job below, or a page); what you make is a draft until someone approves it,
|
|
110
|
+
and the note says so.
|
|
111
|
+
|
|
85
112
|
### Rebuild from a source they attached (a .pptx, .docx, .pdf, .html)
|
|
86
113
|
|
|
87
114
|
1. Dump the source's strings verbatim, one per line, into `content.txt`:
|
|
@@ -94,7 +121,14 @@ beside the first. Nothing in the job changes.
|
|
|
94
121
|
in `edits` (no em dashes: swap them for commas or semicolons there) and
|
|
95
122
|
every line left out in `cut`.
|
|
96
123
|
4. `node wand.js build work/<name>/job.mjs` until every hard gate is ok. Look
|
|
97
|
-
at `out/sheet.png`. Open a page only where something looks off.
|
|
124
|
+
at `out/sheet.png`. Open a page only where something looks off. Then answer
|
|
125
|
+
the review questions the build prints under the gates, as a creative
|
|
126
|
+
director would; if the variety row names a run of pages, recompose it.
|
|
127
|
+
On a deck, no paragraph sets in more than two lines: the lines row names
|
|
128
|
+
any that do. Re-lay, never reword: two by two instead of four across, a
|
|
129
|
+
ruled row (title left, line right) instead of a narrow column. Set
|
|
130
|
+
`maxLines: 2` in the job to make it a hard gate. A source note under one
|
|
131
|
+
slide goes in that page's `footer`.
|
|
98
132
|
5. `node wand.js ship work/<name>/job.mjs --pptx` for a deck; without `--pptx`
|
|
99
133
|
for a document. Deliver the PDF (and the .pptx, and the .html) with the
|
|
100
134
|
review note.
|
|
@@ -105,6 +139,12 @@ Skip `content.txt` (delete the `content:` line in the job). Write the page list
|
|
|
105
139
|
with its claims first, then the pages. Coverage is skipped and says so; the
|
|
106
140
|
review reads the argument instead. Three sections a page, not four.
|
|
107
141
|
|
|
142
|
+
On the next brand, a title's phrase is its quiet second tone and gold is kept
|
|
143
|
+
for the cover, a statement, the close and the figures; photographs go through
|
|
144
|
+
`c.photo("walk")` (the brand's set, graded), large or not at all. On the
|
|
145
|
+
interim brand the phrase changes face instead: `<em>` sets in Newsreader, the
|
|
146
|
+
italic only on the pages that carry the art.
|
|
147
|
+
|
|
108
148
|
### Make it generic (an industry version of a client piece)
|
|
109
149
|
|
|
110
150
|
Author from the client piece: remove the client's figures, names, quotes and
|
|
@@ -120,8 +160,9 @@ talk adds:
|
|
|
120
160
|
1. Notes on every slide, and `seconds` on each when the talk has a slot.
|
|
121
161
|
2. Motion where it carries the argument (PROMPT.md §12): `step(n, html)` for
|
|
122
162
|
a reveal in order, `stat({ count: true })` for a figure to watch arrive,
|
|
123
|
-
`enter("draw")` on a trend line, `enter("grow", i)` on bars
|
|
124
|
-
|
|
163
|
+
`enter("draw")` on a trend line, `enter("grow", i)` on bars, `enter("lit")`
|
|
164
|
+
on a statement, `enter("window")` on a photograph. Titles rise word by word
|
|
165
|
+
on their own. Restraint: one moment a slide.
|
|
125
166
|
3. A live demo: one self-contained HTML file, then its poster on the deck's
|
|
126
167
|
brand: `node wand.js poster demo.html --play 3 --brand <brand>`, and
|
|
127
168
|
`c.demo({ src, poster })` on the slide. A clip: `c.video({ src, poster })`.
|
|
@@ -144,10 +185,45 @@ talk adds:
|
|
|
144
185
|
HTML with its player. Say in the note that timing is scratch timing at the
|
|
145
186
|
`wpm` given until a real read exists, and which frames are still to draw.
|
|
146
187
|
|
|
147
|
-
### Social
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
the
|
|
188
|
+
### Social images
|
|
189
|
+
|
|
190
|
+
**First, is it already approved?** `node wand.js library <words>`: if the
|
|
191
|
+
file exists, hand it over (the job above) instead of drawing it again.
|
|
192
|
+
|
|
193
|
+
**On the interim brand** the banners, link previews, square, avatar and site
|
|
194
|
+
icons are the approved design itself, drawn from the brand's composition
|
|
195
|
+
(PROMPT.md §14):
|
|
196
|
+
|
|
197
|
+
1. For a link preview that is live and wrong (someone sent a screenshot of a
|
|
198
|
+
bad unfurl), read it first: `node wand.js social --audit <url> [more]`.
|
|
199
|
+
Its rows and `audit/audit.png` show what the feeds do to it; say what is
|
|
200
|
+
wrong in the note. Without web access it says so: ask for the saved page
|
|
201
|
+
and its image and pass them (`--audit page.html --image og.png`).
|
|
202
|
+
2. Copy `examples/social/social.json` beside the work and set `line` (the
|
|
203
|
+
words), the `cards` wanted, and for each share image its page's `url`,
|
|
204
|
+
`title`, `description` and `alt`, plus `upload` (where the images will
|
|
205
|
+
live: a new folder each time) and `before` (the image live now, if any).
|
|
206
|
+
An article's share image takes its headline verbatim as `lead` and
|
|
207
|
+
`phrase`. `{ "kind": "icons", "upload": "/assets/<date>/" }` adds the
|
|
208
|
+
favicons, app icons and manifest.
|
|
209
|
+
3. `node wand.js social work/<name>/social.json`. Every image has a row; a
|
|
210
|
+
share image fails if its words leave the centre square or its type falls
|
|
211
|
+
under the floor. Look at `out/preview.png`: each image as the profile, the
|
|
212
|
+
LinkedIn compact card, Slack, X and WhatsApp show it, the live image above
|
|
213
|
+
the new one. Then answer the review questions printed under it.
|
|
214
|
+
4. Deliver the zip (`out/<name>-<date>.zip`: the images, `head-tags.html`,
|
|
215
|
+
`INSTALL.md`, the preview). `INSTALL.md` already says where each file goes
|
|
216
|
+
and how to check it; the note adds that nothing is verified until it is
|
|
217
|
+
live, and that what you drew is a draft until approved.
|
|
218
|
+
|
|
219
|
+
A profile photo that continues the LinkedIn banner is a `profile-photo` card
|
|
220
|
+
with `photo`, a cut-out of the person (transparent ground). If they gave a
|
|
221
|
+
plain photo, ask for the cut-out (Photos or Preview: lift the subject) rather
|
|
222
|
+
than cutting it yourself.
|
|
223
|
+
|
|
224
|
+
**On another brand**: `--surface square` or `og`; one `c.page()` per card;
|
|
225
|
+
`out/pages/pNN.png` are the deliverables. The crop row warns when a share
|
|
226
|
+
image's words leave the centre square: keep them there.
|
|
151
227
|
|
|
152
228
|
### Older Wand work
|
|
153
229
|
|
|
@@ -165,11 +241,15 @@ two kits, or `edit --set`; none of it applies to anything else.
|
|
|
165
241
|
Which brand it is on; what was changed from the source and why (every edit,
|
|
166
242
|
every cut); the gate table as printed; what a human still has to decide (a figure to confirm, a
|
|
167
243
|
quote to clear, a claim legal should see). A file delivered without the gate
|
|
168
|
-
table has been checked by nobody.
|
|
244
|
+
table has been checked by nobody. A library file is the exception: it was
|
|
245
|
+
checked when it was approved, so its note is the `use` and `approved` lines
|
|
246
|
+
`get` prints.
|
|
169
247
|
|
|
170
248
|
## Available scripts
|
|
171
249
|
|
|
172
|
-
- **`wand.js`** — doctor, new, build, check, ship, watch, poster, gallery, components, brands
|
|
250
|
+
- **`wand.js`** — doctor, new, build, check, ship, watch, poster, social, library, gallery, components, brands
|
|
251
|
+
- **`lib/library.js`**, **`library/`** — the approved files, their records and the check
|
|
252
|
+
- **`lib/social.js`** — the social set from a brand's approved composition; **`lib/audit.js`** — a live page's link preview, read
|
|
173
253
|
- **`lib/engine.js`** — the render and the gates
|
|
174
254
|
- **`lib/components.js`** — the vocabulary and its CSS
|
|
175
255
|
- **`lib/pptx.js`**, **`tools/embed_fonts.py`** — the PowerPoint export
|
package/START-HERE.md
CHANGED
|
@@ -6,9 +6,20 @@ node wand.js new work/acme --surface letter # the default brand; doct
|
|
|
6
6
|
# write work/acme/job.mjs (pages(c)) and, for a rebuild, work/acme/content.txt
|
|
7
7
|
node wand.js build work/acme/job.mjs # gates, PDF, a PNG per page, out/sheet.png
|
|
8
8
|
node wand.js ship work/acme/job.mjs --pptx # + one-file HTML, PowerPoint
|
|
9
|
-
node wand.js ship work/acme/job.mjs --brand next # the same job on
|
|
9
|
+
node wand.js ship work/acme/job.mjs --brand next # the same job on another brand (next, interim), in out-<brand>/
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
+
Asked for a file that already exists (the logo, a banner, a link preview, the
|
|
13
|
+
icons), hand over the approved one: `node wand.js library banner`, then
|
|
14
|
+
`node wand.js library get linkedin-banner --to <folder>`. PROMPT.md §15.
|
|
15
|
+
|
|
16
|
+
On the interim brand, `node wand.js social examples/social/social.json` draws
|
|
17
|
+
the approved social set (banners, link previews with their tags, square,
|
|
18
|
+
avatar, a profile photo that continues the banner, the site's icons) from the
|
|
19
|
+
brand's own composition, with `INSTALL.md` and a zip of the hand-over;
|
|
20
|
+
`node wand.js social --audit <url>` reads a live page's preview first.
|
|
21
|
+
PROMPT.md §14 has the rules.
|
|
22
|
+
|
|
12
23
|
A deck's HTML is a talk: entrances, steps, a presenter view (P). A demo needs
|
|
13
24
|
a poster: `node wand.js poster demo.html --play 3`. A storyboard starts from
|
|
14
25
|
`node wand.js new work/film --surface storyboard`; its HTML plays the board.
|
|
@@ -54,7 +54,11 @@
|
|
|
54
54
|
"rule": "E4E0F2",
|
|
55
55
|
"track": "E9E6F5",
|
|
56
56
|
"surface": "EBE8F8",
|
|
57
|
-
"emphLabel": "AA9BFF"
|
|
57
|
+
"emphLabel": "AA9BFF",
|
|
58
|
+
"second": "6C5CE7",
|
|
59
|
+
"secondSm": "6C5CE7",
|
|
60
|
+
"gradeLow": "240F48",
|
|
61
|
+
"gradeHigh": "F8F6FB"
|
|
58
62
|
},
|
|
59
63
|
"dark": {
|
|
60
64
|
"bg": "240F48",
|
|
@@ -74,7 +78,11 @@
|
|
|
74
78
|
"rule": "3A2E63",
|
|
75
79
|
"track": "1A1033",
|
|
76
80
|
"surface": "1A1033",
|
|
77
|
-
"emphLabel": "C4B5F4"
|
|
81
|
+
"emphLabel": "C4B5F4",
|
|
82
|
+
"second": "9481FF",
|
|
83
|
+
"secondSm": "9481FF",
|
|
84
|
+
"gradeLow": "240F48",
|
|
85
|
+
"gradeHigh": "F8F6FB"
|
|
78
86
|
}
|
|
79
87
|
},
|
|
80
88
|
"faces": {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" role="img" aria-label="Wand"><circle cx="400" cy="400" r="400" fill="#261d3d"/><g transform="translate(180.48 300.24) scale(0.187233) translate(0 -512)"><path d="M0 530A18 18 0 0 1 18 512L352.5 512A18 18 0 0 1 370.5 530L370.5 1347A278 278 0 0 0 926.5 1347L926.5 530A18 18 0 0 1 944.5 512L1279 512A18 18 0 0 1 1297 530L1297 1347A278 278 0 0 0 1853 1347L1853 734A18 18 0 0 1 1871 716L1873 716Q1882 716 1888.13 722.59L1940.35 778.75A134.03 134.03 0 0 0 2136.65 778.75L2188.87 722.59Q2195 716 2204 716L2205.5 716A18 18 0 0 1 2223.5 734L2223.5 1347A648.5 648.5 0 0 1 1125.96 1814.89Q1111.75 1800.82 1097.54 1814.89A648.5 648.5 0 0 1 0 1347Z" fill="#ffffff"/><path d="M2021.58 -300.31A16.61 16.61 0 0 1 2055.42 -300.31A426.81 426.81 0 0 0 2465.31 109.58A16.61 16.61 0 0 1 2465.31 143.42A426.81 426.81 0 0 0 2055.42 553.31A16.61 16.61 0 0 1 2021.58 553.31A426.81 426.81 0 0 0 1611.69 143.42A16.61 16.61 0 0 1 1611.69 109.58A426.81 426.81 0 0 0 2021.58 -300.31Z" fill="#c2a1ef"/></g></svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|