@open-assets/open-assets 0.1.11 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -120
- package/bin/open-assets.mjs +165 -319
- package/lib/add.mjs +476 -0
- package/lib/init.mjs +215 -107
- package/lib/list.mjs +64 -0
- package/lib/lockfile.mjs +53 -2
- package/lib/manifest.mjs +132 -0
- package/lib/render.mjs +219 -0
- package/lib/renderer.mjs +57 -7
- package/lib/server.mjs +58 -27
- package/lib/validate.mjs +93 -0
- package/package.json +7 -2
- package/public/img/banner/1280/banner.png +0 -0
- package/public/img/examples/cat-iq-test-icon.png +0 -0
- package/public/img/examples/cat-iq-test.png +0 -0
- package/public/img/examples/no-context-icon.png +0 -0
- package/public/img/examples/no-context.png +0 -0
- package/public/img/examples/only-recipes-icon.png +0 -0
- package/public/img/examples/only-recipes.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 +59 -56
- package/skills/open-assets/SKILL.md +121 -76
package/README.md
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
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
|
|
|
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
|
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
<p><img src="public/img/examples/only-recipes-icon.png" width="14" height="14" /> <a href="https://onlyrecipes.app"><strong>Only Recipes</strong></a> (<a href="examples/only-recipes">examples</a>)</p>
|
|
16
|
+
<img src="public/img/examples/only-recipes.png" alt="Only Recipes screenshots" width="100%" />
|
|
17
|
+
|
|
18
|
+
<p><img src="public/img/examples/cat-iq-test-icon.png" width="14" height="14" /> <a href="https://apps.apple.com/us/app/cat-iq-test/id6759520249"><strong>Cat IQ Test</strong></a> (<a href="examples/cat-iq-test">examples</a>)</p>
|
|
19
|
+
<img src="public/img/examples/cat-iq-test.png" alt="Cat IQ Test screenshots" width="100%" />
|
|
20
|
+
|
|
21
|
+
<p><img src="public/img/examples/no-context-icon.png" width="14" height="14" /> <a href="https://nocontextbot.com"><strong>No Context Bot</strong></a> (<a href="examples/no-context">examples</a>)</p>
|
|
22
|
+
<img src="public/img/examples/no-context.png" alt="No Context Bot screenshots" width="100%" />
|
|
23
|
+
|
|
7
24
|
## Installation
|
|
8
25
|
|
|
9
26
|
```bash
|
|
@@ -30,6 +47,22 @@ npx open-assets init
|
|
|
30
47
|
npx open-assets dev
|
|
31
48
|
```
|
|
32
49
|
|
|
50
|
+
## Shell Alias
|
|
51
|
+
|
|
52
|
+
Add an alias to your shell profile for a shorter command:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
echo 'alias oa="npx open-assets"' >> ~/.zshrc && source ~/.zshrc
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Then use `oa` anywhere:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
oa dev
|
|
62
|
+
oa render --force
|
|
63
|
+
oa init
|
|
64
|
+
```
|
|
65
|
+
|
|
33
66
|
## Concepts
|
|
34
67
|
|
|
35
68
|
open-assets uses a simple, unified data model. Every asset type follows the same structure: **N templates × M export sizes**.
|
|
@@ -39,7 +72,6 @@ open-assets uses a simple, unified data model. Every asset type follows the same
|
|
|
39
72
|
| **Collection** | A named group of related assets sharing the same source size and export sizes. One tab in the dev UI. |
|
|
40
73
|
| **Template** | A single source file (HTML or SVG) that produces one image per export size. |
|
|
41
74
|
| **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
75
|
| **Source Size** | The dimensions the HTML template is authored at. Puppeteer scales from source → export size. |
|
|
44
76
|
| **Output** | An optional post-render action (e.g., write to Xcode `.appiconset`, copy SVG source). |
|
|
45
77
|
|
|
@@ -51,7 +83,7 @@ open-assets uses a simple, unified data model. Every asset type follows the same
|
|
|
51
83
|
npx open-assets init
|
|
52
84
|
```
|
|
53
85
|
|
|
54
|
-
Creates a `
|
|
86
|
+
Creates a `assets.json`, sample HTML templates, and a `public/` directory for shared assets.
|
|
55
87
|
|
|
56
88
|
### 2. Design with Claude Code
|
|
57
89
|
|
|
@@ -74,13 +106,13 @@ your eye as you scroll. Use bold headlines with highlighted keywords, phone
|
|
|
74
106
|
mockups with real app screenshots, and close with reviews + a CTA.
|
|
75
107
|
```
|
|
76
108
|
|
|
77
|
-
Claude reads your `
|
|
109
|
+
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
110
|
|
|
79
111
|
### 3. Preview
|
|
80
112
|
|
|
81
113
|
```bash
|
|
82
114
|
# With Tailwind
|
|
83
|
-
concurrently "npx @tailwindcss/cli -i
|
|
115
|
+
concurrently "npx @tailwindcss/cli -i assets/styles.css -o dist/styles.css --watch" "npx open-assets dev"
|
|
84
116
|
|
|
85
117
|
# Without Tailwind
|
|
86
118
|
npx open-assets dev
|
|
@@ -91,7 +123,7 @@ Opens a live preview UI at `http://localhost:3200` with zoom/pan controls and ex
|
|
|
91
123
|
### 4. Export
|
|
92
124
|
|
|
93
125
|
```bash
|
|
94
|
-
npx open-assets render --
|
|
126
|
+
npx open-assets render --force
|
|
95
127
|
```
|
|
96
128
|
|
|
97
129
|
Exports every template at every configured export size into `./exports/`, organized as `exports/{collection}/{size}/{template}.png`.
|
|
@@ -109,7 +141,7 @@ Capture real app screenshots via Playwright or XCTest, then use them inside your
|
|
|
109
141
|
npx playwright test --project=screenshots
|
|
110
142
|
|
|
111
143
|
# 2. Export marketing screenshots with those captures embedded
|
|
112
|
-
npx open-assets render --
|
|
144
|
+
npx open-assets render --force
|
|
113
145
|
```
|
|
114
146
|
|
|
115
147
|
Reference captured screenshots in your HTML templates:
|
|
@@ -117,10 +149,10 @@ Reference captured screenshots in your HTML templates:
|
|
|
117
149
|
<img src="../../public/screenshots/01-home.png" style="width: 100%; height: 100%; object-fit: cover;" />
|
|
118
150
|
```
|
|
119
151
|
|
|
120
|
-
The `
|
|
152
|
+
The `assets.json` `command` field stores the export command so automation tools know what to run:
|
|
121
153
|
```json
|
|
122
154
|
{
|
|
123
|
-
"command": "npx open-assets render --
|
|
155
|
+
"command": "npx open-assets render --force"
|
|
124
156
|
}
|
|
125
157
|
```
|
|
126
158
|
|
|
@@ -139,7 +171,7 @@ open-assets dev --no-open # Don't auto-open browser
|
|
|
139
171
|
open-assets dev --quiet # Suppress server logs
|
|
140
172
|
open-assets dev --ci # CI mode (quiet + no browser)
|
|
141
173
|
open-assets dev --static-dir ./shared # Serve additional static directories
|
|
142
|
-
open-assets dev --
|
|
174
|
+
open-assets dev --config config.json # Use a custom config filename
|
|
143
175
|
```
|
|
144
176
|
|
|
145
177
|
Options:
|
|
@@ -150,7 +182,7 @@ Options:
|
|
|
150
182
|
| `--no-open` | `OPEN_ASSETS_NO_OPEN` | — | Don't auto-open the browser |
|
|
151
183
|
| `-q, --quiet` | `OPEN_ASSETS_QUIET` | `false` | Suppress server logs |
|
|
152
184
|
| `--ci` | `CI` | `false` | CI mode: quiet + no browser |
|
|
153
|
-
| `--
|
|
185
|
+
| `--config <path>` | `OPEN_ASSETS_CONFIG` | `assets.json` | Path to config file |
|
|
154
186
|
| `--static-dir <dirs...>` | — | — | Additional static directories to serve |
|
|
155
187
|
| `--render-timeout <ms>` | `OPEN_ASSETS_RENDER_TIMEOUT` | `30000` | Puppeteer render timeout |
|
|
156
188
|
|
|
@@ -160,13 +192,11 @@ Render assets headlessly via the command line, without opening a browser.
|
|
|
160
192
|
|
|
161
193
|
```bash
|
|
162
194
|
open-assets render # Render all collections at source size
|
|
163
|
-
open-assets render --
|
|
195
|
+
open-assets render --force # Export at every size, ignore cache
|
|
164
196
|
open-assets render --collection screenshots # Render a specific collection
|
|
165
197
|
open-assets render --template 01-hero # Render a single template
|
|
166
198
|
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
199
|
open-assets render --width 1320 --height 2868 # Custom size
|
|
169
|
-
open-assets render --force # Re-render everything, ignore cache
|
|
170
200
|
open-assets render -o ./build # Custom output directory
|
|
171
201
|
open-assets render --json # Output results as JSON (for CI)
|
|
172
202
|
open-assets render --quiet # Suppress progress logs
|
|
@@ -177,14 +207,12 @@ Options:
|
|
|
177
207
|
|------|---------|---------|-------------|
|
|
178
208
|
| `--collection <id>` | — | all | Render only the collection with this ID |
|
|
179
209
|
| `--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 |
|
|
210
|
+
| `--size <name>` | — | — | Use a named export size from config |
|
|
182
211
|
| `--width <px>` | — | — | Custom output width |
|
|
183
212
|
| `--height <px>` | — | — | Custom output height |
|
|
184
|
-
|
|
|
185
|
-
| `--force` | — | — | Re-render all assets even if unchanged |
|
|
213
|
+
| `-f, --force` | — | — | Export at every size and re-render all (ignores cache) |
|
|
186
214
|
| `-o, --output <dir>` | `OPEN_ASSETS_OUTPUT` | `./exports` | Output directory |
|
|
187
|
-
| `--
|
|
215
|
+
| `--config <path>` | `OPEN_ASSETS_CONFIG` | `assets.json` | Path to config file |
|
|
188
216
|
| `--parallel <count>` | `OPEN_ASSETS_PARALLEL` | `1` | Number of parallel renders |
|
|
189
217
|
| `--render-timeout <ms>` | `OPEN_ASSETS_RENDER_TIMEOUT` | `30000` | Puppeteer render timeout |
|
|
190
218
|
| `--json` | — | — | Output results as JSON |
|
|
@@ -196,13 +224,10 @@ Options:
|
|
|
196
224
|
open-assets render --collection screenshots --template 01-hero --size iphone-6.9
|
|
197
225
|
|
|
198
226
|
# One template at all device sizes
|
|
199
|
-
open-assets render --collection screenshots --template 01-hero --
|
|
227
|
+
open-assets render --collection screenshots --template 01-hero --force
|
|
200
228
|
|
|
201
229
|
# All templates at one device size
|
|
202
230
|
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
231
|
```
|
|
207
232
|
|
|
208
233
|
**Output structure**: `exports/{collection}/{size}/{template}.png`
|
|
@@ -231,7 +256,7 @@ exports/
|
|
|
231
256
|
|
|
232
257
|
### `open-assets list [dir]`
|
|
233
258
|
|
|
234
|
-
List all collections and templates defined in the
|
|
259
|
+
List all collections and templates defined in the config.
|
|
235
260
|
|
|
236
261
|
```bash
|
|
237
262
|
open-assets list # Pretty-print asset tree
|
|
@@ -240,7 +265,7 @@ open-assets list --json # Output as JSON
|
|
|
240
265
|
|
|
241
266
|
### `open-assets validate [dir]`
|
|
242
267
|
|
|
243
|
-
Validate the
|
|
268
|
+
Validate the config and check that all referenced source files exist.
|
|
244
269
|
|
|
245
270
|
```bash
|
|
246
271
|
open-assets validate # Check current directory
|
|
@@ -263,7 +288,7 @@ npx skills add https://github.com/Parra-Inc/open-assets --skill open-assets
|
|
|
263
288
|
|
|
264
289
|
### `open-assets init [dir]`
|
|
265
290
|
|
|
266
|
-
Scaffold a new project with a `
|
|
291
|
+
Scaffold a new project with a `assets.json`, sample HTML templates, and a `public/` directory.
|
|
267
292
|
|
|
268
293
|
```bash
|
|
269
294
|
open-assets init # Current directory
|
|
@@ -272,14 +297,14 @@ open-assets init ./my-assets # Specific directory
|
|
|
272
297
|
|
|
273
298
|
## Manifest Format
|
|
274
299
|
|
|
275
|
-
Your project needs a `
|
|
300
|
+
Your project needs a `assets.json` at its root. This file defines the collections shown in the viewer and all export options.
|
|
276
301
|
|
|
277
302
|
```json
|
|
278
303
|
{
|
|
279
304
|
"version": 1,
|
|
280
305
|
"name": "My App",
|
|
281
306
|
"publicDir": "public",
|
|
282
|
-
"command": "npx open-assets render --
|
|
307
|
+
"command": "npx open-assets render --force",
|
|
283
308
|
"collections": [ ... ]
|
|
284
309
|
}
|
|
285
310
|
```
|
|
@@ -305,19 +330,12 @@ All collections follow the same structure. No `type` field needed.
|
|
|
305
330
|
"sourceSize": { "width": 440, "height": 956 },
|
|
306
331
|
"borderRadius": 4,
|
|
307
332
|
"templates": [
|
|
308
|
-
{ "src": "
|
|
309
|
-
{ "src": "
|
|
310
|
-
],
|
|
311
|
-
"exportSizes": [
|
|
312
|
-
{
|
|
313
|
-
"platform": "App Store",
|
|
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
|
-
}
|
|
333
|
+
{ "src": "assets/screenshots/01-hero.html", "name": "01-hero", "label": "Hero" },
|
|
334
|
+
{ "src": "assets/screenshots/02-features.html", "name": "02-features", "label": "Features" }
|
|
319
335
|
],
|
|
320
|
-
"
|
|
336
|
+
"export": [
|
|
337
|
+
{ "name": "iphone-6.9", "label": "iPhone 6.9\"", "size": { "width": 1320, "height": 2868 } },
|
|
338
|
+
{ "name": "iphone-6.7", "label": "iPhone 6.7\"", "size": { "width": 1290, "height": 2796 } },
|
|
321
339
|
{ "type": "xcode", "path": "../MyApp/Assets.xcassets/AppIcon.appiconset" }
|
|
322
340
|
]
|
|
323
341
|
}
|
|
@@ -333,14 +351,18 @@ All collections follow the same structure. No `type` field needed.
|
|
|
333
351
|
| `templates[].src` | string | Path to HTML/SVG file (relative to project root) |
|
|
334
352
|
| `templates[].name` | string | Filename for exports (used by `--template` flag) |
|
|
335
353
|
| `templates[].label` | string | Display label |
|
|
336
|
-
| `
|
|
337
|
-
| `
|
|
338
|
-
| `
|
|
339
|
-
| `
|
|
354
|
+
| `export` | array | Array of export sizes and output actions |
|
|
355
|
+
| `export[].name` | string | Size identifier (used by `--size` flag) |
|
|
356
|
+
| `export[].label` | string | Display label |
|
|
357
|
+
| `export[].size` | object | `{ width, height }` — output dimensions in pixels |
|
|
358
|
+
| `export[].outFile` | string | Optional output path for this size (supports .png, .jpg) |
|
|
359
|
+
| `export[].type` | string | Output action type (`xcode`, `copy-source`). Entries with `type` are post-render actions, not sizes |
|
|
340
360
|
| `customExport` | object | Optional `{ defaultWidth, defaultHeight }` for custom size UI |
|
|
341
361
|
|
|
342
362
|
### Output Types
|
|
343
363
|
|
|
364
|
+
Export entries with a `type` field are post-render actions (run with `--force`):
|
|
365
|
+
|
|
344
366
|
| Type | Config | Description |
|
|
345
367
|
|------|--------|-------------|
|
|
346
368
|
| `xcode` | `{ "type": "xcode", "path": "..." }` | Render icon and write to Xcode asset catalog |
|
|
@@ -356,19 +378,14 @@ All collections follow the same structure. No `type` field needed.
|
|
|
356
378
|
"sourceSize": { "width": 440, "height": 956 },
|
|
357
379
|
"borderRadius": 4,
|
|
358
380
|
"templates": [
|
|
359
|
-
{ "src": "
|
|
360
|
-
{ "src": "
|
|
381
|
+
{ "src": "assets/screenshots/01-hero.html", "name": "01-hero", "label": "Hero" },
|
|
382
|
+
{ "src": "assets/screenshots/02-import.html", "name": "02-import", "label": "Import" }
|
|
361
383
|
],
|
|
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
|
-
}
|
|
384
|
+
"export": [
|
|
385
|
+
{ "name": "iphone-6.9", "label": "iPhone 6.9\"", "size": { "width": 1320, "height": 2868 } },
|
|
386
|
+
{ "name": "iphone-6.7", "label": "iPhone 6.7\"", "size": { "width": 1290, "height": 2796 } },
|
|
387
|
+
{ "name": "iphone-6.5", "label": "iPhone 6.5\"", "size": { "width": 1284, "height": 2778 } },
|
|
388
|
+
{ "name": "iphone-6.1", "label": "iPhone 6.1\"", "size": { "width": 1179, "height": 2556 } }
|
|
372
389
|
]
|
|
373
390
|
}
|
|
374
391
|
```
|
|
@@ -381,19 +398,12 @@ All collections follow the same structure. No `type` field needed.
|
|
|
381
398
|
"sourceSize": { "width": 1024, "height": 1024 },
|
|
382
399
|
"borderRadius": 224,
|
|
383
400
|
"templates": [
|
|
384
|
-
{ "src": "
|
|
401
|
+
{ "src": "assets/icon.html", "name": "icon", "label": "App Icon" }
|
|
385
402
|
],
|
|
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
|
-
}
|
|
395
|
-
],
|
|
396
|
-
"outputs": [
|
|
403
|
+
"export": [
|
|
404
|
+
{ "name": "1024", "label": "1024px", "size": { "width": 1024, "height": 1024 } },
|
|
405
|
+
{ "name": "180", "label": "180px", "size": { "width": 180, "height": 180 } },
|
|
406
|
+
{ "name": "120", "label": "120px", "size": { "width": 120, "height": 120 } },
|
|
397
407
|
{ "type": "xcode", "path": "../MyApp/Assets.xcassets/AppIcon.appiconset" }
|
|
398
408
|
]
|
|
399
409
|
}
|
|
@@ -407,17 +417,13 @@ All collections follow the same structure. No `type` field needed.
|
|
|
407
417
|
"sourceSize": { "width": 1024, "height": 1024 },
|
|
408
418
|
"borderRadius": 224,
|
|
409
419
|
"templates": [
|
|
410
|
-
{ "src": "
|
|
411
|
-
{ "src": "
|
|
412
|
-
{ "src": "
|
|
420
|
+
{ "src": "assets/icons/concept-a.html", "name": "concept-a", "label": "Concept A" },
|
|
421
|
+
{ "src": "assets/icons/concept-b.html", "name": "concept-b", "label": "Concept B" },
|
|
422
|
+
{ "src": "assets/icons/seasonal-winter.html", "name": "seasonal-winter", "label": "Winter" }
|
|
413
423
|
],
|
|
414
|
-
"
|
|
415
|
-
{
|
|
416
|
-
|
|
417
|
-
{ "name": "1024", "label": "1024px", "width": 1024, "height": 1024 },
|
|
418
|
-
{ "name": "512", "label": "512px", "width": 512, "height": 512 }
|
|
419
|
-
]
|
|
420
|
-
}
|
|
424
|
+
"export": [
|
|
425
|
+
{ "name": "1024", "label": "1024px", "size": { "width": 1024, "height": 1024 } },
|
|
426
|
+
{ "name": "512", "label": "512px", "size": { "width": 512, "height": 512 } }
|
|
421
427
|
]
|
|
422
428
|
}
|
|
423
429
|
```
|
|
@@ -429,20 +435,14 @@ All collections follow the same structure. No `type` field needed.
|
|
|
429
435
|
"label": "Logo",
|
|
430
436
|
"sourceSize": { "width": 940, "height": 940 },
|
|
431
437
|
"templates": [
|
|
432
|
-
{ "src": "
|
|
433
|
-
{ "src": "
|
|
434
|
-
{ "src": "
|
|
435
|
-
],
|
|
436
|
-
"exportSizes": [
|
|
437
|
-
{
|
|
438
|
-
"sizes": [
|
|
439
|
-
{ "name": "2048", "label": "2048px", "width": 2048, "height": 2048 },
|
|
440
|
-
{ "name": "1024", "label": "1024px", "width": 1024, "height": 1024 },
|
|
441
|
-
{ "name": "512", "label": "512px", "width": 512, "height": 512 }
|
|
442
|
-
]
|
|
443
|
-
}
|
|
438
|
+
{ "src": "assets/logo.svg", "name": "logo", "label": "Logo" },
|
|
439
|
+
{ "src": "assets/logo-dark.svg", "name": "logo-dark", "label": "Dark" },
|
|
440
|
+
{ "src": "assets/wordmark.svg", "name": "wordmark", "label": "Wordmark" }
|
|
444
441
|
],
|
|
445
|
-
"
|
|
442
|
+
"export": [
|
|
443
|
+
{ "name": "2048", "label": "2048px", "size": { "width": 2048, "height": 2048 } },
|
|
444
|
+
{ "name": "1024", "label": "1024px", "size": { "width": 1024, "height": 1024 } },
|
|
445
|
+
{ "name": "512", "label": "512px", "size": { "width": 512, "height": 512 } },
|
|
446
446
|
{ "type": "copy-source", "format": "svg" }
|
|
447
447
|
]
|
|
448
448
|
}
|
|
@@ -455,10 +455,10 @@ All collections follow the same structure. No `type` field needed.
|
|
|
455
455
|
"label": "Social Cards",
|
|
456
456
|
"sourceSize": { "width": 1200, "height": 630 },
|
|
457
457
|
"templates": [
|
|
458
|
-
{ "src": "
|
|
458
|
+
{ "src": "assets/og/default.html", "name": "default", "label": "Default OG" }
|
|
459
459
|
],
|
|
460
|
-
"
|
|
461
|
-
{ "
|
|
460
|
+
"export": [
|
|
461
|
+
{ "name": "og", "label": "OG Image", "size": { "width": 1200, "height": 630 } }
|
|
462
462
|
]
|
|
463
463
|
}
|
|
464
464
|
```
|
|
@@ -470,34 +470,24 @@ All collections follow the same structure. No `type` field needed.
|
|
|
470
470
|
"label": "Favicons",
|
|
471
471
|
"sourceSize": { "width": 512, "height": 512 },
|
|
472
472
|
"templates": [
|
|
473
|
-
{ "src": "
|
|
473
|
+
{ "src": "assets/favicon.html", "name": "favicon", "label": "Favicon" }
|
|
474
474
|
],
|
|
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
|
-
}
|
|
475
|
+
"export": [
|
|
476
|
+
{ "name": "512", "label": "512px", "size": { "width": 512, "height": 512 } },
|
|
477
|
+
{ "name": "192", "label": "192px", "size": { "width": 192, "height": 192 } },
|
|
478
|
+
{ "name": "32", "label": "32px", "size": { "width": 32, "height": 32 }, "outFile": "public/favicon.png" },
|
|
479
|
+
{ "name": "16", "label": "16px", "size": { "width": 16, "height": 16 } },
|
|
480
|
+
{ "name": "apple-touch", "label": "Apple Touch Icon", "size": { "width": 180, "height": 180 }, "outFile": "public/apple-touch-icon.png" }
|
|
491
481
|
]
|
|
492
482
|
}
|
|
493
483
|
```
|
|
494
484
|
|
|
495
|
-
## Incremental Builds with
|
|
485
|
+
## Incremental Builds with assets.lock
|
|
496
486
|
|
|
497
|
-
The `render` command maintains a `
|
|
487
|
+
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
488
|
|
|
499
489
|
```
|
|
500
|
-
$ open-assets render --
|
|
490
|
+
$ open-assets render --force
|
|
501
491
|
Skipping 01-hero at 1320x2868 (unchanged)
|
|
502
492
|
Rendering 03-new-screen at 1320x2868...
|
|
503
493
|
→ exports/screenshots/iphone-6.9/03-new-screen.png
|
|
@@ -509,7 +499,7 @@ Use `--force` to re-render everything regardless of the cache.
|
|
|
509
499
|
|
|
510
500
|
**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
501
|
|
|
512
|
-
|
|
502
|
+
Commit `assets.lock` to your repository so teammates and CI benefit from the cache.
|
|
513
503
|
|
|
514
504
|
## CI/CD with GitHub Actions
|
|
515
505
|
|
|
@@ -521,7 +511,7 @@ on:
|
|
|
521
511
|
push:
|
|
522
512
|
paths:
|
|
523
513
|
- 'marketing/screenshots/**'
|
|
524
|
-
- 'marketing/screenshots/
|
|
514
|
+
- 'marketing/screenshots/assets.json'
|
|
525
515
|
jobs:
|
|
526
516
|
export:
|
|
527
517
|
runs-on: ubuntu-latest
|
|
@@ -532,7 +522,7 @@ jobs:
|
|
|
532
522
|
node-version: 20
|
|
533
523
|
- run: npm ci
|
|
534
524
|
- run: npx open-assets validate
|
|
535
|
-
- run: npx open-assets render --
|
|
525
|
+
- run: npx open-assets render --force --json --quiet
|
|
536
526
|
- uses: actions/upload-artifact@v4
|
|
537
527
|
with:
|
|
538
528
|
name: screenshots
|
|
@@ -558,15 +548,15 @@ jobs:
|
|
|
558
548
|
|
|
559
549
|
```
|
|
560
550
|
project/
|
|
561
|
-
|
|
562
|
-
|
|
551
|
+
assets.json
|
|
552
|
+
assets.lock # Auto-generated cache (commit this)
|
|
563
553
|
public/ # Shared assets (configured via publicDir)
|
|
564
554
|
logo-round.png
|
|
565
555
|
social/
|
|
566
556
|
youtube.svg
|
|
567
557
|
screenshots/ # Real app screenshots from UI tests
|
|
568
558
|
01-home.png
|
|
569
|
-
|
|
559
|
+
assets/
|
|
570
560
|
styles.css # Tailwind input
|
|
571
561
|
icon.html # App icon template
|
|
572
562
|
logo.svg # Vector logo template
|