@open-assets/open-assets 0.1.10 → 0.1.12

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 CHANGED
@@ -1,15 +1,34 @@
1
- # open-assets
1
+ <p align="center">
2
+ <img src="public/img/banner/1280/banner.png" alt="Open Assets" width="100%" />
3
+ </p>
4
+
5
+ # Open Assets
6
+
7
+ The LLM first way to do graphics all from your git repo.
2
8
 
3
9
  Dev server and export tool for app marketing assets. Like Storybook, but for marketing assets.
4
10
 
5
11
  Design your App Store screenshots, app icons, logos, OG images, favicons, and more in HTML/CSS/SVG, preview them live in the browser, and export pixel-perfect PNGs at any size — including directly into your Xcode project.
6
12
 
7
- ## Quick Start
13
+ ## Installation
8
14
 
9
15
  ```bash
10
- # Install
11
- npm install --save-dev open-assets
16
+ # npm
17
+ npm install --save-dev @open-assets/open-assets
18
+
19
+ # yarn
20
+ yarn add --dev @open-assets/open-assets
21
+
22
+ # pnpm
23
+ pnpm add --save-dev @open-assets/open-assets
24
+
25
+ # bun
26
+ bun add --dev @open-assets/open-assets
27
+ ```
28
+
29
+ ## Quick Start
12
30
 
31
+ ```bash
13
32
  # Scaffold a new project
14
33
  npx open-assets init
15
34
 
@@ -17,6 +36,22 @@ npx open-assets init
17
36
  npx open-assets dev
18
37
  ```
19
38
 
39
+ ## Shell Alias
40
+
41
+ Add an alias to your shell profile for a shorter command:
42
+
43
+ ```bash
44
+ echo 'alias oa="npx open-assets"' >> ~/.zshrc && source ~/.zshrc
45
+ ```
46
+
47
+ Then use `oa` anywhere:
48
+
49
+ ```bash
50
+ oa dev
51
+ oa render --all
52
+ oa init
53
+ ```
54
+
20
55
  ## Concepts
21
56
 
22
57
  open-assets uses a simple, unified data model. Every asset type follows the same structure: **N templates × M export sizes**.
@@ -26,7 +61,6 @@ open-assets uses a simple, unified data model. Every asset type follows the same
26
61
  | **Collection** | A named group of related assets sharing the same source size and export sizes. One tab in the dev UI. |
27
62
  | **Template** | A single source file (HTML or SVG) that produces one image per export size. |
28
63
  | **Export Size** | A named output dimension that templates are rendered at (e.g., "iPhone 6.9" → 1320×2868). |
29
- | **Platform** | Optional grouping label for related export sizes (e.g., "App Store", "Play Store"). |
30
64
  | **Source Size** | The dimensions the HTML template is authored at. Puppeteer scales from source → export size. |
31
65
  | **Output** | An optional post-render action (e.g., write to Xcode `.appiconset`, copy SVG source). |
32
66
 
@@ -38,21 +72,30 @@ open-assets uses a simple, unified data model. Every asset type follows the same
38
72
  npx open-assets init
39
73
  ```
40
74
 
41
- Creates a `manifest.json`, sample HTML templates, and a `public/` directory for shared assets.
75
+ Creates a `assets.json`, sample HTML templates, and a `public/` directory for shared assets.
42
76
 
43
77
  ### 2. Design with Claude Code
44
78
 
45
- Install the open-assets Claude skill, then prompt:
79
+ Install the open-assets Claude Code skill into your project:
80
+
81
+ ```bash
82
+ # Using the built-in command
83
+ npx open-assets skills
84
+
85
+ # Or using the Skills CLI
86
+ npx skills add https://github.com/Parra-Inc/open-assets --skill open-assets
87
+ ```
88
+
89
+ This copies the skill into `.claude/skills/open-assets/` so Claude Code can use it. Then prompt:
46
90
 
47
91
  ```
48
- Now we want to make beautiful screenshots for this app. Install the open-assets
49
- skill from https://github.com/parra-inc/open-assets. Look at the marketing
92
+ Now we want to make beautiful screenshots for this app. Look at the marketing
50
93
  doc and demographics. Design 8 high-converting App Store screenshots that catch
51
94
  your eye as you scroll. Use bold headlines with highlighted keywords, phone
52
95
  mockups with real app screenshots, and close with reviews + a CTA.
53
96
  ```
54
97
 
55
- Claude reads your `manifest.json` and `publicDir` to understand the project structure, then creates screenshot HTML files using the design patterns in the skill.
98
+ Claude reads your `assets.json` and `publicDir` to understand the project structure, then creates screenshot HTML files using the design patterns in the skill.
56
99
 
57
100
  ### 3. Preview
58
101
 
@@ -95,7 +138,7 @@ Reference captured screenshots in your HTML templates:
95
138
  <img src="../../public/screenshots/01-home.png" style="width: 100%; height: 100%; object-fit: cover;" />
96
139
  ```
97
140
 
98
- The `manifest.json` `command` field stores the export command so automation tools know what to run:
141
+ The `assets.json` `command` field stores the export command so automation tools know what to run:
99
142
  ```json
100
143
  {
101
144
  "command": "npx open-assets render --all"
@@ -117,7 +160,7 @@ open-assets dev --no-open # Don't auto-open browser
117
160
  open-assets dev --quiet # Suppress server logs
118
161
  open-assets dev --ci # CI mode (quiet + no browser)
119
162
  open-assets dev --static-dir ./shared # Serve additional static directories
120
- open-assets dev --manifest config.json # Use a custom manifest filename
163
+ open-assets dev --config config.json # Use a custom config filename
121
164
  ```
122
165
 
123
166
  Options:
@@ -128,7 +171,7 @@ Options:
128
171
  | `--no-open` | `OPEN_ASSETS_NO_OPEN` | — | Don't auto-open the browser |
129
172
  | `-q, --quiet` | `OPEN_ASSETS_QUIET` | `false` | Suppress server logs |
130
173
  | `--ci` | `CI` | `false` | CI mode: quiet + no browser |
131
- | `--manifest <path>` | `OPEN_ASSETS_MANIFEST` | `manifest.json` | Path to manifest file |
174
+ | `--config <path>` | `OPEN_ASSETS_CONFIG` | `assets.json` | Path to config file |
132
175
  | `--static-dir <dirs...>` | — | — | Additional static directories to serve |
133
176
  | `--render-timeout <ms>` | `OPEN_ASSETS_RENDER_TIMEOUT` | `30000` | Puppeteer render timeout |
134
177
 
@@ -142,7 +185,6 @@ open-assets render --all # Export at EVERY configured siz
142
185
  open-assets render --collection screenshots # Render a specific collection
143
186
  open-assets render --template 01-hero # Render a single template
144
187
  open-assets render --size iphone-6.9 # Use a named export size
145
- open-assets render --platform "App Store" # Render all sizes for a platform
146
188
  open-assets render --width 1320 --height 2868 # Custom size
147
189
  open-assets render --force # Re-render everything, ignore cache
148
190
  open-assets render -o ./build # Custom output directory
@@ -155,14 +197,13 @@ Options:
155
197
  |------|---------|---------|-------------|
156
198
  | `--collection <id>` | — | all | Render only the collection with this ID |
157
199
  | `--template <name>` | — | all | Render only the template with this name |
158
- | `--size <name>` | — | — | Use a named export size from manifest |
159
- | `--platform <name>` | — | — | Render only sizes for this platform |
200
+ | `--size <name>` | — | — | Use a named export size from config |
160
201
  | `--width <px>` | — | — | Custom output width |
161
202
  | `--height <px>` | — | — | Custom output height |
162
- | `--all` | — | — | Export at every size defined in the manifest |
203
+ | `--all` | — | — | Export at every size defined in the config |
163
204
  | `--force` | — | — | Re-render all assets even if unchanged |
164
205
  | `-o, --output <dir>` | `OPEN_ASSETS_OUTPUT` | `./exports` | Output directory |
165
- | `--manifest <path>` | `OPEN_ASSETS_MANIFEST` | `manifest.json` | Path to manifest file |
206
+ | `--config <path>` | `OPEN_ASSETS_CONFIG` | `assets.json` | Path to config file |
166
207
  | `--parallel <count>` | `OPEN_ASSETS_PARALLEL` | `1` | Number of parallel renders |
167
208
  | `--render-timeout <ms>` | `OPEN_ASSETS_RENDER_TIMEOUT` | `30000` | Puppeteer render timeout |
168
209
  | `--json` | — | — | Output results as JSON |
@@ -178,9 +219,6 @@ open-assets render --collection screenshots --template 01-hero --all
178
219
 
179
220
  # All templates at one device size
180
221
  open-assets render --collection screenshots --size iphone-6.9
181
-
182
- # All templates for a specific platform
183
- open-assets render --collection screenshots --platform "App Store"
184
222
  ```
185
223
 
186
224
  **Output structure**: `exports/{collection}/{size}/{template}.png`
@@ -209,7 +247,7 @@ exports/
209
247
 
210
248
  ### `open-assets list [dir]`
211
249
 
212
- List all collections and templates defined in the manifest.
250
+ List all collections and templates defined in the config.
213
251
 
214
252
  ```bash
215
253
  open-assets list # Pretty-print asset tree
@@ -218,7 +256,7 @@ open-assets list --json # Output as JSON
218
256
 
219
257
  ### `open-assets validate [dir]`
220
258
 
221
- Validate the manifest and check that all referenced source files exist.
259
+ Validate the config and check that all referenced source files exist.
222
260
 
223
261
  ```bash
224
262
  open-assets validate # Check current directory
@@ -227,9 +265,21 @@ open-assets validate ./assets # Check specific directory
227
265
 
228
266
  Returns exit code 1 if any errors are found — useful in CI pipelines.
229
267
 
268
+ ### `open-assets skills [dir]`
269
+
270
+ Install Claude Code skills into your project. Copies skill files to `.claude/skills/` so Claude Code can generate and manage marketing assets.
271
+
272
+ ```bash
273
+ open-assets skills # Install to current project
274
+ open-assets skills ./my-app # Install to a specific project
275
+
276
+ # Or using the Skills CLI
277
+ npx skills add https://github.com/Parra-Inc/open-assets --skill open-assets
278
+ ```
279
+
230
280
  ### `open-assets init [dir]`
231
281
 
232
- Scaffold a new project with a `manifest.json`, sample HTML templates, and a `public/` directory.
282
+ Scaffold a new project with a `assets.json`, sample HTML templates, and a `public/` directory.
233
283
 
234
284
  ```bash
235
285
  open-assets init # Current directory
@@ -238,7 +288,7 @@ open-assets init ./my-assets # Specific directory
238
288
 
239
289
  ## Manifest Format
240
290
 
241
- Your project needs a `manifest.json` at its root. This file defines the collections shown in the viewer and all export options.
291
+ Your project needs a `assets.json` at its root. This file defines the collections shown in the viewer and all export options.
242
292
 
243
293
  ```json
244
294
  {
@@ -274,14 +324,9 @@ All collections follow the same structure. No `type` field needed.
274
324
  { "src": "src/screenshots/01-hero.html", "name": "01-hero", "label": "Hero" },
275
325
  { "src": "src/screenshots/02-features.html", "name": "02-features", "label": "Features" }
276
326
  ],
277
- "exportSizes": [
278
- {
279
- "platform": "App Store",
280
- "sizes": [
281
- { "name": "iphone-6.9", "label": "iPhone 6.9\"", "width": 1320, "height": 2868 },
282
- { "name": "iphone-6.7", "label": "iPhone 6.7\"", "width": 1290, "height": 2796 }
283
- ]
284
- }
327
+ "export": [
328
+ { "name": "iphone-6.9", "label": "iPhone 6.9\"", "size": { "width": 1320, "height": 2868 } },
329
+ { "name": "iphone-6.7", "label": "iPhone 6.7\"", "size": { "width": 1290, "height": 2796 } }
285
330
  ],
286
331
  "outputs": [
287
332
  { "type": "xcode", "path": "../MyApp/Assets.xcassets/AppIcon.appiconset" }
@@ -299,9 +344,11 @@ All collections follow the same structure. No `type` field needed.
299
344
  | `templates[].src` | string | Path to HTML/SVG file (relative to project root) |
300
345
  | `templates[].name` | string | Filename for exports (used by `--template` flag) |
301
346
  | `templates[].label` | string | Display label |
302
- | `exportSizes` | array | Grouped export size definitions |
303
- | `exportSizes[].platform` | string | Optional grouping label |
304
- | `exportSizes[].sizes[]` | object | `{ name, label, width, height }` |
347
+ | `export` | array | Flat array of export size definitions |
348
+ | `export[].name` | string | Size identifier (used by `--size` flag) |
349
+ | `export[].label` | string | Display label |
350
+ | `export[].size` | object | `{ width, height }` — output dimensions in pixels |
351
+ | `export[].outFile` | string | Optional output path for this size (supports .png, .jpg) |
305
352
  | `outputs` | array | Optional post-render actions |
306
353
  | `customExport` | object | Optional `{ defaultWidth, defaultHeight }` for custom size UI |
307
354
 
@@ -325,16 +372,11 @@ All collections follow the same structure. No `type` field needed.
325
372
  { "src": "src/screenshots/01-hero.html", "name": "01-hero", "label": "Hero" },
326
373
  { "src": "src/screenshots/02-import.html", "name": "02-import", "label": "Import" }
327
374
  ],
328
- "exportSizes": [
329
- {
330
- "platform": "App Store",
331
- "sizes": [
332
- { "name": "iphone-6.9", "label": "iPhone 6.9\"", "width": 1320, "height": 2868 },
333
- { "name": "iphone-6.7", "label": "iPhone 6.7\"", "width": 1290, "height": 2796 },
334
- { "name": "iphone-6.5", "label": "iPhone 6.5\"", "width": 1284, "height": 2778 },
335
- { "name": "iphone-6.1", "label": "iPhone 6.1\"", "width": 1179, "height": 2556 }
336
- ]
337
- }
375
+ "export": [
376
+ { "name": "iphone-6.9", "label": "iPhone 6.9\"", "size": { "width": 1320, "height": 2868 } },
377
+ { "name": "iphone-6.7", "label": "iPhone 6.7\"", "size": { "width": 1290, "height": 2796 } },
378
+ { "name": "iphone-6.5", "label": "iPhone 6.5\"", "size": { "width": 1284, "height": 2778 } },
379
+ { "name": "iphone-6.1", "label": "iPhone 6.1\"", "size": { "width": 1179, "height": 2556 } }
338
380
  ]
339
381
  }
340
382
  ```
@@ -349,15 +391,10 @@ All collections follow the same structure. No `type` field needed.
349
391
  "templates": [
350
392
  { "src": "src/icon.html", "name": "icon", "label": "App Icon" }
351
393
  ],
352
- "exportSizes": [
353
- {
354
- "platform": "Apple",
355
- "sizes": [
356
- { "name": "1024", "label": "1024px", "width": 1024, "height": 1024 },
357
- { "name": "180", "label": "180px", "width": 180, "height": 180 },
358
- { "name": "120", "label": "120px", "width": 120, "height": 120 }
359
- ]
360
- }
394
+ "export": [
395
+ { "name": "1024", "label": "1024px", "size": { "width": 1024, "height": 1024 } },
396
+ { "name": "180", "label": "180px", "size": { "width": 180, "height": 180 } },
397
+ { "name": "120", "label": "120px", "size": { "width": 120, "height": 120 } }
361
398
  ],
362
399
  "outputs": [
363
400
  { "type": "xcode", "path": "../MyApp/Assets.xcassets/AppIcon.appiconset" }
@@ -377,13 +414,9 @@ All collections follow the same structure. No `type` field needed.
377
414
  { "src": "src/icons/concept-b.html", "name": "concept-b", "label": "Concept B" },
378
415
  { "src": "src/icons/seasonal-winter.html", "name": "seasonal-winter", "label": "Winter" }
379
416
  ],
380
- "exportSizes": [
381
- {
382
- "sizes": [
383
- { "name": "1024", "label": "1024px", "width": 1024, "height": 1024 },
384
- { "name": "512", "label": "512px", "width": 512, "height": 512 }
385
- ]
386
- }
417
+ "export": [
418
+ { "name": "1024", "label": "1024px", "size": { "width": 1024, "height": 1024 } },
419
+ { "name": "512", "label": "512px", "size": { "width": 512, "height": 512 } }
387
420
  ]
388
421
  }
389
422
  ```
@@ -399,14 +432,10 @@ All collections follow the same structure. No `type` field needed.
399
432
  { "src": "src/logo-dark.svg", "name": "logo-dark", "label": "Dark" },
400
433
  { "src": "src/wordmark.svg", "name": "wordmark", "label": "Wordmark" }
401
434
  ],
402
- "exportSizes": [
403
- {
404
- "sizes": [
405
- { "name": "2048", "label": "2048px", "width": 2048, "height": 2048 },
406
- { "name": "1024", "label": "1024px", "width": 1024, "height": 1024 },
407
- { "name": "512", "label": "512px", "width": 512, "height": 512 }
408
- ]
409
- }
435
+ "export": [
436
+ { "name": "2048", "label": "2048px", "size": { "width": 2048, "height": 2048 } },
437
+ { "name": "1024", "label": "1024px", "size": { "width": 1024, "height": 1024 } },
438
+ { "name": "512", "label": "512px", "size": { "width": 512, "height": 512 } }
410
439
  ],
411
440
  "outputs": [
412
441
  { "type": "copy-source", "format": "svg" }
@@ -423,8 +452,8 @@ All collections follow the same structure. No `type` field needed.
423
452
  "templates": [
424
453
  { "src": "src/og/default.html", "name": "default", "label": "Default OG" }
425
454
  ],
426
- "exportSizes": [
427
- { "sizes": [{ "name": "og", "label": "OG Image", "width": 1200, "height": 630 }] }
455
+ "export": [
456
+ { "name": "og", "label": "OG Image", "size": { "width": 1200, "height": 630 } }
428
457
  ]
429
458
  }
430
459
  ```
@@ -438,29 +467,19 @@ All collections follow the same structure. No `type` field needed.
438
467
  "templates": [
439
468
  { "src": "src/favicon.html", "name": "favicon", "label": "Favicon" }
440
469
  ],
441
- "exportSizes": [
442
- {
443
- "platform": "Web",
444
- "sizes": [
445
- { "name": "512", "label": "512px", "width": 512, "height": 512 },
446
- { "name": "192", "label": "192px", "width": 192, "height": 192 },
447
- { "name": "32", "label": "32px", "width": 32, "height": 32 },
448
- { "name": "16", "label": "16px", "width": 16, "height": 16 }
449
- ]
450
- },
451
- {
452
- "platform": "Apple",
453
- "sizes": [
454
- { "name": "apple-touch", "label": "Apple Touch Icon", "width": 180, "height": 180 }
455
- ]
456
- }
470
+ "export": [
471
+ { "name": "512", "label": "512px", "size": { "width": 512, "height": 512 } },
472
+ { "name": "192", "label": "192px", "size": { "width": 192, "height": 192 } },
473
+ { "name": "32", "label": "32px", "size": { "width": 32, "height": 32 }, "outFile": "public/favicon.png" },
474
+ { "name": "16", "label": "16px", "size": { "width": 16, "height": 16 } },
475
+ { "name": "apple-touch", "label": "Apple Touch Icon", "size": { "width": 180, "height": 180 }, "outFile": "public/apple-touch-icon.png" }
457
476
  ]
458
477
  }
459
478
  ```
460
479
 
461
- ## Incremental Builds with manifest.lock
480
+ ## Incremental Builds with assets.lock
462
481
 
463
- The `render` command maintains a `manifest.lock` file that stores SHA256 checksums of each source HTML/SVG file. On subsequent renders, unchanged assets are skipped automatically:
482
+ The `render` command maintains a `assets.lock` file that stores SHA256 checksums of each source HTML/SVG file. On subsequent renders, unchanged assets are skipped automatically:
464
483
 
465
484
  ```
466
485
  $ open-assets render --all
@@ -475,7 +494,7 @@ Use `--force` to re-render everything regardless of the cache.
475
494
 
476
495
  **Limitation**: Only source HTML/SVG files are checksummed. Changes to referenced assets (images in `publicDir`, compiled Tailwind CSS) won't trigger re-renders — use `--force` when those change.
477
496
 
478
- Add `manifest.lock` to your `.gitignore` (done automatically by `open-assets init`).
497
+ Add `assets.lock` to your `.gitignore` (done automatically by `open-assets init`).
479
498
 
480
499
  ## CI/CD with GitHub Actions
481
500
 
@@ -487,7 +506,7 @@ on:
487
506
  push:
488
507
  paths:
489
508
  - 'marketing/screenshots/**'
490
- - 'marketing/screenshots/manifest.json'
509
+ - 'marketing/screenshots/assets.json'
491
510
  jobs:
492
511
  export:
493
512
  runs-on: ubuntu-latest
@@ -524,8 +543,8 @@ jobs:
524
543
 
525
544
  ```
526
545
  project/
527
- manifest.json
528
- manifest.lock # Auto-generated cache (gitignored)
546
+ assets.json
547
+ assets.lock # Auto-generated cache (gitignored)
529
548
  public/ # Shared assets (configured via publicDir)
530
549
  logo-round.png
531
550
  social/