docs(readme): metrics dashboard + status badges
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Showing 1 changed file with +71 and −22
modified
README.md
+71 −22
@@ -1,11 +1,77 @@ | ||
| 1 | 1 | # SVGarden 🌱 |
| 2 | 2 | |
| 3 | 3 | > A massive, searchable bank of SVG + CSS animations with copy-ready code snippets. |
| 4 | −> **Production:** https://www.svgarden.dev — **Author:** Simon-Pierre Boucher — contact@spboucher.ai | |
| 4 | + | |
| 5 | +<p> | |
| 6 | + <a href="https://www.svgarden.dev"><img alt="Live" src="https://img.shields.io/badge/live-svgarden.dev-7F77DD?style=flat-square&logo=ngrok&logoColor=white"></a> | |
| 7 | + <img alt="Snippets" src="https://img.shields.io/badge/snippets-74-7F77DD?style=flat-square"> | |
| 8 | + <img alt="Categories" src="https://img.shields.io/badge/categories-14-8b84e0?style=flat-square"> | |
| 9 | + <img alt="Techniques" src="https://img.shields.io/badge/techniques_taught-177-9c95e8?style=flat-square"> | |
| 10 | + <img alt="Lighthouse performance" src="https://img.shields.io/badge/lighthouse_perf-100-1a7f4e?style=flat-square&logo=lighthouse&logoColor=white"> | |
| 11 | + <img alt="Lighthouse accessibility" src="https://img.shields.io/badge/lighthouse_a11y-100-1a7f4e?style=flat-square&logo=lighthouse&logoColor=white"> | |
| 12 | + <img alt="Visitor dependencies" src="https://img.shields.io/badge/visitor_deps-0-1a7f4e?style=flat-square"> | |
| 13 | + <img alt="Astro" src="https://img.shields.io/badge/Astro-5-BC52EE?style=flat-square&logo=astro&logoColor=white"> | |
| 14 | + <img alt="Node" src="https://img.shields.io/badge/node-%E2%89%A5%2020-339933?style=flat-square&logo=node.js&logoColor=white"> | |
| 15 | + <img alt="License" src="https://img.shields.io/badge/license-MIT-blue?style=flat-square"> | |
| 16 | +</p> | |
| 17 | + | |
| 18 | +**Production:** https://www.svgarden.dev · **Author:** Simon-Pierre Boucher — contact@spboucher.ai | |
| 5 | 19 | |
| 6 | 20 | Every animation is one self-contained `.html` file: paste it into a blank page and it works. |
| 7 | 21 | No frameworks, no CDNs, no build step required by the snippets themselves — and each one |
| 8 | −ships with a short "How it works" lesson. | |
| 22 | +ships with a short "How it works" lesson. The site is static (Astro), searched client-side | |
| 23 | +(lazy Fuse.js), highlighted at build time (Shiki), and customized live through CSS custom | |
| 24 | +properties. | |
| 25 | + | |
| 26 | +## 📊 Metrics | |
| 27 | + | |
| 28 | +### The bank | |
| 29 | + | |
| 30 | +| Metric | Value | | |
| 31 | +|---|---| | |
| 32 | +| 🟣 Snippets | **74** | | |
| 33 | +| 🗂 Categories | **14** | | |
| 34 | +| 🧪 Distinct techniques taught | **177** | | |
| 35 | +| ⚡ JavaScript-free snippets | **67 / 74** (90 %) | | |
| 36 | +| 🧭 Snippets with a browser-support caveat (`support`) | **13** | | |
| 37 | +| 📏 Average snippet size | **57 lines** (max 116, hard cap 150) | | |
| 38 | +| 🧩 Pages generated per build | **84** | | |
| 39 | + | |
| 40 | +### Difficulty | |
| 41 | + | |
| 42 | +| | Level | Count | Share | | |
| 43 | +|---|---|---|---| | |
| 44 | +| 🟢 | beginner | 9 | 12 % | | |
| 45 | +| 🟣 | intermediate | 27 | 36 % | | |
| 46 | +| 🔴 | advanced | 38 | 51 % | | |
| 47 | + | |
| 48 | +### Categories | |
| 49 | + | |
| 50 | +| Category | Count | Headline techniques | | |
| 51 | +|---|---:|---| | |
| 52 | +| 🔘 `buttons` | 8 | goo filter, clipPath sweeps, `@property` hue trace, `linear()` springs, multi-stage morph | | |
| 53 | +| 🎛 `filters` | 8 | feTurbulence, feDisplacementMap, goo matrix, feMorphology, feDropShadow stacks, backdrop-filter | | |
| 54 | +| 🖼 `backgrounds` | 7 | mix-blend-mode aurora, SMIL topo morphs, turbulence rain refraction, seamless tiling | | |
| 55 | +| 🌀 `loaders` | 6 | dasharray chase, counter-rotation, choreographed keyframes | | |
| 56 | +| ✨ `text-fx` | 6 | mask knockout, variable-font weight waves, liquid clipPath fill, scramble decode | | |
| 57 | +| 📜 `scroll` | 6 | `animation-timeline: scroll()` / `view()`, `animation-range`, sticky scenes | | |
| 58 | +| 📈 `charts` | 6 | `conic-gradient()` + `@property` sweeps, live polyline updates, `--sg-i` cascades | | |
| 59 | +| 🎚 `interactive` | 6 | `:checked` scenes, reversed-radio rating, `<details>` accordion, pseudo-3D tilt | | |
| 60 | +| 🛰 `motion-path` | 5 | `offset-path`, `animateMotion rotate="auto"`, keyPoints/keyTimes pacing | | |
| 61 | +| ✏️ `stroke-draw` | 4 | pathLength normalization, staggered dashoffset | | |
| 62 | +| 🖱 `hover` | 4 | transform-box, transition choreography | | |
| 63 | +| ⏲ `gauges` | 3 | dashoffset data-mapping, calc() needle angles | | |
| 64 | +| 🔤 `text` | 3 | textPath, SMIL startOffset, glyph stroke tracing | | |
| 65 | +| 🫧 `morph` | 2 | SMIL d-morphing, CSS `d:` with fallback | | |
| 66 | + | |
| 67 | +### Quality gates (every build) | |
| 68 | + | |
| 69 | +| Gate | Status | | |
| 70 | +|---|---| | |
| 71 | +| `validate-snippets.mjs` (headers, frontmatter, scoping, self-containment, size) | 🟢 74/74 | | |
| 72 | +| `npm run build` warnings | 🟢 0 | | |
| 73 | +| Lighthouse performance / accessibility (home + detail) | 🟢 100 / 100 | | |
| 74 | +| Paste-test (copy output → blank .html) | 🟢 verified per batch | | |
| 9 | 75 | |
| 10 | 76 | ## Quick start |
| 11 | 77 | |
@@ -40,14 +106,6 @@ Snippet hard rules (enforced by `scripts/validate-snippets.mjs`, which **fails t | ||
| 40 | 106 | **and** declare a `support: <one-line caveat>` frontmatter field — the detail page |
| 41 | 107 | renders it as a browser-support note. |
| 42 | 108 | |
| 43 | −### Categories | |
| 44 | − | |
| 45 | −`loaders` · `stroke-draw` · `hover` · `gauges` · `text` · `text-fx` (masterclass text | |
| 46 | −effects) · `morph` · `motion-path` (offset-path / animateMotion) · `filters` | |
| 47 | −(feTurbulence, goo, displacement…) · `scroll` (scroll-driven animations, self-contained | |
| 48 | −scroll boxes) · `charts` (animated data-viz primitives) · `interactive` (state-driven, | |
| 49 | −checkbox/radio/details-powered) · `backgrounds` · `buttons` | |
| 50 | − | |
| 51 | 109 | ## Architecture |
| 52 | 110 | |
| 53 | 111 | | Piece | Where | |
@@ -81,8 +139,7 @@ then health-checks `http://127.0.0.1:4321/healthz` and `https://www.svgarden.dev | ||
| 81 | 139 | 2. `www.svgarden.dev` reserved as a **custom domain** in the ngrok dashboard |
| 82 | 140 | (Universal Gateway → Domains). |
| 83 | 141 | 3. DNS: a `CNAME` for `www.svgarden.dev` pointing at the target ngrok gives you when |
| 84 | − reserving the domain. This step happens at your DNS provider; the deploy script | |
| 85 | − degrades gracefully (local server stays up) until it propagates. | |
| 142 | + reserving the domain. | |
| 86 | 143 | 4. Tunnel definition in the node's ngrok config (`~/Library/Application Support/ngrok/ngrok.yml` |
| 87 | 144 | on macOS — add the block, don't overwrite the file): |
| 88 | 145 | |
@@ -94,15 +151,7 @@ tunnels: | ||
| 94 | 151 | domain: www.svgarden.dev |
| 95 | 152 | ``` |
| 96 | 153 | |
| 97 | −pm2 then keeps both alive across reboots (`pm2 save` + `pm2 startup` already configured | |
| 98 | −on the node): `svgarden-web` runs `server.mjs`, `svgarden-tunnel` runs | |
| 99 | −`ngrok start svgarden --log=stdout`. | |
| 100 | − | |
| 101 | −## Quality gates | |
| 102 | − | |
| 103 | −1. `npm run validate` passes; | |
| 104 | −2. `npm run build` completes with zero warnings; | |
| 105 | −3. new snippets visually verified on light **and** dark preview backgrounds; | |
| 106 | −4. copy-button output pastes into a blank `.html` file and renders correctly. | |
| 154 | +pm2 keeps both alive across reboots (`pm2 save` + `pm2 startup`): `svgarden-web` runs | |
| 155 | +`server.mjs`, `svgarden-tunnel` runs `ngrok start svgarden --log=stdout`. | |
| 107 | 156 | |
| 108 | 157 | © Simon-Pierre Boucher — contact@spboucher.ai — svgarden.dev |
| 109 | 158 | |