wiggle — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited wiggle (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Create professional logo animations using Lottie JSON format. Ingest existing logos (PNG/SVG/JPG) or generate simple text-based logos, then animate them with professionally-crafted motion patterns. Output includes Lottie JSON with automatic GIF preview rendering and optional MP4 export.
Trigger this skill when users request:
Important: This skill outputs standalone animation files (Lottie JSON, GIF, MP4), NOT interactive React/HTML artifacts. If user wants an interactive tool or web component, defer to artifacts-builder skill.
Before creating any animation, answer these three questions:
(playful, professional, bold, elegant, innovative, trustworthy)
(excitement, trust, creativity, confidence, curiosity)
(organic growth, mechanical precision, energetic burst, elegant reveal, rhythmic pulse)
Example: "Canva = Creative tool brand → Playful energy + organic growth → Simultaneous entrance with pulse"
See Animation Philosophy section below for detailed framework.
Before creating animation, understand what you're working with:
# For SVG logos - identify elements
python scripts/extract_svg_elements.py logo.svg --listQuick decision tree:
Logo has text?
├─ YES → Read references/text_animation_guide.md FIRST
└─ NO → Continue with standard workflow
Multiple elements (icon + text)?
├─ YES → Extract separately, decide timing (simultaneous vs staggered)
└─ NO → Animate as single unit
SVG or PNG?
├─ SVG → Can extract elements cleanly
└─ PNG → Limited to single-logo animations# Single logo (simple animation)
python scripts/prepare_logo.py logo.png --max-size 500 --optimize
# Creates: logo_optimized.png (30-50KB) + logo_base64.txt
# Multi-element logo (extract FIRST, then convert)
python scripts/extract_svg_elements.py logo.svg --output-dir ./elements/
python scripts/prepare_logo.py elements/icon.svg --max-size 200
python scripts/prepare_logo.py elements/text.svg --max-size 250Size guidelines:
Use EXTERNAL references during development:
{
"v": "5.7.4",
"fr": 60,
"ip": 0,
"op": 180,
"w": 800,
"h": 800,
"layers": [{
"ind": 1,
"ty": 2,
"nm": "Logo",
"refId": "logo_image",
"ks": {
"o": {
"a": 1,
"k": [
{"t": 0, "s": [0], "e": [100], "i": {"x": [0.42], "y": [1]}, "o": {"x": [0.58], "y": [0]}},
{"t": 60, "s": [100]}
]
}
}
}],
"assets": [{"id": "logo_image", "w": 512, "h": 512, "p": "logo_optimized.png", "e": 0}]
}Critical: Use "e": 0 (external reference) during development to avoid Cairo memory errors.
See Animation Patterns below for common effects, or references/detailed_examples.md for full code examples.
# Check Lottie structure (warns about large embedded assets)
python scripts/validate_lottie.py logo_animation.json
# Check loop quality (if creating looping animation)
python scripts/validate_loop.py logo_animation.json# RECOMMENDED: Preview first (renders only first N frames) - saves time!
python scripts/render_lottie.py logo_animation.json preview.gif --preview-frames 60
# Alternative: Test render mode (200x200, 15fps with confirmation prompt)
python scripts/render_lottie.py logo_animation.json logo.gif --test-render
# If preview looks good → Render full animation
python scripts/render_lottie.py logo_animation.json logo.gif
# Optional: MP4 export (better compression than GIF)
python scripts/render_lottie.py logo_animation.json logo.mp4
# Optional: Batch export all formats
python scripts/batch_export.py logo_animation.json ./output gif,mp4,jsonImportant notes:
--preview-frames N to render only first N frames for quick validationAfter successful rendering, optionally convert to embedded base64 for standalone distribution:
// Replace external reference with base64 from logo_base64.txt
"assets": [{"id": "logo_image", "p": "data:image/png;base64,...", "e": 1}]Note: Keep external version for future edits/rendering!
Phase 1: Define Philosophy (think before implementing)
Phase 2: Express Through Technical Choices
"Confident Professionalism"
"Playful Energy"
"Audio/Speech Brand"
More examples in references/preset_library.md and references/animation_theory.md.
Choose motion type based on brand personality:
Professional brands (B2B, finance, legal)
Parameters:
0.42/0.58 (standard ease-in-out)Use for: Corporate logos, B2B brands, professional presentations
Audio, music, speech AI, nature brands
Parameters:
0.25/0.75 (softer, more organic)Use for: Audio apps, music platforms, speech AI, organic products
Example: Vertical bar waveform pattern in references/detailed_examples.md
Startups, social media, marketing
Parameters:
0.34/1.56 (playful bounce) or 0.6/-0.28 (back overshoot)Use for: Startup logos, social media intros, marketing campaigns
Premium brands, film production
Parameters:
Use for: Luxury brands, film intros, high-end agency work
| Pattern | Duration | Properties | Use Case |
|---|---|---|---|
| Fade + Gentle Scale | 1.5s | Opacity: 0→100%, Scale: 95→100% | Corporate entrances |
| Bounce Entrance | 1.2s | Position, Scale, Opacity | Energetic brands |
| Scale Pulse | 3s loop | Scale: 100→103→100% | Idle states, CTAs |
| Smooth Rotation | 10s loop | Rotation: 0→360° | Loading, tech logos |
| Wiggle/Jello | 0.8s | Rotation: ±5° oscillation | Playful notifications |
Full code examples: references/detailed_examples.md
Pattern 1: Simultaneous Entrance Both elements appear together (cohesive brand)
Icon: {"t": 0, "s": [0]}, {"t": 60, "s": [100]}
Text: {"t": 0, "s": [0]}, {"t": 60, "s": [100]}
// Both start at t:0 → SynchronizedPattern 2: Staggered Entrance Icon establishes first, text reinforces (storytelling)
Icon: {"t": 0, "s": [0]}, {"t": 45, "s": [100]}
Text: {"t": 30, "s": [0]}, {"t": 75, "s": [100]}
// Text delayed 30 frames (0.5s at 60fps)Timing guidelines:
Full patterns: references/detailed_examples.md#multi-element-coordination
Always classify user intent to select appropriate animation style:
| Intent | Keyframes | Easing | FPS | Duration | Motion |
|---|---|---|---|---|---|
| Subtle/Professional | 8-12 | 0.42/0.58 | 30 | 1.5-2s | Slow, controlled, minimal rotation |
| Bold/Attention | 15-25 | 0.34/1.56 | 60 | 0.8-1.5s | Medium-fast, dynamic, ±10-20% scale |
| Playful/Creative | 12-20 | 0.34/1.56 | 30-60 | 1-2s | Bouncy, exaggerated, wiggle effects |
| Organic/Continuous | 25-45 | 0.25/0.75 | 60 | 3s | Waveforms, pulses, flowing rhythms |
Default: Provide animation rather than asking questions, unless user explicitly requests options.
Current behavior:
Example:
project/
├── animations/
│ └── logo_animation.json (references "logo_optimized.png")
└── logo_optimized.png
# This will FAIL - asset not foundSolution: Place assets in the same directory as the JSON file:
project/animations/
├── logo_animation.json
└── logo_optimized.png # ✅ Correct locationEmbedded base64 ("e": 1):
External references ("e": 0):
Recommended workflow:
Full list with code examples: references/anti_patterns.md
If logo contains text, you MUST follow specialized workflow:
See: references/text_animation_guide.md for complete guide
Always use external file references during development/rendering:
// ✅ CORRECT: External reference
"assets": [{"id": "logo", "p": "logo_optimized.png", "e": 0}]
// ❌ WRONG: Embedded base64 (causes Cairo crash if >100KB)
"assets": [{"id": "logo", "p": "data:image/png;base64,...", "e": 1}]Why: Cairo renderer crashes with embedded images >100KB. Use external during development, optionally embed AFTER successful rendering.
| Script | Purpose | Example |
|---|---|---|
prepare_logo.py | Optimize and convert logo images | python scripts/prepare_logo.py logo.png --max-size 500 |
extract_svg_elements.py | Extract elements from SVG | python scripts/extract_svg_elements.py logo.svg --list |
validate_lottie.py | Check Lottie structure | python scripts/validate_lottie.py animation.json |
validate_loop.py | Verify perfect loop | python scripts/validate_loop.py animation.json |
render_lottie.py | Render to GIF/MP4 (with asset validation) | python scripts/render_lottie.py animation.json output.gif |
render_lottie.py --preview-frames N | Quick preview (first N frames) | python scripts/render_lottie.py animation.json preview.gif --preview-frames 60 |
render_lottie.py --test-render | Test mode with size warnings | python scripts/render_lottie.py animation.json test.gif --test-render |
batch_export.py | Export multiple formats | python scripts/batch_export.py animation.json ./output gif,mp4 |
New features in render_lottie.py:
--preview-frames N) - renders only first N frames--test-render) - small test render with confirmation promptDetailed usage: references/script_usage.md
{
"v": "5.7.4", // Lottie version
"fr": 60, // Frame rate
"ip": 0, // In point (start frame)
"op": 180, // Out point (end frame)
"w": 800, // Width
"h": 800, // Height
"layers": [...], // Animation layers
"assets": [...] // Image/asset references
}"o": {
"a": 1, // Animated (1) or static (0)
"k": [
{"t": 0, "s": [0], "e": [100], "i": {...}, "o": {...}},
{"t": 60, "s": [100]}
]
}Complete specification: references/lottie_spec.md
Never use linear easing - always use curves for professional motion.
| Easing | Values | Feel | Use Case |
|---|---|---|---|
| Ease-in-out (standard) | 0.42/0.58 | Balanced, professional | Corporate, general use |
| Organic | 0.25/0.75 | Soft, natural | Audio brands, waveforms, continuous motion |
| Bounce | 0.34/1.56 | Playful, energetic | Startups, playful brands |
| Back | 0.6/-0.28 & 0.735/0.045 | Overshoot, dynamic | Bold marketing, attention-grabbing |
Theory and examples: references/animation_theory.md
pip install lottie[all] # Lottie manipulation
pip install Pillow # Image processing
pip install pycairo # Cairo rendering (for GIF)macOS:
brew install cairo pkg-config
pip install pycairoLinux (Ubuntu/Debian):
sudo apt-get install libcairo2-dev pkg-config python3-dev
pip install pycairoVerify:
python3 -c "import cairo; print('Cairo OK')"Troubleshooting: references/troubleshooting.md#cairo-and-dependencies
Asset not found errors:
render_lottie.py - it validates assets before renderingBlank/corrupted output:
MemoryError during GIF rendering:
"e": 0) insteadLoop has visible jump:
validate_loop.py and ensure last frame = first frameText looks wrong:
extract_svg_elements.pyAnimation too choppy:
Preview renders save time:
--preview-frames 60 to validate concept before full render--test-render for interactive testing with size warningsComprehensive guide: references/troubleshooting.md
Target sizes for different use cases:
| Use Case | Lottie JSON | GIF | MP4 | Image Assets |
|---|---|---|---|---|
| Email signature | 20-50KB | 500KB-1MB | 200-500KB | <30KB each |
| Website hero | 30-80KB | 1-3MB | 500KB-1.5MB | <50KB each |
| Social media | 50-150KB | 3-8MB | 1-3MB | <80KB each |
| Splash screen | 30-100KB | 2-5MB | 800KB-2MB | <60KB each |
Optimization: Use scripts/optimize_lottie.py to reduce file sizes by removing redundant keyframes and rounding values.
Quick reference to common presets (full code in references/preset_library.md):
Branding Styles:
Use Cases:
Real-World Examples: Study hover animations from major brands in references/real-world-examples/:
Before creating animation, verify:
"e": 0) during developmentvalidate_loop.py if creating loopIf all checked → Proceed with confidence ✅
validate_loop.py to verifyvalidate_lottie.py and validate_loop.pyRemember: The goal is creating motion that enhances brand identity, not random animation. Philosophy-first workflow ensures alignment from the start.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.