SPB Git

spb/svgarden Public

SVGarden — searchable bank of 74 self-contained SVG+CSS animation snippets (svgarden.dev)

HTML 79.2% Astro 10.3% JavaScript 6% CSS 3.7% Shell 0.8%
15.3 KB · 327 lines markdown
Rendered Raw Blame History
1# CLAUDE.md — SVGarden Platform23> **Project:** SVGarden — A massive, searchable bank of SVG + CSS animations with copy-ready code snippets.4> **Author:** Simon-Pierre Boucher — contact@spboucher.ai5> **Production URL:** https://www.svgarden.dev (served via ngrok from node `m3u96b`)67---89## 1. Mission1011You (Claude Code) are building **SVGarden**, a static-first web platform that hosts a large, ever-growing library of SVG/CSS animations. Every animation is a self-contained snippet that visitors can preview live, customize, and copy in one click.1213The platform must be:14151. **Scalable by design** — adding a new animation means adding ONE file. The gallery, search index, tags, and category pages regenerate automatically at build time.162. **Zero-dependency for visitors** — every copied snippet must work when pasted into a blank `.html` file. No frameworks, no build step, no external assets required by the snippets themselves.173. **Pedagogical** — every snippet ships with a short "How it works" explanation.184. **Beautiful** — the site itself should demonstrate the craft it teaches.1920---2122## 2. Mandatory file header (NON-NEGOTIABLE)2324**EVERY code file in this repository** — HTML, CSS, JS, config files, snippet files, build scripts, everything — MUST begin with an author header. No exceptions. If you create a file without this header, fix it immediately.2526### HTML / Snippet files27```html28<!--29  ============================================================30  SVGarden — https://www.svgarden.dev31  Author : Simon-Pierre Boucher32  Contact: contact@spboucher.ai33  File   : {relative/path/to/file}34  Desc   : {one-line description}35  ============================================================36-->37```3839### CSS files40```css41/*42  ============================================================43  SVGarden — https://www.svgarden.dev44  Author : Simon-Pierre Boucher45  Contact: contact@spboucher.ai46  File   : {relative/path/to/file}47  Desc   : {one-line description}48  ============================================================49*/50```5152### JavaScript / Node files53```js54/**55 * ============================================================56 * SVGarden — https://www.svgarden.dev57 * Author : Simon-Pierre Boucher58 * Contact: contact@spboucher.ai59 * File   : {relative/path/to/file}60 * Desc   : {one-line description}61 * ============================================================62 */63```6465### Shell scripts / YAML / config66```bash67# ============================================================68# SVGarden — https://www.svgarden.dev69# Author : Simon-Pierre Boucher70# Contact: contact@spboucher.ai71# File   : {relative/path/to/file}72# Desc   : {one-line description}73# ============================================================74```7576Additionally, the **copy-to-clipboard output** of every snippet must include the HTML-comment version of this header at the top, so attribution travels with the code.7778---7980## 3. Tech stack8182| Layer | Choice | Rationale |83|---|---|---|84| Runtime | Node.js ≥ 20 (LTS) | Runs on node `m3u96b` |85| Framework | **Astro** (latest stable) | Static output, content collections, zero client JS by default |86| Styling | Vanilla CSS with custom properties | The site must eat its own dog food — no Tailwind for the public site |87| Syntax highlighting | **Shiki** (build-time) | Zero runtime cost |88| Search | **Fuse.js** (client-side, lazy-loaded) | Small, works on static hosting |89| Server | `astro preview` or a tiny Express static server on port **4321** | Fronted by ngrok |90| Tunnel | **ngrok** with reserved domain `www.svgarden.dev` | See §9 |91| Process manager | **pm2** | Keeps server + tunnel alive on `m3u96b` |9293If Astro is unavailable or problematic on the node, fall back to a hand-rolled Node build script (`build.mjs`) that reads `snippets/**` and emits static HTML from templates. The architecture below must work either way.9495---9697## 4. Repository structure9899```100svgarden/101├── CLAUDE.md                  ← this file102├── README.md103├── package.json104├── astro.config.mjs105├── ecosystem.config.cjs       ← pm2 config (site + ngrok)106├── scripts/107│   ├── new-snippet.mjs        ← scaffolds a new snippet file interactively108│   ├── validate-snippets.mjs  ← CI check: headers, metadata, self-containment109│   └── deploy.sh              ← build + pm2 restart + ngrok health check110├── src/111│   ├── layouts/Base.astro112│   ├── pages/113│   │   ├── index.astro        ← gallery home (all snippets, filterable)114│   │   ├── category/[cat].astro115│   │   ├── snippet/[slug].astro  ← detail page: preview + code + customizer116│   │   └── about.astro117│   ├── components/118│   │   ├── SnippetCard.astro119│   │   ├── LivePreview.astro  ← sandboxed iframe preview120│   │   ├── CodeBlock.astro    ← Shiki-highlighted, copy button121│   │   ├── Customizer.astro   ← color/speed/size controls → live re-render122│   │   ├── SearchBar.astro123│   │   └── TagFilter.astro124│   └── styles/global.css125├── snippets/                  ← THE BANK. One file = one animation.126│   ├── loaders/127│   ├── hover/128│   ├── stroke-draw/129│   ├── gauges/130│   ├── text/131│   ├── morph/132│   ├── backgrounds/133│   └── buttons/134└── public/135    ├── favicon.svg136    └── og/                    ← auto-generated OG images per snippet (stretch goal)137```138139---140141## 5. Snippet file format (the heart of the platform)142143Every snippet is a single `.html` file inside `snippets/{category}/`. It contains a YAML-in-comment frontmatter block, followed by the raw self-contained snippet code.144145```html146<!--147  ============================================================148  SVGarden — https://www.svgarden.dev149  Author : Simon-Pierre Boucher150  Contact: contact@spboucher.ai151  File   : snippets/loaders/spinner-dash.html152  Desc   : Rotating arc loader using animated stroke-dasharray153  ============================================================154-->155<!--svgarden156title: Dash spinner157slug: spinner-dash158category: loaders159tags: [loader, dasharray, keyframes, infinite]160difficulty: beginner161techniques: [stroke-dasharray, stroke-dashoffset, "@keyframes", transform-rotate]162how_it_works: >163  The outer rotation is a simple 2s linear spin. The "chasing" effect164  comes from animating stroke-dasharray so the visible arc grows and165  shrinks while stroke-dashoffset shifts its starting point.166customizable:167  - { var: "--sg-color",    label: "Color",  type: color,  default: "#7F77DD" }168  - { var: "--sg-size",     label: "Size",   type: range,  min: 24, max: 120, default: 48, unit: px }169  - { var: "--sg-duration", label: "Speed",  type: range,  min: 0.5, max: 4, step: 0.1, default: 1.5, unit: s }170created: 2026-08-10171-->172<div class="sg-spinner" style="--sg-color:#7F77DD; --sg-size:48px; --sg-duration:1.5s;">173  <svg viewBox="0 0 50 50" width="var(--sg-size)" ...>...</svg>174</div>175<style>176  /* scoped: every class is prefixed sg- and unique per snippet */177</style>178```179180### Hard rules for snippets1811. **Self-contained**: no external fonts, images, scripts, or CSS. Inline everything.1822. **Scoped**: all class names prefixed with `sg-` + snippet slug context to avoid collisions when users paste multiple snippets in one page.1833. **Customizable via CSS custom properties** (`--sg-*`) declared on the root element — this is what powers the live Customizer.1844. **Dark/light safe**: must look good on both `#ffffff` and `#111111` backgrounds. Preview iframe offers a background toggle.1855. **No JS unless essential** (gauges/interactive snippets may use minimal vanilla JS, clearly marked with tag `js`).1866. **Accessible**: decorative SVGs get `aria-hidden="true"`; meaningful ones get `role="img"` + `<title>`.1877. **Max ~120 lines** per snippet. Elegance over bloat.188189### The build pipeline must190- Parse the `<!--svgarden ... -->` frontmatter of every file in `snippets/**`.191- Generate: the gallery index, one detail page per snippet, per-category pages, a `search-index.json` for Fuse.js, and a tag cloud.192- **Fail the build** if any snippet is missing the author header, frontmatter, or violates validation (`scripts/validate-snippets.mjs`).193194---195196## 6. Site features (in priority order)197198### MVP (build ALL of this)1991. **Gallery home** — responsive card grid, each card shows the live animation (lazy-rendered iframe or inline with IntersectionObserver), title, category badge, tags.2002. **Detail page per snippet** — large live preview with light/dark background toggle, "How it works" section, full highlighted code, **Copy code** button (copies snippet WITH the attribution header), **Download .html** button.2013. **Customizer** — auto-generated controls from the `customizable` frontmatter (color pickers, range sliders). Changes update the live preview instantly AND rewrite the code block + clipboard output with the chosen values.2024. **Search & filters** — instant client-side search (title, tags, techniques) + category filter + difficulty filter.2035. **Dark/light site theme** — respects `prefers-color-scheme` with a manual toggle.204205### V2 (build after MVP is deployed and validated)2066. Keyboard navigation + `/` to focus search.2077. "Random snippet" button.2088. Per-snippet OG image generation at build time.2099. RSS/JSON feed of newly added snippets.21010. Simple analytics (self-hosted Plausible script placeholder — do NOT add third-party trackers).211212---213214## 7. Seed content — REQUIRED example snippets215216Create **at least 24 snippets** at initial build, spread across categories. Each one fully compliant with §5. Required list:217218**loaders/** (6)2191. `spinner-dash` — rotating arc with animated dasharray2202. `dots-pulse` — three SVG circles pulsing in sequence2213. `ring-dual` — two counter-rotating arcs2224. `bar-indeterminate` — sliding indeterminate progress bar2235. `orbit-dots` — dots orbiting a center point2246. `hourglass-flip` — hourglass shape flipping with rotate keyframes225226**stroke-draw/** (4)2277. `signature-draw` — a scripted path "hand-drawing" itself (dashoffset)2288. `checkmark-pop` — animated checkmark draw + scale pop (success state)2299. `circuit-trace` — a circuit-like polyline tracing with staggered delays23010. `underline-sketch` — sketchy underline that draws on load231232**hover/** (4)23311. `star-spin` — star rotates + scales on hover23412. `icon-morph-menu` — hamburger → X on hover/click (line transforms)23513. `card-lift-border` — SVG border that draws itself around a card on hover23614. `magnetic-arrow` — arrow that nudges along its axis on hover237238**gauges/** (3)23915. `gauge-circle` — circular percentage gauge, JS slider driven (tag: js)24016. `gauge-semicircle` — semicircle speedometer style24117. `battery-fill` — battery icon with animated fill level242243**text/** (3)24418. `text-on-path` — text following a curved `<textPath>`, animated startOffset24519. `text-stroke-reveal` — outlined text that fills in via dashoffset24620. `wave-text` — letters bouncing in a wave (staggered animation-delay)247248**morph/** (2)24921. `blob-morph` — organic blob morphing between path shapes (CSS `d:` or SMIL fallback)25022. `play-pause-morph` — play ⇄ pause icon morph on click (tag: js)251252**backgrounds/** (2)25323. `wave-divider` — animated layered wave section divider25424. `dots-drift` — subtle drifting dot-grid pattern background255256Each snippet's `how_it_works` must genuinely teach the technique in 2–4 sentences. Do not copy text between snippets.257258---259260## 8. Design system for the site itself261262- Typography: system font stack; headings weight 600, body 400.263- Layout: max-width 1200px gallery, CSS grid `repeat(auto-fill, minmax(280px, 1fr))`.264- Palette: neutral background, ONE accent color (`#7F77DD` violet), semantic greens/reds only for status.265- Cards: 1px hairline borders, 12px radius, no drop shadows, subtle hover lift via `transform: translateY(-2px)`.266- The site must score ≥ 95 on Lighthouse performance & accessibility. Verify before deploying.267- Footer on every page: `© Simon-Pierre Boucher — contact@spboucher.ai — svgarden.dev`.268269---270271## 9. Deployment — node `m3u96b` + ngrok → www.svgarden.dev272273Target: the platform runs persistently on node **`m3u96b`** and is publicly reachable at **https://www.svgarden.dev** through an ngrok tunnel.274275### Steps to implement2761. **Build**: `npm run build` → static output in `dist/`.2772. **Serve**: minimal static server (`server.mjs`, Express or `serve`) on `127.0.0.1:4321`, with correct cache headers (`immutable` for hashed assets, `no-cache` for HTML) and gzip/brotli.2783. **ngrok**:279   - Assume ngrok is installed and authenticated on `m3u96b` (`ngrok config add-authtoken ...` already done by the operator; if not, print clear instructions and stop — NEVER ask for or handle the authtoken value yourself).280   - The domain `www.svgarden.dev` must be configured as a **reserved custom domain** in the ngrok dashboard, with the DNS CNAME pointed at ngrok as per their docs. Document this requirement in README; you cannot do the DNS step yourself.281   - Tunnel config in `~/.config/ngrok/ngrok.yml` (create/extend via a documented block, not by overwriting):282     ```yaml283     tunnels:284       svgarden:285         proto: http286         addr: 4321287         domain: www.svgarden.dev288     ```289   - Start with `ngrok start svgarden`.2904. **pm2** (`ecosystem.config.cjs`): two apps — `svgarden-web` (the static server) and `svgarden-tunnel` (`ngrok start svgarden --log=stdout`). Enable `pm2 save` + startup so both survive reboots.2915. **`scripts/deploy.sh`**: `git pull``npm ci``npm run build``pm2 restart ecosystem.config.cjs` → curl health check on `http://127.0.0.1:4321` AND `https://www.svgarden.dev` → print status summary.2926. **Health**: add a `/healthz` route returning build timestamp + snippet count.293294### Deployment rules295- Never commit secrets, tokens, or the ngrok authtoken to the repo. `.gitignore` must cover `ngrok.yml`, `.env*`, `node_modules`, `dist`.296- If the tunnel fails (domain not reserved, auth missing), degrade gracefully: keep the local server running and print actionable instructions.297298---299300## 10. Quality gates & workflow301302Before considering ANY task done:3031. `node scripts/validate-snippets.mjs` passes (headers ✔, frontmatter ✔, scoping ✔, size limit ✔).3042. `npm run build` completes with zero warnings.3053. Every new snippet was visually verified (describe what you checked).3064. Copy button output pasted into a blank HTML file renders correctly — test at least 3 snippets this way per session.3075. Git: conventional commits (`feat(snippets): add blob-morph`, `fix(site): ...`). Commit in small, logical units.308309### Working style310- When asked to "add N snippets", follow §5 and §7 formats exactly, pick varied techniques, and update nothing else — the build handles the rest.311- Prefer editing the build system once over hand-editing generated pages ever.312- If a requirement in this file conflicts with a user instruction in chat, the chat instruction wins — but flag the conflict explicitly.313314---315316## 11. Roadmap summary317318| Phase | Deliverable |319|---|---|320| 1 | Repo scaffold, build pipeline, validation script, base layout |321| 2 | 24 seed snippets (§7), gallery + detail pages |322| 3 | Search, filters, customizer, copy/download, dark mode |323| 4 | Deployment on `m3u96b` + ngrok + pm2 + deploy.sh |324| 5 | V2 features (§6), grow the bank toward 100+ snippets |325326Build it beautifully. Every snippet is a small lesson; the site is the classroom.327