@open-assets/open-assets 0.1.11 → 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 +73 -88
- package/bin/open-assets.mjs +113 -320
- package/lib/add.mjs +476 -0
- package/lib/init.mjs +215 -107
- package/lib/list.mjs +66 -0
- package/lib/lockfile.mjs +1 -1
- package/lib/manifest.mjs +125 -0
- package/lib/render.mjs +206 -0
- package/lib/renderer.mjs +19 -5
- package/lib/server.mjs +14 -4
- package/lib/validate.mjs +90 -0
- package/package.json +7 -2
- package/public/img/banner/1280/banner.png +0 -0
- package/public/img/icon/16/icon.png +0 -0
- package/public/img/icon/180/icon.png +0 -0
- package/public/img/icon/192/icon.png +0 -0
- package/public/img/icon/32/icon.png +0 -0
- package/public/img/icon/512/icon.png +0 -0
- package/public/viewer.html +28 -25
- package/skills/open-assets/SKILL.md +99 -52
package/README.md
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
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
|
|
|
@@ -30,6 +36,22 @@ npx open-assets init
|
|
|
30
36
|
npx open-assets dev
|
|
31
37
|
```
|
|
32
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
|
+
|
|
33
55
|
## Concepts
|
|
34
56
|
|
|
35
57
|
open-assets uses a simple, unified data model. Every asset type follows the same structure: **N templates × M export sizes**.
|
|
@@ -39,7 +61,6 @@ open-assets uses a simple, unified data model. Every asset type follows the same
|
|
|
39
61
|
| **Collection** | A named group of related assets sharing the same source size and export sizes. One tab in the dev UI. |
|
|
40
62
|
| **Template** | A single source file (HTML or SVG) that produces one image per export size. |
|
|
41
63
|
| **Export Size** | A named output dimension that templates are rendered at (e.g., "iPhone 6.9" → 1320×2868). |
|
|
42
|
-
| **Platform** | Optional grouping label for related export sizes (e.g., "App Store", "Play Store"). |
|
|
43
64
|
| **Source Size** | The dimensions the HTML template is authored at. Puppeteer scales from source → export size. |
|
|
44
65
|
| **Output** | An optional post-render action (e.g., write to Xcode `.appiconset`, copy SVG source). |
|
|
45
66
|
|
|
@@ -51,7 +72,7 @@ open-assets uses a simple, unified data model. Every asset type follows the same
|
|
|
51
72
|
npx open-assets init
|
|
52
73
|
```
|
|
53
74
|
|
|
54
|
-
Creates a `
|
|
75
|
+
Creates a `assets.json`, sample HTML templates, and a `public/` directory for shared assets.
|
|
55
76
|
|
|
56
77
|
### 2. Design with Claude Code
|
|
57
78
|
|
|
@@ -74,7 +95,7 @@ your eye as you scroll. Use bold headlines with highlighted keywords, phone
|
|
|
74
95
|
mockups with real app screenshots, and close with reviews + a CTA.
|
|
75
96
|
```
|
|
76
97
|
|
|
77
|
-
Claude reads your `
|
|
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.
|
|
78
99
|
|
|
79
100
|
### 3. Preview
|
|
80
101
|
|
|
@@ -117,7 +138,7 @@ Reference captured screenshots in your HTML templates:
|
|
|
117
138
|
<img src="../../public/screenshots/01-home.png" style="width: 100%; height: 100%; object-fit: cover;" />
|
|
118
139
|
```
|
|
119
140
|
|
|
120
|
-
The `
|
|
141
|
+
The `assets.json` `command` field stores the export command so automation tools know what to run:
|
|
121
142
|
```json
|
|
122
143
|
{
|
|
123
144
|
"command": "npx open-assets render --all"
|
|
@@ -139,7 +160,7 @@ open-assets dev --no-open # Don't auto-open browser
|
|
|
139
160
|
open-assets dev --quiet # Suppress server logs
|
|
140
161
|
open-assets dev --ci # CI mode (quiet + no browser)
|
|
141
162
|
open-assets dev --static-dir ./shared # Serve additional static directories
|
|
142
|
-
open-assets dev --
|
|
163
|
+
open-assets dev --config config.json # Use a custom config filename
|
|
143
164
|
```
|
|
144
165
|
|
|
145
166
|
Options:
|
|
@@ -150,7 +171,7 @@ Options:
|
|
|
150
171
|
| `--no-open` | `OPEN_ASSETS_NO_OPEN` | — | Don't auto-open the browser |
|
|
151
172
|
| `-q, --quiet` | `OPEN_ASSETS_QUIET` | `false` | Suppress server logs |
|
|
152
173
|
| `--ci` | `CI` | `false` | CI mode: quiet + no browser |
|
|
153
|
-
| `--
|
|
174
|
+
| `--config <path>` | `OPEN_ASSETS_CONFIG` | `assets.json` | Path to config file |
|
|
154
175
|
| `--static-dir <dirs...>` | — | — | Additional static directories to serve |
|
|
155
176
|
| `--render-timeout <ms>` | `OPEN_ASSETS_RENDER_TIMEOUT` | `30000` | Puppeteer render timeout |
|
|
156
177
|
|
|
@@ -164,7 +185,6 @@ open-assets render --all # Export at EVERY configured siz
|
|
|
164
185
|
open-assets render --collection screenshots # Render a specific collection
|
|
165
186
|
open-assets render --template 01-hero # Render a single template
|
|
166
187
|
open-assets render --size iphone-6.9 # Use a named export size
|
|
167
|
-
open-assets render --platform "App Store" # Render all sizes for a platform
|
|
168
188
|
open-assets render --width 1320 --height 2868 # Custom size
|
|
169
189
|
open-assets render --force # Re-render everything, ignore cache
|
|
170
190
|
open-assets render -o ./build # Custom output directory
|
|
@@ -177,14 +197,13 @@ Options:
|
|
|
177
197
|
|------|---------|---------|-------------|
|
|
178
198
|
| `--collection <id>` | — | all | Render only the collection with this ID |
|
|
179
199
|
| `--template <name>` | — | all | Render only the template with this name |
|
|
180
|
-
| `--size <name>` | — | — | Use a named export size from
|
|
181
|
-
| `--platform <name>` | — | — | Render only sizes for this platform |
|
|
200
|
+
| `--size <name>` | — | — | Use a named export size from config |
|
|
182
201
|
| `--width <px>` | — | — | Custom output width |
|
|
183
202
|
| `--height <px>` | — | — | Custom output height |
|
|
184
|
-
| `--all` | — | — | Export at every size defined in the
|
|
203
|
+
| `--all` | — | — | Export at every size defined in the config |
|
|
185
204
|
| `--force` | — | — | Re-render all assets even if unchanged |
|
|
186
205
|
| `-o, --output <dir>` | `OPEN_ASSETS_OUTPUT` | `./exports` | Output directory |
|
|
187
|
-
| `--
|
|
206
|
+
| `--config <path>` | `OPEN_ASSETS_CONFIG` | `assets.json` | Path to config file |
|
|
188
207
|
| `--parallel <count>` | `OPEN_ASSETS_PARALLEL` | `1` | Number of parallel renders |
|
|
189
208
|
| `--render-timeout <ms>` | `OPEN_ASSETS_RENDER_TIMEOUT` | `30000` | Puppeteer render timeout |
|
|
190
209
|
| `--json` | — | — | Output results as JSON |
|
|
@@ -200,9 +219,6 @@ open-assets render --collection screenshots --template 01-hero --all
|
|
|
200
219
|
|
|
201
220
|
# All templates at one device size
|
|
202
221
|
open-assets render --collection screenshots --size iphone-6.9
|
|
203
|
-
|
|
204
|
-
# All templates for a specific platform
|
|
205
|
-
open-assets render --collection screenshots --platform "App Store"
|
|
206
222
|
```
|
|
207
223
|
|
|
208
224
|
**Output structure**: `exports/{collection}/{size}/{template}.png`
|
|
@@ -231,7 +247,7 @@ exports/
|
|
|
231
247
|
|
|
232
248
|
### `open-assets list [dir]`
|
|
233
249
|
|
|
234
|
-
List all collections and templates defined in the
|
|
250
|
+
List all collections and templates defined in the config.
|
|
235
251
|
|
|
236
252
|
```bash
|
|
237
253
|
open-assets list # Pretty-print asset tree
|
|
@@ -240,7 +256,7 @@ open-assets list --json # Output as JSON
|
|
|
240
256
|
|
|
241
257
|
### `open-assets validate [dir]`
|
|
242
258
|
|
|
243
|
-
Validate the
|
|
259
|
+
Validate the config and check that all referenced source files exist.
|
|
244
260
|
|
|
245
261
|
```bash
|
|
246
262
|
open-assets validate # Check current directory
|
|
@@ -263,7 +279,7 @@ npx skills add https://github.com/Parra-Inc/open-assets --skill open-assets
|
|
|
263
279
|
|
|
264
280
|
### `open-assets init [dir]`
|
|
265
281
|
|
|
266
|
-
Scaffold a new project with a `
|
|
282
|
+
Scaffold a new project with a `assets.json`, sample HTML templates, and a `public/` directory.
|
|
267
283
|
|
|
268
284
|
```bash
|
|
269
285
|
open-assets init # Current directory
|
|
@@ -272,7 +288,7 @@ open-assets init ./my-assets # Specific directory
|
|
|
272
288
|
|
|
273
289
|
## Manifest Format
|
|
274
290
|
|
|
275
|
-
Your project needs a `
|
|
291
|
+
Your project needs a `assets.json` at its root. This file defines the collections shown in the viewer and all export options.
|
|
276
292
|
|
|
277
293
|
```json
|
|
278
294
|
{
|
|
@@ -308,14 +324,9 @@ All collections follow the same structure. No `type` field needed.
|
|
|
308
324
|
{ "src": "src/screenshots/01-hero.html", "name": "01-hero", "label": "Hero" },
|
|
309
325
|
{ "src": "src/screenshots/02-features.html", "name": "02-features", "label": "Features" }
|
|
310
326
|
],
|
|
311
|
-
"
|
|
312
|
-
{
|
|
313
|
-
|
|
314
|
-
"sizes": [
|
|
315
|
-
{ "name": "iphone-6.9", "label": "iPhone 6.9\"", "width": 1320, "height": 2868 },
|
|
316
|
-
{ "name": "iphone-6.7", "label": "iPhone 6.7\"", "width": 1290, "height": 2796 }
|
|
317
|
-
]
|
|
318
|
-
}
|
|
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 } }
|
|
319
330
|
],
|
|
320
331
|
"outputs": [
|
|
321
332
|
{ "type": "xcode", "path": "../MyApp/Assets.xcassets/AppIcon.appiconset" }
|
|
@@ -333,9 +344,11 @@ All collections follow the same structure. No `type` field needed.
|
|
|
333
344
|
| `templates[].src` | string | Path to HTML/SVG file (relative to project root) |
|
|
334
345
|
| `templates[].name` | string | Filename for exports (used by `--template` flag) |
|
|
335
346
|
| `templates[].label` | string | Display label |
|
|
336
|
-
| `
|
|
337
|
-
| `
|
|
338
|
-
| `
|
|
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) |
|
|
339
352
|
| `outputs` | array | Optional post-render actions |
|
|
340
353
|
| `customExport` | object | Optional `{ defaultWidth, defaultHeight }` for custom size UI |
|
|
341
354
|
|
|
@@ -359,16 +372,11 @@ All collections follow the same structure. No `type` field needed.
|
|
|
359
372
|
{ "src": "src/screenshots/01-hero.html", "name": "01-hero", "label": "Hero" },
|
|
360
373
|
{ "src": "src/screenshots/02-import.html", "name": "02-import", "label": "Import" }
|
|
361
374
|
],
|
|
362
|
-
"
|
|
363
|
-
{
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
{ "name": "iphone-6.7", "label": "iPhone 6.7\"", "width": 1290, "height": 2796 },
|
|
368
|
-
{ "name": "iphone-6.5", "label": "iPhone 6.5\"", "width": 1284, "height": 2778 },
|
|
369
|
-
{ "name": "iphone-6.1", "label": "iPhone 6.1\"", "width": 1179, "height": 2556 }
|
|
370
|
-
]
|
|
371
|
-
}
|
|
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 } }
|
|
372
380
|
]
|
|
373
381
|
}
|
|
374
382
|
```
|
|
@@ -383,15 +391,10 @@ All collections follow the same structure. No `type` field needed.
|
|
|
383
391
|
"templates": [
|
|
384
392
|
{ "src": "src/icon.html", "name": "icon", "label": "App Icon" }
|
|
385
393
|
],
|
|
386
|
-
"
|
|
387
|
-
{
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
{ "name": "1024", "label": "1024px", "width": 1024, "height": 1024 },
|
|
391
|
-
{ "name": "180", "label": "180px", "width": 180, "height": 180 },
|
|
392
|
-
{ "name": "120", "label": "120px", "width": 120, "height": 120 }
|
|
393
|
-
]
|
|
394
|
-
}
|
|
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 } }
|
|
395
398
|
],
|
|
396
399
|
"outputs": [
|
|
397
400
|
{ "type": "xcode", "path": "../MyApp/Assets.xcassets/AppIcon.appiconset" }
|
|
@@ -411,13 +414,9 @@ All collections follow the same structure. No `type` field needed.
|
|
|
411
414
|
{ "src": "src/icons/concept-b.html", "name": "concept-b", "label": "Concept B" },
|
|
412
415
|
{ "src": "src/icons/seasonal-winter.html", "name": "seasonal-winter", "label": "Winter" }
|
|
413
416
|
],
|
|
414
|
-
"
|
|
415
|
-
{
|
|
416
|
-
|
|
417
|
-
{ "name": "1024", "label": "1024px", "width": 1024, "height": 1024 },
|
|
418
|
-
{ "name": "512", "label": "512px", "width": 512, "height": 512 }
|
|
419
|
-
]
|
|
420
|
-
}
|
|
417
|
+
"export": [
|
|
418
|
+
{ "name": "1024", "label": "1024px", "size": { "width": 1024, "height": 1024 } },
|
|
419
|
+
{ "name": "512", "label": "512px", "size": { "width": 512, "height": 512 } }
|
|
421
420
|
]
|
|
422
421
|
}
|
|
423
422
|
```
|
|
@@ -433,14 +432,10 @@ All collections follow the same structure. No `type` field needed.
|
|
|
433
432
|
{ "src": "src/logo-dark.svg", "name": "logo-dark", "label": "Dark" },
|
|
434
433
|
{ "src": "src/wordmark.svg", "name": "wordmark", "label": "Wordmark" }
|
|
435
434
|
],
|
|
436
|
-
"
|
|
437
|
-
{
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
{ "name": "1024", "label": "1024px", "width": 1024, "height": 1024 },
|
|
441
|
-
{ "name": "512", "label": "512px", "width": 512, "height": 512 }
|
|
442
|
-
]
|
|
443
|
-
}
|
|
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 } }
|
|
444
439
|
],
|
|
445
440
|
"outputs": [
|
|
446
441
|
{ "type": "copy-source", "format": "svg" }
|
|
@@ -457,8 +452,8 @@ All collections follow the same structure. No `type` field needed.
|
|
|
457
452
|
"templates": [
|
|
458
453
|
{ "src": "src/og/default.html", "name": "default", "label": "Default OG" }
|
|
459
454
|
],
|
|
460
|
-
"
|
|
461
|
-
{ "
|
|
455
|
+
"export": [
|
|
456
|
+
{ "name": "og", "label": "OG Image", "size": { "width": 1200, "height": 630 } }
|
|
462
457
|
]
|
|
463
458
|
}
|
|
464
459
|
```
|
|
@@ -472,29 +467,19 @@ All collections follow the same structure. No `type` field needed.
|
|
|
472
467
|
"templates": [
|
|
473
468
|
{ "src": "src/favicon.html", "name": "favicon", "label": "Favicon" }
|
|
474
469
|
],
|
|
475
|
-
"
|
|
476
|
-
{
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
{ "name": "32", "label": "32px", "width": 32, "height": 32 },
|
|
482
|
-
{ "name": "16", "label": "16px", "width": 16, "height": 16 }
|
|
483
|
-
]
|
|
484
|
-
},
|
|
485
|
-
{
|
|
486
|
-
"platform": "Apple",
|
|
487
|
-
"sizes": [
|
|
488
|
-
{ "name": "apple-touch", "label": "Apple Touch Icon", "width": 180, "height": 180 }
|
|
489
|
-
]
|
|
490
|
-
}
|
|
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" }
|
|
491
476
|
]
|
|
492
477
|
}
|
|
493
478
|
```
|
|
494
479
|
|
|
495
|
-
## Incremental Builds with
|
|
480
|
+
## Incremental Builds with assets.lock
|
|
496
481
|
|
|
497
|
-
The `render` command maintains a `
|
|
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:
|
|
498
483
|
|
|
499
484
|
```
|
|
500
485
|
$ open-assets render --all
|
|
@@ -509,7 +494,7 @@ Use `--force` to re-render everything regardless of the cache.
|
|
|
509
494
|
|
|
510
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.
|
|
511
496
|
|
|
512
|
-
Add `
|
|
497
|
+
Add `assets.lock` to your `.gitignore` (done automatically by `open-assets init`).
|
|
513
498
|
|
|
514
499
|
## CI/CD with GitHub Actions
|
|
515
500
|
|
|
@@ -521,7 +506,7 @@ on:
|
|
|
521
506
|
push:
|
|
522
507
|
paths:
|
|
523
508
|
- 'marketing/screenshots/**'
|
|
524
|
-
- 'marketing/screenshots/
|
|
509
|
+
- 'marketing/screenshots/assets.json'
|
|
525
510
|
jobs:
|
|
526
511
|
export:
|
|
527
512
|
runs-on: ubuntu-latest
|
|
@@ -558,8 +543,8 @@ jobs:
|
|
|
558
543
|
|
|
559
544
|
```
|
|
560
545
|
project/
|
|
561
|
-
|
|
562
|
-
|
|
546
|
+
assets.json
|
|
547
|
+
assets.lock # Auto-generated cache (gitignored)
|
|
563
548
|
public/ # Shared assets (configured via publicDir)
|
|
564
549
|
logo-round.png
|
|
565
550
|
social/
|