@topy-ai/maggie 0.8.11 → 0.8.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.
@@ -66,6 +66,10 @@
66
66
  "name": "maggie-fundraising",
67
67
  "description": "Fundraising and investor relations for a founder - draft a pitch deck and narrative, assemble a data room, write investor updates, keep cap-table and round hygiene, and prepare SEIS/EIS materials. Use when the user asks to prepare to raise, build a deck or data room, write an investor update, or organise round documents. Factual only; not securities, investment, legal, or tax advice. Pairs with maggie-finance and the TOPY/CEO tools."
68
68
  },
69
+ {
70
+ "name": "maggie-image",
71
+ "description": "Process marketing images - resize and fit to channel/OG sizes, convert to WebP/AVIF, make favicon and OG-image sets, strip metadata, compress, optimize and render SVG, and build contact-sheet montages. A recipe generator over ImageMagick (primary) with dedicated tools (svgo/resvg/cwebp/avifenc/pngquant) used when installed. Use when the user wants to resize, convert, optimize, favicon, watermark, or batch-process images for a site or social post."
72
+ },
69
73
  {
70
74
  "name": "maggie-landing-page",
71
75
  "description": "Build a high-converting landing page - intake, page structure, layout selection, conversion copy, SEO/AEO, plus a visual-system discipline (typography, spacing, radius, backgrounds, hero, icons, motion) whose specific values are defaults the project's DESIGN.md overrides. Use when building, editing, styling, or writing copy for a landing page, marketing page, or a page section meant to convert. Designs the page; maggie-design produces and validates it."
@@ -2,7 +2,7 @@
2
2
  name: maggie-design
3
3
  description: Design authorized interior pages, review rendered responsive layouts, explicitly rebrand a packaged homepage/template, or audit and upgrade an existing site/app in place (fix generic AI-design patterns, weak states, and sloppy code). Use rebrand only with a named source brand and target brand. Use the redesign audit whenever the user wants to improve, polish, upgrade, refine, audit, or redesign an existing page, even when they just say it looks cheap, generic, or AI-made.
4
4
  metadata:
5
- version: 1.7.0
5
+ version: 1.7.1
6
6
  ---
7
7
 
8
8
  # Maggie Design
@@ -21,7 +21,12 @@ Concrete values come from
21
21
  overridden by the project's own DESIGN.md/tokens. For building a new landing page
22
22
  from scratch use [`maggie-landing-page`](../maggie-landing-page/SKILL.md); for
23
23
  turning a design into an animated showcase use
24
- [`maggie-design-motion`](../maggie-design-motion/SKILL.md).
24
+ [`maggie-design-motion`](../maggie-design-motion/SKILL.md). For page visuals and
25
+ assets: process images with [`maggie-image`](../maggie-image/SKILL.md)
26
+ ([recipes](../../references/image-recipes.md)), add motion from
27
+ [web animation patterns](../../references/web-animation-patterns.md), and generate
28
+ code-drawn backgrounds/3D/stylized art from
29
+ [generative visuals](../../references/generative-visuals.md).
25
30
 
26
31
  ## In-place route evidence
27
32
 
@@ -2,7 +2,7 @@
2
2
  name: maggie-design-motion
3
3
  description: Turn a static design (a Figma frame, screenshot, dashboard, card set, app screen, or a UI on a photo) into a pixel-exact HTML replica that loads from an empty state, then has every visual act out what it does in a seamless loop, and export an MP4 plus GIFs. Use when asked to animate a design, a Figma link, a screenshot, UI cards, a dashboard or hero image, or to make a showcase loop, motion mockup, or a video/GIF of a design. Also for bento/feature cards on a landing page.
4
4
  metadata:
5
- version: 0.1.1
5
+ version: 0.1.2
6
6
  ---
7
7
 
8
8
  # Maggie Design Motion
@@ -287,6 +287,9 @@ size/dimensions/fps/duration; anything not reproduced exactly, named plainly.
287
287
  - `maggie-spirit` - deterministic brand sprites/avatars (a different motion job).
288
288
  - `maggie-landing-page` / `maggie-design` - where website motion lives and is
289
289
  produced.
290
+ - [web animation patterns](../../references/web-animation-patterns.md) - the motion
291
+ vocabulary for the website context; [generative visuals](../../references/generative-visuals.md)
292
+ - code-drawn visuals you capture through this skill's Part C.
290
293
 
291
294
  # Credits
292
295
 
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: maggie-image
3
+ description: Process marketing images - resize and fit to channel/OG sizes, convert to WebP/AVIF, make favicon and OG-image sets, strip metadata, compress, optimize and render SVG, and build contact-sheet montages. A recipe generator over ImageMagick (primary) with dedicated tools (svgo/resvg/cwebp/avifenc/pngquant) used when installed. Use when the user wants to resize, convert, optimize, favicon, watermark, or batch-process images for a site or social post.
4
+ metadata:
5
+ version: 0.1.0
6
+ ---
7
+
8
+ # Maggie Image
9
+
10
+ The image-asset lane: turn a source image into the correctly-sized, correctly-
11
+ formatted, metadata-clean asset a site or social post needs. It is a **recipe
12
+ generator** like `maggie-video` - it prints the exact command (reviewable/loggable)
13
+ and runs it with `--run` when the tool is on PATH. It **invokes binaries at arm's
14
+ length** (no GPL code vendored).
15
+
16
+ This is image *processing*. For generating *new* visuals from a prompt see
17
+ `maggie media generate` (and the Q-category AI tools); for brand marks/avatars see
18
+ `maggie-spirit`; for generative/3D/stylized visuals see
19
+ [generative visuals](../../references/generative-visuals.md). Responsive-variant
20
+ manifests are `maggie_images.py` (a different concern).
21
+
22
+ Follow the [Maggie Memory Hook](../../references/memory-hook.md) at invocation and
23
+ completion.
24
+
25
+ ## When to use
26
+
27
+ - Resize/crop an image to a channel or OG size (1200x630, 1080x1080, 9:16, ...).
28
+ - Convert to WebP/AVIF for faster pages.
29
+ - Make a favicon set and OG/social images.
30
+ - Strip EXIF/GPS metadata, compress, or optimize before publishing.
31
+ - Optimize an SVG (svgo) or render one to PNG (resvg).
32
+ - Build a contact sheet / grid for a carousel.
33
+
34
+ ## Tool posture
35
+
36
+ ImageMagick (`magick` on IM7, else `convert`) is the primary path - almost always
37
+ present and covers nearly every raster op. Dedicated tools give better bytes-per-
38
+ quality and are used **automatically when installed**: `cwebp`/`avifenc` (encode),
39
+ `pngquant` (lossy PNG), `svgo` (SVG optimize), `resvg`/`rsvg-convert` (SVG render).
40
+ `--force-im` forces the ImageMagick path. Full commands are in
41
+ [image recipes](../../references/image-recipes.md).
42
+
43
+ ## CLI
44
+
45
+ ```bash
46
+ maggie tool maggie_image.py social --input hero.png --output og.jpg --preset og # 1200x630 cover-crop
47
+ maggie tool maggie_image.py resize --input a.jpg --output a.jpg --size 1080x1080 --mode cover
48
+ maggie tool maggie_image.py --run webp --input hero.png --output hero.webp --quality 80
49
+ maggie tool maggie_image.py --run avif --input hero.png --output hero.avif
50
+ maggie tool maggie_image.py --run favicon --input logo.png --out-dir public/
51
+ maggie tool maggie_image.py --run strip --input photo.jpg --output photo.jpg
52
+ maggie tool maggie_image.py --run compress --input big.jpg --output small.jpg --quality 82
53
+ maggie tool maggie_image.py svgo --input logo.svg --output logo.min.svg --multipass
54
+ maggie tool maggie_image.py svg2png --input logo.svg --output logo.png --width 512
55
+ maggie tool maggie_image.py --run montage --inputs a.png b.png c.png --output sheet.jpg --tile 3x
56
+ maggie tool maggie_image.py presets
57
+ ```
58
+
59
+ Subcommands: `resize`, `social`, `webp`, `avif`, `favicon`, `strip`, `compress`,
60
+ `svgo`, `svg2png`, `montage`, `presets`. `--run` (before the subcommand) executes
61
+ when the tool is present; otherwise the command is printed for review.
62
+
63
+ ## Defaults and quality
64
+
65
+ - Metadata **stripped** on public assets (privacy + bytes).
66
+ - JPEG/WebP quality ~80, AVIF ~50 (sharp/squoosh web-delivery defaults).
67
+ - OG/social are **cover-cropped** (fill, no distortion); logos **contain-pad**.
68
+ - Favicon: `.ico` (64/48/32/16) + PNG set (16/32/48/180-apple-touch/192/512).
69
+ - SVG: svgo keeps `viewBox` and `title` (responsive + accessible); never rasterize an
70
+ SVG as a substitute for optimizing it.
71
+
72
+ ## Quality bar
73
+
74
+ - Output is the exact target size with no distortion; cover vs pad chosen for the
75
+ content (photos crop, logos pad).
76
+ - Public images carry no EXIF/GPS; file sizes are web-appropriate (WebP/AVIF offered).
77
+ - SVGs stay vector and keep `viewBox`; a rendered PNG is only made on request.
78
+ - Every command is printed/logged before (or instead of) running.
79
+
80
+ ## Guardrails
81
+
82
+ - Local tools only; invoke `convert`/`magick` and dedicated binaries at arm's length;
83
+ never vendor GPL/AGPL code (e.g. Upscayl is AGPL - for AI upscaling invoke the
84
+ separate `realesrgan-ncnn-vulkan` binary instead).
85
+ - Do not claim a file was produced unless `--run` executed and it exists.
86
+ - Do not upscale/alter a logo or product shot in a way that misrepresents it; keep
87
+ brand assets faithful.
88
+ - Reproducing copyrighted or third-party imagery is the caller's responsibility.
89
+
90
+ ## Related skills
91
+
92
+ - `maggie-video` - the moving-image counterpart (same recipe-generator pattern).
93
+ - `maggie-spirit` - brand marks/avatars; `maggie-design` - where assets are placed
94
+ and the icon/responsive gates run.
95
+ - `maggie media generate` - generating new images from a prompt.
96
+ - [generative visuals](../../references/generative-visuals.md) - making visuals in code.
97
+
98
+ ## Boundaries
99
+
100
+ - Processing and optimization only; generation and placement live in other lanes.
@@ -2,7 +2,7 @@
2
2
  name: maggie-landing-page
3
3
  description: Build a high-converting landing page - intake, page structure, layout selection, conversion copy, SEO/AEO, plus a visual-system discipline (typography, spacing, radius, backgrounds, hero, icons, motion) whose specific values are defaults the project's DESIGN.md overrides. Use when building, editing, styling, or writing copy for a landing page, marketing page, or a page section meant to convert. Designs the page; maggie-design produces and validates it.
4
4
  metadata:
5
- version: 0.1.1
5
+ version: 0.1.2
6
6
  ---
7
7
 
8
8
  # Maggie Landing Page
@@ -156,6 +156,10 @@ icon inventory + glyph-render gates before release.
156
156
 
157
157
  ## B7. Motion
158
158
 
159
+ The motion vocabulary (eases, scroll-reveal, stagger, SVG draw-on, typing, page
160
+ transitions, Lottie, particles) with per-library guidance is in
161
+ [web animation patterns](../../references/web-animation-patterns.md).
162
+
159
163
  Weighted, decelerating motion; never a browser-default curve. Default base curve
160
164
  `cubic-bezier(0.22,1,0.36,1)` ~500ms for layout/position; 300ms (never under 200ms)
161
165
  for hover colour/opacity. Animate only `transform`/`opacity`. Respect
@@ -2,7 +2,7 @@
2
2
  name: maggie-spirit
3
3
  description: Generate an AI brand's flat-pixel spirit (sprite) system - a logo mark that animates through a fixed 32-state base set, and per-agent avatar faces animated through the same states. Use for agent/brand avatars, logo marks, sprite-sheet and sprite-animation assets, and a shared motion vocabulary across Core and Service agents.
4
4
  metadata:
5
- version: 0.1.0
5
+ version: 0.1.1
6
6
  ---
7
7
 
8
8
  # Maggie Spirit
@@ -14,7 +14,9 @@ states** (power, work, comms, outcome, gov). Agents differ only by their
14
14
  and status badges stay identical so a state reads the same everywhere.
15
15
 
16
16
  Everything is deterministic (seeded by accent + persona) and self-contained
17
- (Pillow only - no model calls, no per-image cost). It pairs with
17
+ (Pillow only - no model calls, no per-image cost). For code-drawn generative
18
+ visuals (backgrounds, 3D, stylized photos) beyond the brand mark, see
19
+ [generative visuals](../../references/generative-visuals.md). It pairs with
18
20
  [agent goal-led design](../../references/agent-goal-design.md): design the agent,
19
21
  then give it a spirit.
20
22
 
@@ -2,7 +2,7 @@
2
2
  name: maggie-video
3
3
  description: Produce and process marketing video - render a composition to MP4/GIF/WebM, assemble clips/images/text/captions/audio on a timeline, cut to channel aspects (reel/square/youtube), burn in captions, normalize loudness, watermark, transcode, and make social cuts. Engine-neutral over the renderer (ffmpeg for assembly/transcode, a programmatic engine for code-drawn animation). Use when the user wants to make, edit, cut, caption, resize, or export a video for marketing.
4
4
  metadata:
5
- version: 0.1.3
5
+ version: 0.1.4
6
6
  ---
7
7
 
8
8
  # Maggie Video
@@ -92,7 +92,8 @@ paid API):
92
92
  toggleable track.
93
93
 
94
94
  Never fabricate a transcript; generate it from the real audio and have a human
95
- review before publishing.
95
+ review before publishing. Engine choice and the full flow are in
96
+ [captions and transcription](../../references/captions-transcription.md).
96
97
 
97
98
  ## Channel presets and safe areas
98
99
 
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env python3
2
+ """maggie_image - generate correct image-processing commands for marketing assets.
3
+
4
+ A recipe generator distilled from ImageMagick, sharp, svgo, resvg, squoosh and
5
+ imagemin (see references/image-recipes.md). Each subcommand prints the exact command
6
+ (reviewable/loggable) and runs it with --run only when the tool is on PATH. Raster
7
+ ops prefer ImageMagick (`magick` on IM7, else `convert`) since it is almost always
8
+ present and covers nearly everything; vector ops use the dedicated tool (svgo, resvg)
9
+ and are generate-only until it is installed. Web-delivery quality defaults follow
10
+ sharp/squoosh (JPEG/WebP ~80, AVIF ~50); OG/social are cover-cropped, logos pad.
11
+
12
+ Subcommands: resize, social, webp, avif, favicon, strip, compress, svgo, svg2png,
13
+ montage, presets.
14
+ """
15
+ import argparse
16
+ import shlex
17
+ import shutil
18
+ import subprocess
19
+ import sys
20
+
21
+ # OG/social use cover-crop; name -> (W, H)
22
+ SOCIAL = {"og": (1200, 630), "twitter": (1600, 900), "square": (1080, 1080),
23
+ "story": (1080, 1920), "reel": (1080, 1920), "landscape": (1920, 1080),
24
+ "linkedin": (1200, 627), "pinterest": (1000, 1500)}
25
+ FAVICON_PNG = [16, 32, 48, 180, 192, 512] # 180 = apple-touch
26
+
27
+
28
+ def _im():
29
+ return ["magick"] if shutil.which("magick") else ["convert"]
30
+
31
+
32
+ def _im_tool():
33
+ return _im()[0]
34
+
35
+
36
+ def _montage():
37
+ return ["magick", "montage"] if shutil.which("magick") else ["montage"]
38
+
39
+
40
+ def emit(args, run, tool):
41
+ print(" ".join(shlex.quote(a) for a in args))
42
+ if not run:
43
+ return 0
44
+ if not shutil.which(tool):
45
+ sys.stderr.write(f"{tool} not found on PATH; printed the command only.\n")
46
+ return 3
47
+ return subprocess.run(args).returncode
48
+
49
+
50
+ def _resize_ops(w, h, mode, pad):
51
+ if mode == "cover":
52
+ return ["-resize", f"{w}x{h}^", "-gravity", "center", "-extent", f"{w}x{h}"]
53
+ if mode == "contain":
54
+ return ["-resize", f"{w}x{h}", "-background", pad, "-gravity", "center", "-extent", f"{w}x{h}"]
55
+ if mode == "shrink":
56
+ return ["-resize", f"{w}x{h}>"]
57
+ return ["-resize", f"{w}x{h}"] # fit
58
+
59
+
60
+ def c_resize(a):
61
+ w, h = a.size.lower().split("x")
62
+ cmd = _im() + [a.input, "-strip"] + _resize_ops(w, h, a.mode, a.pad) + \
63
+ ["-quality", str(a.quality), a.output]
64
+ return emit(cmd, a.run, _im_tool())
65
+
66
+
67
+ def c_social(a):
68
+ w, h = SOCIAL[a.preset]
69
+ cmd = _im() + [a.input, "-strip"] + _resize_ops(w, h, a.mode, a.pad) + \
70
+ ["-quality", str(a.quality), a.output]
71
+ return emit(cmd, a.run, _im_tool())
72
+
73
+
74
+ def c_webp(a):
75
+ if shutil.which("cwebp") and not a.force_im:
76
+ return emit(["cwebp", "-q", str(a.quality), "-m", "6", a.input, "-o", a.output], a.run, "cwebp")
77
+ cmd = _im() + [a.input, "-strip", "-quality", str(a.quality), "-define", "webp:method=6", a.output]
78
+ return emit(cmd, a.run, _im_tool())
79
+
80
+
81
+ def c_avif(a):
82
+ if shutil.which("avifenc") and not a.force_im:
83
+ return emit(["avifenc", "-s", "6", "--min", "20", "--max", "40", a.input, a.output], a.run, "avifenc")
84
+ cmd = _im() + [a.input, "-strip", "-quality", str(a.quality), a.output]
85
+ return emit(cmd, a.run, _im_tool())
86
+
87
+
88
+ def c_favicon(a):
89
+ import os
90
+ os.makedirs(a.out_dir, exist_ok=True)
91
+ rc = 0
92
+ ico = os.path.join(a.out_dir, "favicon.ico")
93
+ rc |= emit(_im() + [a.input, "-define", "icon:auto-resize=64,48,32,16", ico], a.run, _im_tool())
94
+ for s in FAVICON_PNG:
95
+ name = "apple-touch-icon.png" if s == 180 else f"favicon-{s}.png"
96
+ out = os.path.join(a.out_dir, name)
97
+ rc |= emit(_im() + [a.input, "-strip", "-resize", f"{s}x{s}", out], a.run, _im_tool())
98
+ return rc
99
+
100
+
101
+ def c_strip(a):
102
+ return emit(_im() + [a.input, "-strip", a.output], a.run, _im_tool())
103
+
104
+
105
+ def c_compress(a):
106
+ out = a.output.lower()
107
+ if out.endswith((".jpg", ".jpeg")):
108
+ cmd = _im() + [a.input, "-strip", "-interlace", "Plane", "-quality", str(a.quality), a.output]
109
+ else: # png: palette-reduce + max zlib (pngquant is the better alt)
110
+ if shutil.which("pngquant") and not a.force_im:
111
+ return emit(["pngquant", "--quality", "60-82", "--strip", "--force",
112
+ "--output", a.output, a.input], a.run, "pngquant")
113
+ cmd = _im() + [a.input, "-strip", "-colors", "256",
114
+ "-define", "png:compression-level=9", a.output]
115
+ return emit(cmd, a.run, _im_tool())
116
+
117
+
118
+ def c_svgo(a):
119
+ args = ["svgo", "--multipass"] if a.multipass else ["svgo"]
120
+ args += ["-i", a.input, "-o", a.output]
121
+ print("# svgo keeps viewBox and title by default (responsive + accessible).")
122
+ if not shutil.which("svgo"):
123
+ print("# svgo not installed (npm i -g svgo). Do NOT rasterize an SVG as a substitute.")
124
+ return emit(args, a.run, "svgo")
125
+
126
+
127
+ def c_svg2png(a):
128
+ if shutil.which("resvg") and not a.force_im:
129
+ args = ["resvg"]
130
+ if a.width:
131
+ args += ["-w", str(a.width)]
132
+ if a.background:
133
+ args += ["--background", a.background]
134
+ args += [a.input, a.output]
135
+ return emit(args, a.run, "resvg")
136
+ if shutil.which("rsvg-convert") and not a.force_im:
137
+ args = ["rsvg-convert"]
138
+ if a.width:
139
+ args += ["-w", str(a.width)]
140
+ return emit(args + [a.input, "-o", a.output], a.run, "rsvg-convert")
141
+ # ImageMagick fallback: drive size via -density (it rasterizes at DPI); lower fidelity
142
+ dens = 384
143
+ bg = ["-background", a.background] if a.background else ["-background", "none"]
144
+ size = ["-resize", f"{a.width}x"] if a.width else []
145
+ print("# ImageMagick SVG fallback is lower fidelity; install resvg for correct rendering.")
146
+ return emit(_im() + bg + ["-density", str(dens), a.input] + size + [a.output], a.run, _im_tool())
147
+
148
+
149
+ def c_montage(a):
150
+ cmd = _montage() + list(a.inputs) + ["-tile", a.tile, "-geometry",
151
+ f"{a.cell}+{a.pad}+{a.pad}", "-background", a.background, a.output]
152
+ return emit(cmd, a.run, _montage()[0])
153
+
154
+
155
+ def c_presets(a):
156
+ print("Social/OG size presets (use with `social --preset <name>`; cover-cropped):")
157
+ for name, (w, h) in SOCIAL.items():
158
+ print(f" {name:<10} {w}x{h}")
159
+ print("\nDefaults: strip metadata; JPEG/WebP quality 80, AVIF 50; favicon .ico "
160
+ "(64/48/32/16) + PNG set (16/32/48/180-apple/192/512).")
161
+ print(f"ImageMagick binary detected: {_im_tool()}")
162
+ return 0
163
+
164
+
165
+ def main(argv=None):
166
+ ap = argparse.ArgumentParser(prog="maggie_image", description=__doc__,
167
+ formatter_class=argparse.RawDescriptionHelpFormatter)
168
+ ap.add_argument("--run", action="store_true", help="execute (needs the tool on PATH); default prints only")
169
+ ap.add_argument("--force-im", action="store_true", dest="force_im",
170
+ help="force the ImageMagick path even if a dedicated tool exists")
171
+ sub = ap.add_subparsers(dest="cmd", required=True)
172
+
173
+ def io(p, out=True):
174
+ p.add_argument("--input", required=True)
175
+ if out:
176
+ p.add_argument("--output", required=True)
177
+
178
+ r = sub.add_parser("resize", help="resize+fit to WxH")
179
+ io(r); r.add_argument("--size", required=True, help="WxH, e.g. 1200x630")
180
+ r.add_argument("--mode", choices=["cover", "contain", "fit", "shrink"], default="cover")
181
+ r.add_argument("--pad", default="#ffffff"); r.add_argument("--quality", type=int, default=82)
182
+ r.set_defaults(fn=c_resize)
183
+
184
+ s = sub.add_parser("social", help="resize to a channel/OG preset")
185
+ io(s); s.add_argument("--preset", choices=list(SOCIAL), required=True)
186
+ s.add_argument("--mode", choices=["cover", "contain", "fit", "shrink"], default="cover")
187
+ s.add_argument("--pad", default="#ffffff"); s.add_argument("--quality", type=int, default=82)
188
+ s.set_defaults(fn=c_social)
189
+
190
+ w = sub.add_parser("webp", help="encode WebP"); io(w)
191
+ w.add_argument("--quality", type=int, default=80); w.set_defaults(fn=c_webp)
192
+ av = sub.add_parser("avif", help="encode AVIF"); io(av)
193
+ av.add_argument("--quality", type=int, default=50); av.set_defaults(fn=c_avif)
194
+
195
+ fv = sub.add_parser("favicon", help="favicon .ico + PNG set")
196
+ fv.add_argument("--input", required=True); fv.add_argument("--out-dir", dest="out_dir", required=True)
197
+ fv.set_defaults(fn=c_favicon)
198
+
199
+ st = sub.add_parser("strip", help="strip metadata (EXIF/GPS/ICC)"); io(st); st.set_defaults(fn=c_strip)
200
+ co = sub.add_parser("compress", help="compress JPEG/PNG"); io(co)
201
+ co.add_argument("--quality", type=int, default=82); co.set_defaults(fn=c_compress)
202
+
203
+ so = sub.add_parser("svgo", help="optimize an SVG (svgo)"); io(so)
204
+ so.add_argument("--multipass", action="store_true"); so.set_defaults(fn=c_svgo)
205
+ sp = sub.add_parser("svg2png", help="render SVG -> PNG (resvg)"); io(sp)
206
+ sp.add_argument("--width", type=int); sp.add_argument("--background"); sp.set_defaults(fn=c_svg2png)
207
+
208
+ mo = sub.add_parser("montage", help="contact sheet / grid")
209
+ mo.add_argument("--inputs", nargs="+", required=True); mo.add_argument("--output", required=True)
210
+ mo.add_argument("--tile", default="3x"); mo.add_argument("--cell", default="400x400")
211
+ mo.add_argument("--pad", type=int, default=10); mo.add_argument("--background", default="#ffffff")
212
+ mo.set_defaults(fn=c_montage)
213
+
214
+ sub.add_parser("presets", help="list size presets").set_defaults(fn=c_presets)
215
+
216
+ a = ap.parse_args(argv)
217
+ raise SystemExit(a.fn(a))
218
+
219
+
220
+ if __name__ == "__main__":
221
+ main()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topy-ai/maggie",
3
- "version": "0.8.11",
3
+ "version": "0.8.12",
4
4
  "description": "Install and manage Maggie Skills for AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -0,0 +1,41 @@
1
+ # Captions and transcription
2
+
3
+ Local, offline speech-to-text for video captions and transcripts, used by
4
+ `maggie-video`'s `captions` subcommand. All engines run on the user's machine - **no
5
+ paid API** - so transcription has no per-minute cost, only local CPU/GPU time.
6
+ Distilled from the reference library's R-category projects.
7
+
8
+ ## Engines
9
+
10
+ | Engine | What / how | License | Reach for it when |
11
+ |---|---|---|---|
12
+ | openai-whisper | The reference Python CLI: `whisper IN --model base --output_format srt --output_dir DIR` | MIT | the default; simplest install (`pip install openai-whisper`) |
13
+ | whisper.cpp | C/C++ port, fast on CPU, GGML models: `whisper-cli -m model.bin -f IN -osrt -of OUTBASE` | MIT | no GPU / fastest CPU / embedding in a pipeline |
14
+ | whisperX | whisper + forced alignment for **word-level timestamps** and diarization: `whisperx IN --model large-v3 --output_format srt --output_dir DIR` | BSD-4 | word-accurate caption timing or speaker labels |
15
+
16
+ Model size trades speed for accuracy: `tiny` / `base` (fast, rough) -> `small` /
17
+ `medium` -> `large-v3` (slow, best). Use `--lang` to skip auto-detect when known.
18
+
19
+ ## Workflow (voiceover -> captions -> on-screen)
20
+
21
+ 1. **Transcribe** the voiceover or the video's audio to SRT with a local engine
22
+ (`maggie_video.py captions --input vo.mp3 --output vo.srt --engine whisper
23
+ --model base`). A larger model is slower but more accurate.
24
+ 2. **Review** the SRT - never ship an unreviewed transcript; whisper mishears names,
25
+ numbers, and brand terms. A human edits it.
26
+ 3. **Put it on screen**, one of:
27
+ - burn in (`maggie_video.py subtitle --input video.mp4 --srt vo.srt --output out.mp4`),
28
+ - soft-mux a toggleable track (`subtitle --soft`), or
29
+ - a `captions` layer in a `maggie_video.py compile` timeline (see
30
+ [video timeline model](video-timeline-model.md)).
31
+
32
+ ## Rules
33
+
34
+ - Captions lift watch time and serve sound-off viewing - caption every social video.
35
+ - **Never fabricate a transcript**; generate it from the real audio and have a human
36
+ review before publishing (accuracy, names, and brand terms).
37
+ - Local/offline: no audio leaves the machine, no paid API. If a hosted transcription
38
+ API is ever wired in instead, the global spend-first rule applies - state the cost.
39
+ - Keep caption text inside the safe area (see `maggie-video` channel presets).
40
+
41
+ See `maggie-video` for the subcommands and the burn-in / soft-mux / compile options.
@@ -0,0 +1,90 @@
1
+ # Generative visuals (creative coding)
2
+
3
+ Patterns for generating marketing visuals in code - hero backgrounds, textures, 3D
4
+ product shots, data-viz, and stylized images - distilled from the leading creative-
5
+ coding libraries. We adopt **patterns, not code**. Output becomes a deliverable as a
6
+ **still** (canvas/SVG export) or a **loop** (captured via
7
+ [design-motion production](design-motion-production.md) Part C or
8
+ [ffmpeg recipes](ffmpeg-recipes.md), then assembled in `maggie-video`). Determinism
9
+ by seeding matches `maggie-spirit`'s philosophy: same seed -> same pixels.
10
+
11
+ ## Libraries
12
+
13
+ | Library | What / model | Lang | License | Marketing fit |
14
+ |---|---|---|---|---|
15
+ | three.js | WebGL 3D: Scene + Camera + WebGLRenderer; `renderer.render(scene,camera)` in a loop | JS | MIT | 3D product spins, logo stings, depth-y hero backgrounds |
16
+ | Babylon.js | Higher-level 3D engine (PBR, asset pipeline); heavier | JS/TS | Apache-2.0 | 3D product config; alt to three when its pipeline earns the weight |
17
+ | react-three-fiber | three.js as React JSX (`<mesh><boxGeometry/>…`), `useFrame` | JS/TS | MIT | 3D on a React site |
18
+ | p5.js | Canvas sketch: `setup()` once + `draw()` per frame; `random()/noise()` with `randomSeed()/noiseSeed()` | JS | **LGPL-2.1** | generative hero backgrounds, flow fields, noise art |
19
+ | paper.js | Vector scene graph (Path/Group), boolean ops, hit-testing | JS | MIT | editable vector hero art, print-quality SVG |
20
+ | two.js | One 2D API across SVG/Canvas/WebGL renderers | JS | MIT | vector art you want to export as SVG or capture from canvas |
21
+ | rough.js | Hand-drawn/sketchy shapes; `{seed}` = reproducible | JS/TS | MIT | approachable hand-made brand style, doodle accents |
22
+ | zdog | Pseudo-3D round/flat vector, designer-friendly | JS | MIT | cute 3D-ish icons, mascot/logo spins |
23
+ | pts | Computational geometry (Space + Form + Pt) | TS/JS | Apache-2.0 | geometric/particle hero art |
24
+ | hydra | Live-coded video synth (chained GLSL ops) | JS | **AGPL-3.0** | trippy animated backgrounds - **pattern only, do not ship its code** |
25
+ | regl | Functional WebGL (stateless draw commands) | JS | MIT | custom shader backgrounds/gradients when three is overkill |
26
+ | d3 | Data-driven SVG (scales + selections) | JS | ISC | bespoke infographics - but defer standard charts to the `dataviz` skill |
27
+ | fogleman/primitive | Reproduce an image with N geometric primitives (CLI) | Go | MIT | stylize a product photo into abstract art (still or GIF) |
28
+ | svg.js | Lightweight SVG DOM manipulation | JS | MIT | programmatic SVG icons/badges/dividers |
29
+ | nannou | Rust creative framework (desktop) | Rust | MIT/Apache | note only - high-perf generative art in Rust |
30
+
31
+ **License flags:** hydra is **AGPL-3.0**, p5 is **LGPL-2.1**, processing (non-core)
32
+ is GPL - fine as *idea* sources, but do not vendor their code into shipped product;
33
+ reimplement the pattern or use an MIT equivalent (two.js / pts / regl / svg.js).
34
+
35
+ ## Patterns and the deliverable path
36
+
37
+ - **2D generative** (p5 / paper / two / rough / zdog / pts / svg.js): `setup()` once +
38
+ `draw()`/`update()` per frame. Use for brand-tinted hero/section backgrounds,
39
+ textures, doodle accents, geometric motifs. **Still:** SVG-capable libs serialize
40
+ their `<svg>` (crisp, editable, print-ready); canvas libs use `canvas.toDataURL()`
41
+ -> PNG. **Loop:** run the sketch headless and capture via design-motion Part C, or
42
+ in-browser with CCapture.js (MIT), then hand to `maggie-video`.
43
+ - **3D** (three / babylon / r3f): Scene + Camera + Renderer; animate by frame index.
44
+ Product spins, 3D logo stings, depth-y backgrounds. **Still:**
45
+ `renderer.domElement.toDataURL()` (set `preserveDrawingBuffer:true`); **loop:** drive
46
+ by frame, capture as above. Prefer three/r3f (MIT); babylon only when needed.
47
+ - **Data-viz** (d3): `d3-scale` + `d3-selection`; SVG is the native output. For
48
+ standard charts, **defer to the `dataviz` skill** (its palette/spec); pull in d3
49
+ only for bespoke marks (arc diagrams, force layouts, custom infographics).
50
+ - **Live visuals** (hydra): chained feedback-graph ops -> animated GLSL. Renders to a
51
+ canvas -> capture -> `maggie-video`. **AGPL: idea only**; for an MIT shader
52
+ background use regl.
53
+ - **Image -> primitives** (fogleman/primitive, MIT, Go CLI): stylize a photo into
54
+ abstract geometry.
55
+
56
+ ```bash
57
+ primitive -i input.png -o output.svg -n 100 -m 1
58
+ # -n shapes (50-200); -m mode (1 triangle,2 rect,3 ellipse,4 circle,6 beziers,8 polygon);
59
+ # output type by extension: PNG/JPG (raster), SVG (vector), GIF (animated, needs ImageMagick)
60
+ ```
61
+
62
+ **Still:** PNG/SVG directly; **loop:** `.gif` or `%d`-numbered PNG frames ->
63
+ `maggie-video`. It is randomized (no seed): generate once and **store the artifact**;
64
+ do not regenerate on every build.
65
+
66
+ ## Determinism
67
+
68
+ p5 `randomSeed()/noiseSeed()`, rough.js `{seed}`, and a seeded PRNG in place of
69
+ `Math.random` give byte-reproducible stills; the frame-index/virtual-clock rule from
70
+ [programmatic video](programmatic-video.md) gives reproducible motion. `primitive`
71
+ and `hydra` are non-deterministic - capture and store their output as a fixed asset.
72
+
73
+ ## Placement
74
+
75
+ - **maggie-spirit** owns seeded brand marks/characters; borrow the 2D-canvas sketch
76
+ model and seed discipline for flat-vector mark construction (zdog/two.js/rough).
77
+ Generative *backgrounds/scenes* do not live here.
78
+ - **maggie-design** owns generative hero backgrounds, section textures, 3D product
79
+ shots and image stylization as page/brand visuals; it points at this reference and
80
+ cross-links design-motion / `maggie-video` for capture-to-deliverable.
81
+ - **Reference-only:** d3 (defer to `dataviz`), hydra (AGPL, idea only), regl, babylon,
82
+ nannou/processing/openFrameworks (desktop notes), svg.js.
83
+
84
+ ## Credits
85
+
86
+ Patterns adapted (not code) from three.js, p5.js, d3, paper.js, two.js, rough.js,
87
+ zdog, pts, hydra, regl, Babylon.js, react-three-fiber, fogleman/primitive, svg.js,
88
+ nannou - licenses in the table above. Capture pipeline: see
89
+ [programmatic video](programmatic-video.md), [design-motion production](design-motion-production.md),
90
+ [ffmpeg recipes](ffmpeg-recipes.md).