branding-engine 0.1.0 → 0.2.1

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.
Files changed (46) hide show
  1. package/README.md +428 -73
  2. package/bin/cli.mjs +8 -5
  3. package/examples/severino-labs/README.md +95 -0
  4. package/examples/severino-labs/brand.json +30 -0
  5. package/examples/severino-labs/generated/cards/social-card.png +0 -0
  6. package/examples/severino-labs/generated/severino-labs/README.md +49 -0
  7. package/examples/severino-labs/generated/severino-labs/icons/apple-touch-icon.png +0 -0
  8. package/examples/severino-labs/generated/severino-labs/icons/favicon-192.png +0 -0
  9. package/examples/severino-labs/generated/severino-labs/icons/favicon-32.png +0 -0
  10. package/examples/severino-labs/generated/severino-labs/icons/favicon.ico +0 -0
  11. package/examples/severino-labs/generated/severino-labs/icons/favicon.svg +1 -0
  12. package/examples/severino-labs/generated/severino-labs/mark/mark-1024.png +0 -0
  13. package/examples/severino-labs/generated/severino-labs/mark/mark-512.png +0 -0
  14. package/examples/severino-labs/generated/severino-labs/mark/mark-transparent-dark.png +0 -0
  15. package/examples/severino-labs/generated/severino-labs/mark/mark-transparent-light.png +0 -0
  16. package/examples/severino-labs/generated/severino-labs/mark/mark.svg +1 -0
  17. package/examples/severino-labs/generated/severino-labs/sheet/overview.png +0 -0
  18. package/examples/severino-labs/generated/severino-labs/sheet/palette.png +0 -0
  19. package/examples/severino-labs/generated/severino-labs/sheet/sheet-mark.png +0 -0
  20. package/examples/severino-labs/generated/severino-labs/sheet/type-specimen.png +0 -0
  21. package/examples/severino-labs/generated/severino-labs/web/head.html +6 -0
  22. package/examples/severino-labs/generated/severino-labs/web/site.webmanifest +19 -0
  23. package/examples/severino-labs/generated/severino-labs/web/tokens.css +7 -0
  24. package/examples/severino-labs/generated/severino-labs/wordmark/wordmark-caps-dark.png +0 -0
  25. package/examples/severino-labs/generated/severino-labs/wordmark/wordmark-caps-light.png +0 -0
  26. package/examples/severino-labs/generated/severino-labs/wordmark/wordmark-caps.svg +1 -0
  27. package/examples/severino-labs/generated/severino-labs/wordmark/wordmark-dark.png +0 -0
  28. package/examples/severino-labs/generated/severino-labs/wordmark/wordmark-light.png +0 -0
  29. package/examples/severino-labs/generated/severino-labs/wordmark/wordmark.svg +1 -0
  30. package/examples/severino-labs/studio.jpg +0 -0
  31. package/index.mjs +1 -0
  32. package/package.json +13 -6
  33. package/src/build.mjs +8 -6
  34. package/src/lib/extract-glyphs.mjs +65 -0
  35. package/src/lib/glyphs.mjs +6 -19
  36. package/src/lib/identity.mjs +11 -0
  37. package/src/lib/mark.mjs +28 -8
  38. package/src/lib/render.mjs +11 -2
  39. package/src/lib/wordmark.mjs +6 -1
  40. package/src/make-mark.mjs +2 -0
  41. package/src/make-sheet.mjs +2 -0
  42. package/src/make-web.mjs +2 -0
  43. package/src/make-wordmark.mjs +3 -1
  44. package/src/site.mjs +3 -1
  45. package/requirements.txt +0 -3
  46. package/src/lib/extract-glyphs.py +0 -75
package/README.md CHANGED
@@ -1,129 +1,484 @@
1
1
  # branding-engine
2
2
 
3
- Generate a complete, self-consistent brand kit from one accent color and a
4
- monogram: a favicon set, a vector mark, wordmark lockups, social cards, a brand
5
- sheet, and drop-in web tokens. The mark and wordmark are real font outlines
6
- (pure vector, no raster source); only the social cards and brand sheet render
7
- live text via a headless browser.
3
+ Generate a consistent brand kit from a compact alphanumeric mark and one accent
4
+ color. Outputs include favicons, vector and raster marks, wordmark lockups,
5
+ brand sheets, social cards, manifests, and CSS tokens.
8
6
 
9
- One monogram, one accent color, every brand surface.
7
+ The mark and wordmark use real font outlines. The common website path requires
8
+ only Node.js; browser rendering is optional.
10
9
 
11
- ## Install
10
+ ## Example
12
11
 
13
- ```sh
12
+ Illustrative input using a non-production sample palette:
13
+
14
+ ```json
15
+ {
16
+ "name": "Severino Labs",
17
+ "identity": {
18
+ "slug": "severino-labs",
19
+ "color": "#6D5EF7",
20
+ "deep": "#352A8A",
21
+ "onColor": "#FFFFFF",
22
+ "glyph": "SL",
23
+ "wordmark": "Severino Labs"
24
+ },
25
+ "portrait": "./studio.jpg",
26
+ "cardPalette": {
27
+ "accent": "#9B8CFF",
28
+ "textSoft": "#E3DEFF",
29
+ "textMuted": "#B7AFE8"
30
+ },
31
+ "cards": [
32
+ {
33
+ "file": "social-card.png",
34
+ "width": 1200,
35
+ "height": 630,
36
+ "photoWidth": 420,
37
+ "eyebrow": "Severino Labs",
38
+ "name": "Brand systems, generated.",
39
+ "tagline": "Marks, wordmarks, sheets, web assets, and social cards from one config.",
40
+ "meta": "Illustrative branding-engine example",
41
+ "url": "github.com/jseverino/branding-engine"
42
+ }
43
+ ]
44
+ }
45
+ ```
46
+
47
+ Generated mark:
48
+
49
+ ![Severino Labs generated mark](./examples/severino-labs/generated/severino-labs/mark/mark-512.png)
50
+
51
+ Generated wordmark:
52
+
53
+ ![Severino Labs generated wordmark](./examples/severino-labs/generated/severino-labs/wordmark/wordmark-light.png)
54
+
55
+ Generated brand sheet:
56
+
57
+ ![Severino Labs generated brand sheet](./examples/severino-labs/generated/severino-labs/sheet/overview.png)
58
+
59
+ Generated social card:
60
+
61
+ ![Severino Labs generated social card](./examples/severino-labs/generated/cards/social-card.png)
62
+
63
+ The complete input and committed generated output are in
64
+ [`examples/severino-labs`](./examples/severino-labs/).
65
+
66
+ ## Requirements
67
+
68
+ - Node.js 18 or newer
69
+ - `sharp`, OpenType.js, and the WOFF2 decoder, installed automatically
70
+ - Optional: `@playwright/test` plus Chromium for brand sheets and social cards
71
+
72
+ Install:
73
+
74
+ ```bash
14
75
  npm install branding-engine
15
76
  ```
16
77
 
17
- `sharp` (used everywhere) installs automatically. `@playwright/test` is an
18
- **optional** dependency: it's only needed for the brand sheet and social cards.
19
- The mark, wordmark, and icon generation path needs neither Playwright nor Python.
20
- To enable sheets and cards:
78
+ For a project-local CLI installation:
79
+
80
+ ```bash
81
+ npm install --save-dev branding-engine
82
+ npx branding-engine --help
83
+ ```
84
+
85
+ The package can also be installed globally with
86
+ `npm install --global branding-engine`, though project-local installation keeps
87
+ the version reproducible for collaborators and CI.
88
+
89
+ For sheets and social cards:
90
+
91
+ ```bash
92
+ npm install --save-dev @playwright/test
93
+ npx playwright install chromium
94
+ ```
95
+
96
+ ## Glyph Rules
97
+
98
+ `glyph` is the compact mark rendered inside the tile.
99
+
100
+ - Accepts 1-3 ASCII letters or digits
101
+ - Lowercase letters are normalized to uppercase
102
+ - Spaces, punctuation, symbols, and strings longer than three characters fail
103
+ - Layout dynamically adjusts by character count and caps narrow marks by height
104
+
105
+ Valid:
106
+
107
+ ```text
108
+ A
109
+ AC
110
+ A3X
111
+ 7
112
+ R2
113
+ ```
114
+
115
+ Invalid:
21
116
 
22
- ```sh
23
- npm i -D @playwright/test && npx playwright install chromium
117
+ ```text
118
+ ABCD
119
+ A C
120
+ A-C
121
+ @
24
122
  ```
25
123
 
26
- ## Plug into a site (Astro, Eleventy, plain HTML)
124
+ ## Quick Start: Add Branding to a Website
27
125
 
28
- The fastest path for a website: scaffold a config, set your color, generate a
29
- favicon set into `public/`. No headless browser, no python.
126
+ Use `init` and `generate` when a site needs favicons, a manifest, and CSS
127
+ tokens in its public directory.
30
128
 
31
- ```sh
32
- npm i -D branding-engine
33
- npx branding-engine init # writes brand.config.json + a `brand` npm script
34
- # edit accent, glyph, name in brand.config.json, then:
35
- npm run brand # generates into public/, prints the <head> snippet
129
+ ```bash
130
+ npm install --save-dev branding-engine
131
+ npx branding-engine init
36
132
  ```
37
133
 
38
- `brand.config.json` is flat:
134
+ Edit the generated `brand.config.json`:
39
135
 
40
136
  ```json
41
- { "name": "My Site", "accent": "#2563EB", "glyph": "MS", "wordmark": "My Site" }
137
+ {
138
+ "name": "My Site",
139
+ "accent": "#2563EB",
140
+ "deep": "#173B8F",
141
+ "onColor": "#FFFFFF",
142
+ "glyph": "MS"
143
+ }
42
144
  ```
43
145
 
44
- `generate` writes these to `public/` at the root paths a static site expects, and
45
- prints the `<head>` block to paste in (its `theme-color` reflects your accent):
146
+ Then generate the files:
147
+
148
+ ```bash
149
+ npm run brand
150
+ ```
151
+
152
+ Default output:
46
153
 
47
154
  ```text
48
- public/favicon.ico favicon.svg favicon-32.png favicon-192.png
49
- public/apple-touch-icon.png site.webmanifest brand-tokens.css
155
+ public/
156
+ ├── apple-touch-icon.png
157
+ ├── brand-tokens.css
158
+ ├── favicon-32.png
159
+ ├── favicon-192.png
160
+ ├── favicon.ico
161
+ ├── favicon.svg
162
+ └── site.webmanifest
50
163
  ```
51
164
 
52
- Commit those files; they are deterministic, so re-running `npm run brand` after a
53
- color change reproduces them exactly. Optional flags: `--public <dir>`,
54
- `--config <file>`.
165
+ The command also prints the `<head>` links to add to the site.
55
166
 
56
- ## CLI
167
+ ### Website Config Reference
57
168
 
58
- ```sh
59
- # A one-off kit (mark, wordmark, sheet, web) from an accent + initials
60
- branding-engine kit acme ff5733 AC "Acme Corp"
169
+ | Field | Required | Description |
170
+ |---|---:|---|
171
+ | `name` | yes | Application name used in `site.webmanifest` |
172
+ | `accent` | yes | Six-digit hex accent, with or without `#` |
173
+ | `glyph` | yes | One to three alphanumeric mark characters |
174
+ | `deep` | no | Dark palette shade; derived from `accent` when omitted |
175
+ | `onColor` | no | Glyph color on the accent; defaults to `#FFFFFF` |
61
176
 
62
- # Just the lean, browser-free pieces (what a website needs)
63
- branding-engine kit acme ff5733 AC "Acme Corp" --only mark,wordmark,web
177
+ Options:
64
178
 
65
- # A whole brand (primary identity + surfaces + cards) from a config
66
- branding-engine build --config ./brand --out ./kits
179
+ ```bash
180
+ branding-engine generate --config path/to/brand.config.json --public path/to/public
67
181
  ```
68
182
 
69
- Flags: `--config <dir|brand.json>`, `--out <dir>`, `--font <file>`,
70
- `--only mark,wordmark,sheet,web,cards` (`mark` includes the favicon set).
183
+ Generated files are deterministic and intended to be committed with the site.
184
+
185
+ ### Astro
186
+
187
+ Astro serves files from `public/` at the site root, so the default generator
188
+ paths work without customization:
71
189
 
72
- ## Brand config
190
+ ```bash
191
+ npm install --save-dev branding-engine
192
+ npx branding-engine init
193
+ npm run brand
194
+ ```
195
+
196
+ In your shared layout, add the generated links and tokens:
197
+
198
+ ```astro
199
+ <html lang="en">
200
+ <head>
201
+ <link rel="icon" href="/favicon.ico" sizes="any" />
202
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
203
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
204
+ <link rel="manifest" href="/site.webmanifest" />
205
+ <link rel="stylesheet" href="/brand-tokens.css" />
206
+ <meta name="theme-color" content="#2563EB" />
207
+ </head>
208
+ <body><slot /></body>
209
+ </html>
210
+ ```
73
211
 
74
- `build` reads a `brand.json` (and an optional sibling `surfaces.json`). Paths
75
- inside it (`font`, `portrait`) are resolved relative to the config's directory;
76
- omit `font` to use the bundled Inter.
212
+ To regenerate before every production build, add it to the existing build
213
+ script:
77
214
 
78
- ```jsonc
215
+ ```json
216
+ {
217
+ "scripts": {
218
+ "brand": "branding-engine generate",
219
+ "build": "npm run brand && astro build"
220
+ }
221
+ }
222
+ ```
223
+
224
+ ### Plain HTML or Static Site
225
+
226
+ If the repository already publishes a `public/` directory, use the same
227
+ default commands as Astro. If the repository root itself is deployed:
228
+
229
+ ```bash
230
+ npx branding-engine generate --public .
231
+ ```
232
+
233
+ Add the links printed by the command to the page `<head>`, plus the token
234
+ stylesheet:
235
+
236
+ ```html
237
+ <link rel="stylesheet" href="/brand-tokens.css" />
238
+ ```
239
+
240
+ The generated CSS variables can then be used from any stylesheet:
241
+
242
+ ```css
243
+ .button {
244
+ color: var(--brand-on-accent);
245
+ background: var(--brand-accent);
246
+ }
247
+ ```
248
+
249
+ ## Full Brand Kit
250
+
251
+ Use `build` for a reusable config-driven kit:
252
+
253
+ ```bash
254
+ branding-engine build --config ./brand --out ./kits
255
+ ```
256
+
257
+ `--config` accepts either a `brand.json` path or a directory containing
258
+ `brand.json`. An optional `surfaces.json` can live beside it.
259
+
260
+ Minimal `brand.json`:
261
+
262
+ ```json
79
263
  {
80
264
  "name": "Acme",
81
- "wordmarkWeight": 700, // wordmark text weight (mark uses `weight`, default 800)
82
265
  "identity": {
83
266
  "slug": "acme",
84
- "color": "#1E3A8A", // accent
85
- "deep": "#14245C", // optional; falls back to a darkened accent
86
- "onColor": "#ffffff", // optional; color on the accent
267
+ "color": "#1E3A8A",
87
268
  "glyph": "AC",
88
269
  "wordmark": "Acme Corp"
270
+ }
271
+ }
272
+ ```
273
+
274
+ Expanded `brand.json`:
275
+
276
+ ```json
277
+ {
278
+ "name": "Acme",
279
+ "font": "./AcmeSans.ttf",
280
+ "weight": 800,
281
+ "wordmarkWeight": 700,
282
+ "identity": {
283
+ "slug": "acme",
284
+ "color": "#1E3A8A",
285
+ "deep": "#14245C",
286
+ "onColor": "#FFFFFF",
287
+ "glyph": "A3C",
288
+ "wordmark": "Acme Corp"
289
+ },
290
+ "portrait": "./portrait.jpg",
291
+ "cardPalette": {
292
+ "accent": "#5B82D6",
293
+ "textSoft": "#DDE6FB",
294
+ "textMuted": "#A9C0E8"
89
295
  },
90
- "cardPalette": { "accent": "#5B82D6", "textSoft": "#DDE6FB", "textMuted": "#A9C0E8" },
91
- "cards": [ /* { file, width, height, photoWidth, eyebrow, name, tagline, meta, url } */ ]
296
+ "cards": [
297
+ {
298
+ "file": "social-card.png",
299
+ "width": 1200,
300
+ "height": 630,
301
+ "photoWidth": 420,
302
+ "eyebrow": "Acme Corp",
303
+ "name": "Acme",
304
+ "tagline": "Built for what comes next.",
305
+ "meta": "Brand systems and engineering",
306
+ "url": "acme.example"
307
+ }
308
+ ]
92
309
  }
93
310
  ```
94
311
 
95
- `surfaces.json` lists other surfaces that inherit the font and glyph and override
96
- only color (and optionally wordmark):
312
+ ### Full Config Reference
313
+
314
+ | Field | Required | Description |
315
+ |---|---:|---|
316
+ | `name` | no | Human-readable brand name used in logs and fallbacks |
317
+ | `identity` | yes | Primary brand identity object |
318
+ | `identity.slug` | yes | Output directory name |
319
+ | `identity.color` | yes | Six-digit accent color |
320
+ | `identity.glyph` | yes | One to three alphanumeric mark characters |
321
+ | `identity.wordmark` | no | Text used for wordmark lockups and sheet title |
322
+ | `identity.deep` | no | Curated dark shade |
323
+ | `identity.onColor` | no | Glyph color on accent |
324
+ | `font` | no | Font path relative to `brand.json`; defaults to bundled Inter |
325
+ | `weight` | no | Mark font weight; defaults to `800` |
326
+ | `wordmarkWeight` | no | Wordmark font weight; defaults to `700` |
327
+ | `surfaces` | no | Inline additional surfaces; `surfaces.json` takes precedence |
328
+ | `portrait` | for cards | JPEG path relative to `brand.json` |
329
+ | `cardPalette` | for cards | Card accent and supporting text colors |
330
+ | `cards` | no | Social-card definitions rendered to `<out>/cards/` |
331
+
332
+ Additional surfaces inherit the primary glyph unless they override it:
97
333
 
98
334
  ```json
99
- { "support": { "color": "#1f4d57", "wordmark": "Acme Support" } }
335
+ {
336
+ "support": {
337
+ "color": "#1F4D57",
338
+ "wordmark": "Acme Support"
339
+ },
340
+ "labs": {
341
+ "color": "#7C3AED",
342
+ "glyph": "A3",
343
+ "wordmark": "Acme Labs"
344
+ }
345
+ }
100
346
  ```
101
347
 
348
+ ## One-Off Kit
349
+
350
+ Create a kit without a config file:
351
+
352
+ ```bash
353
+ branding-engine kit acme ff5733 AC "Acme Corp"
354
+ ```
355
+
356
+ Three-character example:
357
+
358
+ ```bash
359
+ branding-engine kit prism 635bff P3X "Prism Works" \
360
+ --only mark,wordmark,web \
361
+ --out ./kits
362
+ ```
363
+
364
+ Syntax:
365
+
366
+ ```text
367
+ branding-engine kit <slug> <hex> <glyph> ["Wordmark"] [options]
368
+ ```
369
+
370
+ ## Stages
371
+
372
+ Select stages with a comma-separated `--only` value:
373
+
374
+ ```bash
375
+ branding-engine build \
376
+ --config ./brand.json \
377
+ --out ./kits \
378
+ --only mark,wordmark,web
379
+ ```
380
+
381
+ | Stage | Browser needed | Output |
382
+ |---|---:|---|
383
+ | `mark` | no | Favicons, vector mark, PNG marks, transparent variants |
384
+ | `wordmark` | no | Vector and PNG title-case/all-caps lockups |
385
+ | `web` | no | CSS tokens, web manifest, and `<head>` snippet |
386
+ | `sheet` | yes | Brand overview poster, sections, and generated kit README |
387
+ | `cards` | yes | Configured social-card PNGs |
388
+
389
+ Without `--only`, all stages run.
390
+
391
+ ## Output Layout
392
+
393
+ Each kit is written under `<out>/<slug>/`:
394
+
395
+ ```text
396
+ <out>/<slug>/
397
+ ├── icons/
398
+ ├── mark/
399
+ ├── sheet/
400
+ ├── web/
401
+ └── wordmark/
402
+ ```
403
+
404
+ Social cards are written to `<out>/cards/`.
405
+
102
406
  ## Programmatic API
103
407
 
104
408
  ```js
105
- import { buildBrand, buildKit, markSvg, wordmarkSvg } from 'branding-engine';
106
-
107
- await buildKit({ slug: 'acme', hex: '#ff5733', glyph: 'AC', wordmark: 'Acme', only: 'mark,wordmark', outDir: 'public/brand' });
108
- const svg = markSvg({ size: 64, bg: '#ff5733', glyph: 'AC' }); // pure string, no I/O
409
+ import {
410
+ buildBrand,
411
+ buildKit,
412
+ generateSite,
413
+ markSvg,
414
+ normalizeGlyph,
415
+ wordmarkSvg,
416
+ } from 'branding-engine';
417
+
418
+ await buildKit({
419
+ slug: 'acme',
420
+ hex: '#FF5733',
421
+ glyph: 'a3x',
422
+ wordmark: 'Acme',
423
+ only: 'mark,wordmark,web',
424
+ outDir: 'public/brand',
425
+ });
426
+
427
+ const glyph = normalizeGlyph('a3x'); // "A3X"
428
+ const mark = markSvg({ size: 64, bg: '#FF5733', glyph });
429
+ const lockup = wordmarkSvg({
430
+ tileHex: '#FF5733',
431
+ text: 'Acme',
432
+ glyph,
433
+ });
109
434
  ```
110
435
 
111
- ## Output
436
+ Main exports:
437
+
438
+ - `buildBrand(options)`
439
+ - `buildKit(options)`
440
+ - `initSite(options)`
441
+ - `generateSite(options)`
442
+ - `makeMark(options)`
443
+ - `makeWordmark(options)`
444
+ - `makeSheet(options)`
445
+ - `makeWeb(options)`
446
+ - `makeCards(options)`
447
+ - `markSvg(options)`
448
+ - `wordmarkSvg(options)`
449
+ - `normalizeGlyph(glyph)`
450
+ - `renderCard(browser, options)`
451
+ - `launchBrowser()`
112
452
 
113
- Each kit is `<out>/<slug>/`:
453
+ ## Fonts and Glyph Extraction
114
454
 
115
- - `icons/`: `favicon.svg/.ico`, `favicon-32/192.png`, `apple-touch-icon.png`
116
- - `mark/`: `mark.svg`, `mark-512/1024.png`, transparent light/dark
117
- - `wordmark/`: `wordmark.svg` + light/dark PNGs, plus all-caps `wordmark-caps.*`
118
- - `sheet/`: `overview.png` poster + section images, and a `README.md`
119
- - `web/`: `tokens.css`, `site.webmanifest`, `head.html`
455
+ Bundled Inter caches include uppercase letters and digits for marks, plus
456
+ uppercase, lowercase, digits, and spaces for wordmarks.
120
457
 
121
- Social cards land in `<out>/cards/`.
458
+ Custom fonts and missing characters are extracted entirely in Node with
459
+ OpenType.js and a WebAssembly WOFF2 decoder. No Python, fonttools, native
460
+ binding, or system font utility is required. Supported input formats are TTF,
461
+ OTF, WOFF, and WOFF2.
462
+
463
+ Extracted caches are written under `.brand-cache/`, or the directory specified
464
+ by `BRAND_CACHE_DIR`. The installed package is never modified. If a variable
465
+ font cannot be instantiated at the requested `weight`, the build exits with the
466
+ font filename and parser error; use a static font file or another supported
467
+ variable font.
468
+
469
+ ## Errors
470
+
471
+ The CLI exits nonzero with an actionable message for invalid glyphs, invalid
472
+ colors, missing configs, unavailable font glyphs, or missing optional browser
473
+ dependencies.
474
+
475
+ Example:
476
+
477
+ ```text
478
+ Invalid glyph: "ABCD". Expected 1-3 letters or digits, e.g. A, AC, or A3X.
479
+ ```
122
480
 
123
- ## Fonts and python
481
+ ## License
124
482
 
125
- The bundled Inter ships with prebuilt glyph outlines, so the default font needs
126
- **no python**. A custom font (or a glyph outside the bundled set) is extracted on
127
- demand and requires `python3` + `fonttools` (`pip install -r requirements.txt`);
128
- the extracted cache is written under `.brand-cache/` (or `$BRAND_CACHE_DIR`),
129
- never into the installed package.
483
+ MIT. The bundled Inter font includes its own notice under
484
+ `assets/fonts/inter/NOTICE.md`.
package/bin/cli.mjs CHANGED
@@ -3,7 +3,7 @@
3
3
  // branding-engine init scaffold a site brand.config + npm script
4
4
  // branding-engine generate [--public <dir>] [--config <file>] favicons + manifest + tokens -> public/
5
5
  // branding-engine build [--config <dir|brand.json>] [--out <dir>] [--only a,b]
6
- // branding-engine kit <slug> <hex> <initials> ["Wordmark"] [--font f] [--out d] [--only a,b]
6
+ // branding-engine kit <slug> <hex> <glyph> ["Wordmark"] [--font f] [--out d] [--only a,b]
7
7
  // Stages for --only: mark, wordmark, sheet, web, cards (mark includes favicons).
8
8
  import { buildBrand, buildKit } from '../src/build.mjs';
9
9
  import { generateSite, initSite } from '../src/site.mjs';
@@ -29,17 +29,20 @@ const USAGE =
29
29
  ' branding-engine init scaffold brand.config.json + a `brand` npm script\n' +
30
30
  ' branding-engine generate [--public <dir>] [--config <file>] favicons + manifest + tokens -> public/\n' +
31
31
  ' branding-engine build [--config <dir|brand.json>] [--out <dir>] [--only mark,wordmark,sheet,web,cards]\n' +
32
- ' branding-engine kit <slug> <hex> <initials> ["Wordmark"] [--font <file>] [--out <dir>] [--only ...]';
32
+ ' branding-engine kit <slug> <hex> <glyph> ["Wordmark"] [--font <file>] [--out <dir>] [--only ...]\n' +
33
+ ' <glyph> is 1-3 letters or digits, e.g. A, AC, or A3X.';
33
34
 
34
35
  const [cmd, ...rest] = process.argv.slice(2);
35
36
  const { pos, opt } = parse(rest);
36
37
 
37
38
  try {
38
- if (cmd === 'init') {
39
+ if (!cmd || cmd === '--help' || cmd === '-h') {
40
+ console.log(USAGE);
41
+ } else if (cmd === 'init') {
39
42
  const { created, headSnippet } = initSite({});
40
43
  if (created.length) console.log('Created:\n' + created.map((c) => ' ' + c).join('\n'));
41
44
  console.log('\nNext: edit brand.config.json (accent, glyph, name), then run `npm run brand`.');
42
- console.log('\nAdd this to your site <head> (or import public/brand-tokens.css for the CSS vars):\n');
45
+ console.log('\nAdd this to your site <head>:\n');
43
46
  console.log(headSnippet + '\n');
44
47
  } else if (cmd === 'generate') {
45
48
  const { written, publicDir, headSnippet } = await generateSite({ config: opt.config, publicDir: opt.public });
@@ -58,7 +61,7 @@ try {
58
61
  await buildKit({ slug, hex, glyph, wordmark, font: opt.font, outDir: opt.out, only: opt.only });
59
62
  } else {
60
63
  console.error(USAGE);
61
- process.exit(cmd ? 1 : 0);
64
+ process.exit(1);
62
65
  }
63
66
  } catch (err) {
64
67
  console.error(`\n${err.message}`);
@@ -0,0 +1,95 @@
1
+ # Severino Labs example
2
+
3
+ This illustrative example uses the Severino Labs name with a non-production
4
+ sample palette. It runs the full-kit `build` command from
5
+ [`brand.json`](./brand.json):
6
+
7
+ ```json
8
+ {
9
+ "name": "Severino Labs",
10
+ "identity": {
11
+ "slug": "severino-labs",
12
+ "color": "#6D5EF7",
13
+ "deep": "#352A8A",
14
+ "onColor": "#FFFFFF",
15
+ "glyph": "SL",
16
+ "wordmark": "Severino Labs"
17
+ },
18
+ "portrait": "./studio.jpg",
19
+ "cardPalette": {
20
+ "accent": "#9B8CFF",
21
+ "textSoft": "#E3DEFF",
22
+ "textMuted": "#B7AFE8"
23
+ },
24
+ "cards": [
25
+ {
26
+ "file": "social-card.png",
27
+ "width": 1200,
28
+ "height": 630,
29
+ "photoWidth": 420,
30
+ "eyebrow": "Severino Labs",
31
+ "name": "Brand systems, generated.",
32
+ "tagline": "Marks, wordmarks, sheets, web assets, and social cards from one config.",
33
+ "meta": "Illustrative branding-engine example",
34
+ "url": "github.com/jseverino/branding-engine"
35
+ }
36
+ ]
37
+ }
38
+ ```
39
+
40
+ Regenerate the committed output from the repository root:
41
+
42
+ ```bash
43
+ node bin/cli.mjs build \
44
+ --config examples/severino-labs/brand.json \
45
+ --out examples/severino-labs/generated
46
+ ```
47
+
48
+ ## Preview
49
+
50
+ ![Severino Labs generated icon](./generated/severino-labs/mark/mark-512.png)
51
+
52
+ ![Severino Labs generated wordmark](./generated/severino-labs/wordmark/wordmark-light.png)
53
+
54
+ ![Severino Labs generated brand sheet](./generated/severino-labs/sheet/overview.png)
55
+
56
+ ![Severino Labs generated social card](./generated/cards/social-card.png)
57
+
58
+ ## Generated files
59
+
60
+ ```text
61
+ generated/severino-labs/
62
+ ├── icons/
63
+ │ ├── apple-touch-icon.png
64
+ │ ├── favicon-32.png
65
+ │ ├── favicon-192.png
66
+ │ ├── favicon.ico
67
+ │ └── favicon.svg
68
+ ├── mark/
69
+ │ ├── mark-512.png
70
+ │ ├── mark-1024.png
71
+ │ ├── mark-transparent-dark.png
72
+ │ ├── mark-transparent-light.png
73
+ │ └── mark.svg
74
+ ├── sheet/
75
+ │ ├── overview.png
76
+ │ ├── palette.png
77
+ │ ├── sheet-mark.png
78
+ │ └── type-specimen.png
79
+ ├── web/
80
+ │ ├── head.html
81
+ │ ├── site.webmanifest
82
+ │ └── tokens.css
83
+ └── wordmark/
84
+ ├── wordmark-caps-dark.png
85
+ ├── wordmark-caps-light.png
86
+ ├── wordmark-caps.svg
87
+ ├── wordmark-dark.png
88
+ ├── wordmark-light.png
89
+ └── wordmark.svg
90
+
91
+ generated/cards/
92
+ └── social-card.png
93
+ ```
94
+
95
+ These files are generated by `branding-engine`; do not edit them by hand.