@open-assets/open-assets 0.1.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ian MacCallum
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,564 @@
1
+ # open-assets
2
+
3
+ Dev server and export tool for app marketing assets. Like Storybook, but for marketing assets.
4
+
5
+ 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
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ # Install
11
+ npm install --save-dev open-assets
12
+
13
+ # Scaffold a new project
14
+ npx open-assets init
15
+
16
+ # Start the dev server
17
+ npx open-assets dev
18
+ ```
19
+
20
+ ## Concepts
21
+
22
+ open-assets uses a simple, unified data model. Every asset type follows the same structure: **N templates × M export sizes**.
23
+
24
+ | Term | Definition |
25
+ |------|-----------|
26
+ | **Collection** | A named group of related assets sharing the same source size and export sizes. One tab in the dev UI. |
27
+ | **Template** | A single source file (HTML or SVG) that produces one image per export size. |
28
+ | **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
+ | **Source Size** | The dimensions the HTML template is authored at. Puppeteer scales from source → export size. |
31
+ | **Output** | An optional post-render action (e.g., write to Xcode `.appiconset`, copy SVG source). |
32
+
33
+ ## End-to-End Screenshot Pipeline
34
+
35
+ ### 1. Initialize
36
+
37
+ ```bash
38
+ npx open-assets init
39
+ ```
40
+
41
+ Creates a `manifest.json`, sample HTML templates, and a `public/` directory for shared assets.
42
+
43
+ ### 2. Design with Claude Code
44
+
45
+ Install the open-assets Claude skill, then prompt:
46
+
47
+ ```
48
+ Now we want to make beautiful screenshots for this app. Install the open-assets
49
+ skill from https://github.com/ianmaccallum/open-assets. Look at the marketing
50
+ doc and demographics. Design 8 high-converting App Store screenshots that catch
51
+ your eye as you scroll. Use bold headlines with highlighted keywords, phone
52
+ mockups with real app screenshots, and close with reviews + a CTA.
53
+ ```
54
+
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.
56
+
57
+ ### 3. Preview
58
+
59
+ ```bash
60
+ # With Tailwind
61
+ concurrently "npx @tailwindcss/cli -i src/styles.css -o dist/styles.css --watch" "npx open-assets dev"
62
+
63
+ # Without Tailwind
64
+ npx open-assets dev
65
+ ```
66
+
67
+ Opens a live preview UI at `http://localhost:3200` with zoom/pan controls and export buttons.
68
+
69
+ ### 4. Export
70
+
71
+ ```bash
72
+ npx open-assets render --all
73
+ ```
74
+
75
+ Exports every template at every configured export size into `./exports/`, organized as `exports/{collection}/{size}/{template}.png`.
76
+
77
+ ### 5. Upload to App Store Connect / Google Play
78
+
79
+ Upload the exported PNGs to App Store Connect or Google Play Console. Each size subdirectory maps to a device size required by the store.
80
+
81
+ ## Generating Screenshots from UI Tests
82
+
83
+ Capture real app screenshots via Playwright or XCTest, then use them inside your marketing screenshot templates:
84
+
85
+ ```bash
86
+ # 1. Run UI tests to capture app screenshots into public/screenshots/
87
+ npx playwright test --project=screenshots
88
+
89
+ # 2. Export marketing screenshots with those captures embedded
90
+ npx open-assets render --all
91
+ ```
92
+
93
+ Reference captured screenshots in your HTML templates:
94
+ ```html
95
+ <img src="../../public/screenshots/01-home.png" style="width: 100%; height: 100%; object-fit: cover;" />
96
+ ```
97
+
98
+ The `manifest.json` `command` field stores the export command so automation tools know what to run:
99
+ ```json
100
+ {
101
+ "command": "npx open-assets render --all"
102
+ }
103
+ ```
104
+
105
+ ## CLI Commands
106
+
107
+ ### `open-assets dev [dir]`
108
+
109
+ Start the dev server with a live preview UI and export controls.
110
+
111
+ ```bash
112
+ open-assets dev # Use current directory
113
+ open-assets dev ./screenshots # Use a specific directory
114
+ open-assets dev --port 4000 # Custom port (default: 3200)
115
+ open-assets dev --host 0.0.0.0 # Bind to all interfaces (network access)
116
+ open-assets dev --no-open # Don't auto-open browser
117
+ open-assets dev --quiet # Suppress server logs
118
+ open-assets dev --ci # CI mode (quiet + no browser)
119
+ open-assets dev --static-dir ./shared # Serve additional static directories
120
+ open-assets dev --manifest config.json # Use a custom manifest filename
121
+ ```
122
+
123
+ Options:
124
+ | Flag | Env Var | Default | Description |
125
+ |------|---------|---------|-------------|
126
+ | `-p, --port <port>` | `OPEN_ASSETS_PORT` | `3200` | Port to listen on |
127
+ | `-H, --host <host>` | `OPEN_ASSETS_HOST` | `localhost` | Host to bind to |
128
+ | `--no-open` | `OPEN_ASSETS_NO_OPEN` | — | Don't auto-open the browser |
129
+ | `-q, --quiet` | `OPEN_ASSETS_QUIET` | `false` | Suppress server logs |
130
+ | `--ci` | `CI` | `false` | CI mode: quiet + no browser |
131
+ | `--manifest <path>` | `OPEN_ASSETS_MANIFEST` | `manifest.json` | Path to manifest file |
132
+ | `--static-dir <dirs...>` | — | — | Additional static directories to serve |
133
+ | `--render-timeout <ms>` | `OPEN_ASSETS_RENDER_TIMEOUT` | `30000` | Puppeteer render timeout |
134
+
135
+ ### `open-assets render [dir]`
136
+
137
+ Render assets headlessly via the command line, without opening a browser.
138
+
139
+ ```bash
140
+ open-assets render # Render all collections at source size
141
+ open-assets render --all # Export at EVERY configured size
142
+ open-assets render --collection screenshots # Render a specific collection
143
+ open-assets render --template 01-hero # Render a single template
144
+ 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
+ open-assets render --width 1320 --height 2868 # Custom size
147
+ open-assets render --force # Re-render everything, ignore cache
148
+ open-assets render -o ./build # Custom output directory
149
+ open-assets render --json # Output results as JSON (for CI)
150
+ open-assets render --quiet # Suppress progress logs
151
+ ```
152
+
153
+ Options:
154
+ | Flag | Env Var | Default | Description |
155
+ |------|---------|---------|-------------|
156
+ | `--collection <id>` | — | all | Render only the collection with this ID |
157
+ | `--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 |
160
+ | `--width <px>` | — | — | Custom output width |
161
+ | `--height <px>` | — | — | Custom output height |
162
+ | `--all` | — | — | Export at every size defined in the manifest |
163
+ | `--force` | — | — | Re-render all assets even if unchanged |
164
+ | `-o, --output <dir>` | `OPEN_ASSETS_OUTPUT` | `./exports` | Output directory |
165
+ | `--manifest <path>` | `OPEN_ASSETS_MANIFEST` | `manifest.json` | Path to manifest file |
166
+ | `--parallel <count>` | `OPEN_ASSETS_PARALLEL` | `1` | Number of parallel renders |
167
+ | `--render-timeout <ms>` | `OPEN_ASSETS_RENDER_TIMEOUT` | `30000` | Puppeteer render timeout |
168
+ | `--json` | — | — | Output results as JSON |
169
+ | `-q, --quiet` | `OPEN_ASSETS_QUIET` | `false` | Suppress progress logs |
170
+
171
+ **Selective export** — flags compose naturally:
172
+ ```bash
173
+ # Single template at a single device size
174
+ open-assets render --collection screenshots --template 01-hero --size iphone-6.9
175
+
176
+ # One template at all device sizes
177
+ open-assets render --collection screenshots --template 01-hero --all
178
+
179
+ # All templates at one device size
180
+ 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
+ ```
185
+
186
+ **Output structure**: `exports/{collection}/{size}/{template}.png`
187
+ ```
188
+ exports/
189
+ screenshots/
190
+ iphone-6.9/
191
+ 01-hero.png
192
+ 02-features.png
193
+ iphone-6.7/
194
+ 01-hero.png
195
+ 02-features.png
196
+ icon/
197
+ 1024/
198
+ icon.png
199
+ 180/
200
+ icon.png
201
+ logo/
202
+ svg/
203
+ logo.svg
204
+ logo-dark.svg
205
+ 1024/
206
+ logo.png
207
+ logo-dark.png
208
+ ```
209
+
210
+ ### `open-assets list [dir]`
211
+
212
+ List all collections and templates defined in the manifest.
213
+
214
+ ```bash
215
+ open-assets list # Pretty-print asset tree
216
+ open-assets list --json # Output as JSON
217
+ ```
218
+
219
+ ### `open-assets validate [dir]`
220
+
221
+ Validate the manifest and check that all referenced source files exist.
222
+
223
+ ```bash
224
+ open-assets validate # Check current directory
225
+ open-assets validate ./assets # Check specific directory
226
+ ```
227
+
228
+ Returns exit code 1 if any errors are found — useful in CI pipelines.
229
+
230
+ ### `open-assets init [dir]`
231
+
232
+ Scaffold a new project with a `manifest.json`, sample HTML templates, and a `public/` directory.
233
+
234
+ ```bash
235
+ open-assets init # Current directory
236
+ open-assets init ./my-assets # Specific directory
237
+ ```
238
+
239
+ ## Manifest Format
240
+
241
+ Your project needs a `manifest.json` at its root. This file defines the collections shown in the viewer and all export options.
242
+
243
+ ```json
244
+ {
245
+ "version": 1,
246
+ "name": "My App",
247
+ "publicDir": "public",
248
+ "command": "npx open-assets render --all",
249
+ "collections": [ ... ]
250
+ }
251
+ ```
252
+
253
+ ### Root Fields
254
+
255
+ | Field | Type | Required | Description |
256
+ |-------|------|----------|-------------|
257
+ | `version` | number | yes | Manifest schema version (`1`) |
258
+ | `name` | string | yes | App display name |
259
+ | `publicDir` | string | no | Directory for shared assets (auto-served by dev server) |
260
+ | `command` | string | no | Export command for automation tools and CI |
261
+ | `collections` | array | yes | Asset collection definitions |
262
+
263
+ ### Collection Schema (Unified)
264
+
265
+ All collections follow the same structure. No `type` field needed.
266
+
267
+ ```json
268
+ {
269
+ "id": "screenshots",
270
+ "label": "App Store Screenshots",
271
+ "sourceSize": { "width": 440, "height": 956 },
272
+ "borderRadius": 4,
273
+ "templates": [
274
+ { "src": "src/screenshots/01-hero.html", "name": "01-hero", "label": "Hero" },
275
+ { "src": "src/screenshots/02-features.html", "name": "02-features", "label": "Features" }
276
+ ],
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
+ }
285
+ ],
286
+ "outputs": [
287
+ { "type": "xcode", "path": "../MyApp/Assets.xcassets/AppIcon.appiconset" }
288
+ ]
289
+ }
290
+ ```
291
+
292
+ | Field | Type | Description |
293
+ |-------|------|-------------|
294
+ | `id` | string | Unique collection identifier (used in CLI `--collection`) |
295
+ | `label` | string | Display name in the collection selector |
296
+ | `sourceSize` | object | `{ width, height }` — the dimensions templates are authored at |
297
+ | `borderRadius` | number | Border radius for preview frames (px) |
298
+ | `templates` | array | Source files to render |
299
+ | `templates[].src` | string | Path to HTML/SVG file (relative to project root) |
300
+ | `templates[].name` | string | Filename for exports (used by `--template` flag) |
301
+ | `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 }` |
305
+ | `outputs` | array | Optional post-render actions |
306
+ | `customExport` | object | Optional `{ defaultWidth, defaultHeight }` for custom size UI |
307
+
308
+ ### Output Types
309
+
310
+ | Type | Config | Description |
311
+ |------|--------|-------------|
312
+ | `xcode` | `{ "type": "xcode", "path": "..." }` | Render icon and write to Xcode asset catalog |
313
+ | `copy-source` | `{ "type": "copy-source", "format": "svg" }` | Copy source files to export directory |
314
+
315
+ ### Example Collections
316
+
317
+ **Screenshots** (8 templates × 4 iPhone sizes):
318
+ ```json
319
+ {
320
+ "id": "screenshots",
321
+ "label": "App Store Screenshots",
322
+ "sourceSize": { "width": 440, "height": 956 },
323
+ "borderRadius": 4,
324
+ "templates": [
325
+ { "src": "src/screenshots/01-hero.html", "name": "01-hero", "label": "Hero" },
326
+ { "src": "src/screenshots/02-import.html", "name": "02-import", "label": "Import" }
327
+ ],
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
+ }
338
+ ]
339
+ }
340
+ ```
341
+
342
+ **App Icon** (1 template × many Apple sizes + Xcode output):
343
+ ```json
344
+ {
345
+ "id": "icon",
346
+ "label": "App Icon",
347
+ "sourceSize": { "width": 1024, "height": 1024 },
348
+ "borderRadius": 224,
349
+ "templates": [
350
+ { "src": "src/icon.html", "name": "icon", "label": "App Icon" }
351
+ ],
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
+ }
361
+ ],
362
+ "outputs": [
363
+ { "type": "xcode", "path": "../MyApp/Assets.xcassets/AppIcon.appiconset" }
364
+ ]
365
+ }
366
+ ```
367
+
368
+ **Icon Explorations** (3 concept variants × preview sizes):
369
+ ```json
370
+ {
371
+ "id": "icon-explorations",
372
+ "label": "Icon Explorations",
373
+ "sourceSize": { "width": 1024, "height": 1024 },
374
+ "borderRadius": 224,
375
+ "templates": [
376
+ { "src": "src/icons/concept-a.html", "name": "concept-a", "label": "Concept A" },
377
+ { "src": "src/icons/concept-b.html", "name": "concept-b", "label": "Concept B" },
378
+ { "src": "src/icons/seasonal-winter.html", "name": "seasonal-winter", "label": "Winter" }
379
+ ],
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
+ }
387
+ ]
388
+ }
389
+ ```
390
+
391
+ **Logo** (3 variants + SVG source copy):
392
+ ```json
393
+ {
394
+ "id": "logo",
395
+ "label": "Logo",
396
+ "sourceSize": { "width": 940, "height": 940 },
397
+ "templates": [
398
+ { "src": "src/logo.svg", "name": "logo", "label": "Logo" },
399
+ { "src": "src/logo-dark.svg", "name": "logo-dark", "label": "Dark" },
400
+ { "src": "src/wordmark.svg", "name": "wordmark", "label": "Wordmark" }
401
+ ],
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
+ }
410
+ ],
411
+ "outputs": [
412
+ { "type": "copy-source", "format": "svg" }
413
+ ]
414
+ }
415
+ ```
416
+
417
+ **OG Images** (social cards):
418
+ ```json
419
+ {
420
+ "id": "og-images",
421
+ "label": "Social Cards",
422
+ "sourceSize": { "width": 1200, "height": 630 },
423
+ "templates": [
424
+ { "src": "src/og/default.html", "name": "default", "label": "Default OG" }
425
+ ],
426
+ "exportSizes": [
427
+ { "sizes": [{ "name": "og", "label": "OG Image", "width": 1200, "height": 630 }] }
428
+ ]
429
+ }
430
+ ```
431
+
432
+ **Favicons** (1 template × many sizes):
433
+ ```json
434
+ {
435
+ "id": "favicon",
436
+ "label": "Favicons",
437
+ "sourceSize": { "width": 512, "height": 512 },
438
+ "templates": [
439
+ { "src": "src/favicon.html", "name": "favicon", "label": "Favicon" }
440
+ ],
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
+ }
457
+ ]
458
+ }
459
+ ```
460
+
461
+ ## Incremental Builds with manifest.lock
462
+
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:
464
+
465
+ ```
466
+ $ open-assets render --all
467
+ Skipping 01-hero at 1320x2868 (unchanged)
468
+ Rendering 03-new-screen at 1320x2868...
469
+ → exports/screenshots/iphone-6.9/03-new-screen.png
470
+
471
+ Done. 1 asset(s) rendered, 1 skipped (unchanged) in 1.2s.
472
+ ```
473
+
474
+ Use `--force` to re-render everything regardless of the cache.
475
+
476
+ **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
+
478
+ Add `manifest.lock` to your `.gitignore` (done automatically by `open-assets init`).
479
+
480
+ ## CI/CD with GitHub Actions
481
+
482
+ Automatically export screenshots on push:
483
+
484
+ ```yaml
485
+ name: Export Marketing Assets
486
+ on:
487
+ push:
488
+ paths:
489
+ - 'marketing/screenshots/**'
490
+ - 'marketing/screenshots/manifest.json'
491
+ jobs:
492
+ export:
493
+ runs-on: ubuntu-latest
494
+ steps:
495
+ - uses: actions/checkout@v4
496
+ - uses: actions/setup-node@v4
497
+ with:
498
+ node-version: 20
499
+ - run: npm ci
500
+ - run: npx open-assets validate
501
+ - run: npx open-assets render --all --json --quiet
502
+ - uses: actions/upload-artifact@v4
503
+ with:
504
+ name: screenshots
505
+ path: exports/
506
+ ```
507
+
508
+ ## Common Export Sizes
509
+
510
+ | Platform | Label | Width | Height |
511
+ |----------|-------|-------|--------|
512
+ | App Store | iPhone 6.9" | 1320 | 2868 |
513
+ | App Store | iPhone 6.7" | 1290 | 2796 |
514
+ | App Store | iPhone 6.5" | 1284 | 2778 |
515
+ | App Store | iPhone 6.1" | 1179 | 2556 |
516
+ | App Store | iPad 12.9" | 2048 | 2732 |
517
+ | Play Store | Phone | 1080 | 1920 |
518
+ | Play Store | Phone (tall) | 1080 | 2400 |
519
+ | Product Hunt | Gallery | 1270 | 760 |
520
+ | Web | OG Image | 1200 | 630 |
521
+ | Mac App Store | Retina | 2880 | 1800 |
522
+
523
+ ## File Structure Convention
524
+
525
+ ```
526
+ project/
527
+ manifest.json
528
+ manifest.lock # Auto-generated cache (gitignored)
529
+ public/ # Shared assets (configured via publicDir)
530
+ logo-round.png
531
+ social/
532
+ youtube.svg
533
+ screenshots/ # Real app screenshots from UI tests
534
+ 01-home.png
535
+ src/
536
+ styles.css # Tailwind input
537
+ icon.html # App icon template
538
+ logo.svg # Vector logo template
539
+ icons/ # Icon concept explorations
540
+ concept-a.html
541
+ concept-b.html
542
+ screenshots/
543
+ 01-hero.html
544
+ 02-features.html
545
+ og/ # OG image templates
546
+ default.html
547
+ dist/
548
+ styles.css # Compiled Tailwind
549
+ exports/ # Rendered output (gitignored)
550
+ screenshots/
551
+ iphone-6.9/
552
+ 01-hero.png
553
+ iphone-6.7/
554
+ icon/
555
+ 1024/
556
+ icon.png
557
+ logo/
558
+ svg/
559
+ logo.svg
560
+ ```
561
+
562
+ ## License
563
+
564
+ MIT