$npx -y skills add Varnan-Tech/opendirectory --skill graphic-gifCreates animated looping GIFs from CSS animations (default) or AI image-to-video. 800×800px default, 6 animation types, 4 style presets. Trigger when user says "create an animated gif", "make a looping gif", "animated banner", "CSS animation gif", "social media animation", "make
| 1 | # graphic-gif |
| 2 | |
| 3 | Generates an animated looping GIF from CSS animations or an AI image-to-video API. Output: `animation.gif`. |
| 4 | |
| 5 | Unlike every other `graphic-` skill that outputs a static PNG or PDF, this skill outputs an animated `.gif`. Uses CSS `@keyframes` animations captured frame-by-frame via Playwright and the Web Animations API (Option A, default), or an AI image-to-video pipeline via Kling (Option B). |
| 6 | |
| 7 | --- |
| 8 | |
| 9 | ## Critical Rules (read before every generation) |
| 10 | |
| 11 | 1. **Default is css-animated.** Never use `ai-generated` unless explicitly requested. |
| 12 | 2. **Canvas is 800×800px square.** All `clamp()` values computed at 800px (1vw = 8px). |
| 13 | 3. **Single self-contained HTML.** All CSS inline in `<style>`. Font CDN `<link>` only external dependency. |
| 14 | 4. **Never dump HTML in chat.** Save to file, show summary only. |
| 15 | 5. **Frame capture uses Web Animations API seeking.** NOT `setTimeout` loops, NOT `animation-delay` tricks. |
| 16 | 6. **Exact frame count:** `Math.floor(duration_seconds * fps)` frames. The frame at `t=duration_ms` MUST NOT be captured — it duplicates `t=0` and causes a visible stutter at the loop point. |
| 17 | 7. **No placeholder boxes.** CSS-generated visuals only. No "image goes here" elements. |
| 18 | 8. **Simpler palettes = smaller files.** Use: `clean-slate`, `terminal`, `electric-burst`, `brutalist`. |
| 19 | 9. **No animation-delay for stagger.** Bake stagger into `@keyframes` percentages — frame seeking handles timing. |
| 20 | 10. **Commit to design direction before writing CSS.** Tone, signature element, motion style, unforgettable detail — all decided before first line of code. |
| 21 | |
| 22 | --- |
| 23 | |
| 24 | ## Step 1: Intake |
| 25 | |
| 26 | **Required:** `prompt` (content description AND motion brief) |
| 27 | |
| 28 | **Optional with defaults:** |
| 29 | |
| 30 | | Parameter | Default | Options | |
| 31 | |---|---|---| |
| 32 | | animation_type | css-animated | css-animated / ai-generated | |
| 33 | | duration | 3.0 | seconds | |
| 34 | | fps | 12 | frames per second | |
| 35 | | loop | true | true / false | |
| 36 | | style | clean-slate | clean-slate / terminal / electric-burst / brutalist | |
| 37 | | dimensions | 800x800 | WxH in pixels | |
| 38 | | optimization | balanced | quality / balanced / filesize | |
| 39 | |
| 40 | **If prompt is missing or lacks motion description, ask exactly:** |
| 41 | |
| 42 | > "What should the GIF show? Describe the content AND the motion (e.g., 'Stats count up: 73% of buyers read 3+ pieces of content before purchase. Typewriter effect, one character at a time. Style: terminal. 3 seconds, 12fps.') |
| 43 | > |
| 44 | > Key settings (all optional, defaults shown): |
| 45 | > - animation_type: css-animated (default) or ai-generated |
| 46 | > - duration: 3.0 seconds |
| 47 | > - fps: 12 |
| 48 | > - loop: true |
| 49 | > - style: clean-slate (options: clean-slate / terminal / electric-burst / brutalist) |
| 50 | > - dimensions: 800x800 |
| 51 | > - optimization: balanced (options: quality / balanced / filesize)" |
| 52 | |
| 53 | If all required info is present → skip directly to Step 2. |
| 54 | |
| 55 | --- |
| 56 | |
| 57 | ## Step 2: Internal Architecture (never shown to user) |
| 58 | |
| 59 | **For css-animated:** |
| 60 | |
| 61 | 1. Choose animation type from: `fade-in`, `slide-in`, `typewriter`, `counter`, `pulse`, `loop-scroll` |
| 62 | 2. Read `references/animation-library.md` — find the chosen type's full HTML/CSS spec |
| 63 | 3. Read `references/style-presets.md` — load the chosen style's CSS token block |
| 64 | 4. Calculate frame count: `Math.floor(duration_seconds * fps)` — write this number down |
| 65 | 5. Commit to design direction: |
| 66 | |
| 67 | | Decision | Derive from | |
| 68 | |---|---| |
| 69 | | Tone | Emotional register for audience (mechanical / warm / electric / professional) | |
| 70 | | Signature element | ONE visual device used consistently (cursor blink, ghost number, scan-line overlay, accent border) | |
| 71 | | Motion style | Ease curve philosophy for this type (spring / linear / step / ease-in-out) | |
| 72 | | Unforgettable detail | The ONE thing a viewer will remember about this GIF | |
| 73 | |
| 74 | **For ai-generated:** |
| 75 | 1. Generate base still frame HTML (poster-style layout for the canvas) |
| 76 | 2. Export as PNG using screenshot |
| 77 | 3. Call Kling API: `POST https://api.klingai.com/v1/videos/image2video` with `image_url` and `prompt` describing the motion |
| 78 | 4. Poll for job completion |
| 79 | 5. Download video → convert to GIF with ffmpeg: |
| 80 | ```bash |
| 81 | # Two-pass palette for best color quality |
| 82 | ffmpeg -i input.mp4 -vf "fps=12,scale=800:800:flags=lanczos,palettegen=stats_mode=diff" palette.png |
| 83 | ffmpeg -i input.mp4 -i palette.png -vf "fps=12,scale=800:800:flags=lanczos,paletteuse=dither=bayer:bayer_scale=5" output.gif |
| 84 | ``` |
| 85 | |
| 86 | --- |
| 87 | |
| 88 | ## Step 3: HTML Generation (css-animated path) |
| 89 | |
| 90 | Read `references/animation-library.md` and `references/style-presets.md` before generating. |
| 91 | |
| 92 | **Canvas base — required on every GIF:** |
| 93 | ```css |
| 94 | *, *::before, *::after { margin: 0; padding: 0; box-si |