# CLAUDE.md — SVGarden Platform > **Project:** SVGarden — A massive, searchable bank of SVG + CSS animations with copy-ready code snippets. > **Author:** Simon-Pierre Boucher — contact@spboucher.ai > **Production URL:** https://www.svgarden.dev (served via ngrok from node `m3u96b`) --- ## 1. Mission You (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. The platform must be: 1. **Scalable by design** — adding a new animation means adding ONE file. The gallery, search index, tags, and category pages regenerate automatically at build time. 2. **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. 3. **Pedagogical** — every snippet ships with a short "How it works" explanation. 4. **Beautiful** — the site itself should demonstrate the craft it teaches. --- ## 2. Mandatory file header (NON-NEGOTIABLE) **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. ### HTML / Snippet files ```html ``` ### CSS files ```css /* ============================================================ SVGarden — https://www.svgarden.dev Author : Simon-Pierre Boucher Contact: contact@spboucher.ai File : {relative/path/to/file} Desc : {one-line description} ============================================================ */ ``` ### JavaScript / Node files ```js /** * ============================================================ * SVGarden — https://www.svgarden.dev * Author : Simon-Pierre Boucher * Contact: contact@spboucher.ai * File : {relative/path/to/file} * Desc : {one-line description} * ============================================================ */ ``` ### Shell scripts / YAML / config ```bash # ============================================================ # SVGarden — https://www.svgarden.dev # Author : Simon-Pierre Boucher # Contact: contact@spboucher.ai # File : {relative/path/to/file} # Desc : {one-line description} # ============================================================ ``` Additionally, 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. --- ## 3. Tech stack | Layer | Choice | Rationale | |---|---|---| | Runtime | Node.js ≥ 20 (LTS) | Runs on node `m3u96b` | | Framework | **Astro** (latest stable) | Static output, content collections, zero client JS by default | | Styling | Vanilla CSS with custom properties | The site must eat its own dog food — no Tailwind for the public site | | Syntax highlighting | **Shiki** (build-time) | Zero runtime cost | | Search | **Fuse.js** (client-side, lazy-loaded) | Small, works on static hosting | | Server | `astro preview` or a tiny Express static server on port **4321** | Fronted by ngrok | | Tunnel | **ngrok** with reserved domain `www.svgarden.dev` | See §9 | | Process manager | **pm2** | Keeps server + tunnel alive on `m3u96b` | If 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. --- ## 4. Repository structure ``` svgarden/ ├── CLAUDE.md ← this file ├── README.md ├── package.json ├── astro.config.mjs ├── ecosystem.config.cjs ← pm2 config (site + ngrok) ├── scripts/ │ ├── new-snippet.mjs ← scaffolds a new snippet file interactively │ ├── validate-snippets.mjs ← CI check: headers, metadata, self-containment │ └── deploy.sh ← build + pm2 restart + ngrok health check ├── src/ │ ├── layouts/Base.astro │ ├── pages/ │ │ ├── index.astro ← gallery home (all snippets, filterable) │ │ ├── category/[cat].astro │ │ ├── snippet/[slug].astro ← detail page: preview + code + customizer │ │ └── about.astro │ ├── components/ │ │ ├── SnippetCard.astro │ │ ├── LivePreview.astro ← sandboxed iframe preview │ │ ├── CodeBlock.astro ← Shiki-highlighted, copy button │ │ ├── Customizer.astro ← color/speed/size controls → live re-render │ │ ├── SearchBar.astro │ │ └── TagFilter.astro │ └── styles/global.css ├── snippets/ ← THE BANK. One file = one animation. │ ├── loaders/ │ ├── hover/ │ ├── stroke-draw/ │ ├── gauges/ │ ├── text/ │ ├── morph/ │ ├── backgrounds/ │ └── buttons/ └── public/ ├── favicon.svg └── og/ ← auto-generated OG images per snippet (stretch goal) ``` --- ## 5. Snippet file format (the heart of the platform) Every 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. ```html
...
``` ### Hard rules for snippets 1. **Self-contained**: no external fonts, images, scripts, or CSS. Inline everything. 2. **Scoped**: all class names prefixed with `sg-` + snippet slug context to avoid collisions when users paste multiple snippets in one page. 3. **Customizable via CSS custom properties** (`--sg-*`) declared on the root element — this is what powers the live Customizer. 4. **Dark/light safe**: must look good on both `#ffffff` and `#111111` backgrounds. Preview iframe offers a background toggle. 5. **No JS unless essential** (gauges/interactive snippets may use minimal vanilla JS, clearly marked with tag `js`). 6. **Accessible**: decorative SVGs get `aria-hidden="true"`; meaningful ones get `role="img"` + ``. 7. **Max ~120 lines** per snippet. Elegance over bloat. ### The build pipeline must - Parse the `<!--svgarden ... -->` frontmatter of every file in `snippets/**`. - Generate: the gallery index, one detail page per snippet, per-category pages, a `search-index.json` for Fuse.js, and a tag cloud. - **Fail the build** if any snippet is missing the author header, frontmatter, or violates validation (`scripts/validate-snippets.mjs`). --- ## 6. Site features (in priority order) ### MVP (build ALL of this) 1. **Gallery home** — responsive card grid, each card shows the live animation (lazy-rendered iframe or inline with IntersectionObserver), title, category badge, tags. 2. **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. 3. **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. 4. **Search & filters** — instant client-side search (title, tags, techniques) + category filter + difficulty filter. 5. **Dark/light site theme** — respects `prefers-color-scheme` with a manual toggle. ### V2 (build after MVP is deployed and validated) 6. Keyboard navigation + `/` to focus search. 7. "Random snippet" button. 8. Per-snippet OG image generation at build time. 9. RSS/JSON feed of newly added snippets. 10. Simple analytics (self-hosted Plausible script placeholder — do NOT add third-party trackers). --- ## 7. Seed content — REQUIRED example snippets Create **at least 24 snippets** at initial build, spread across categories. Each one fully compliant with §5. Required list: **loaders/** (6) 1. `spinner-dash` — rotating arc with animated dasharray 2. `dots-pulse` — three SVG circles pulsing in sequence 3. `ring-dual` — two counter-rotating arcs 4. `bar-indeterminate` — sliding indeterminate progress bar 5. `orbit-dots` — dots orbiting a center point 6. `hourglass-flip` — hourglass shape flipping with rotate keyframes **stroke-draw/** (4) 7. `signature-draw` — a scripted path "hand-drawing" itself (dashoffset) 8. `checkmark-pop` — animated checkmark draw + scale pop (success state) 9. `circuit-trace` — a circuit-like polyline tracing with staggered delays 10. `underline-sketch` — sketchy underline that draws on load **hover/** (4) 11. `star-spin` — star rotates + scales on hover 12. `icon-morph-menu` — hamburger → X on hover/click (line transforms) 13. `card-lift-border` — SVG border that draws itself around a card on hover 14. `magnetic-arrow` — arrow that nudges along its axis on hover **gauges/** (3) 15. `gauge-circle` — circular percentage gauge, JS slider driven (tag: js) 16. `gauge-semicircle` — semicircle speedometer style 17. `battery-fill` — battery icon with animated fill level **text/** (3) 18. `text-on-path` — text following a curved `<textPath>`, animated startOffset 19. `text-stroke-reveal` — outlined text that fills in via dashoffset 20. `wave-text` — letters bouncing in a wave (staggered animation-delay) **morph/** (2) 21. `blob-morph` — organic blob morphing between path shapes (CSS `d:` or SMIL fallback) 22. `play-pause-morph` — play ⇄ pause icon morph on click (tag: js) **backgrounds/** (2) 23. `wave-divider` — animated layered wave section divider 24. `dots-drift` — subtle drifting dot-grid pattern background Each snippet's `how_it_works` must genuinely teach the technique in 2–4 sentences. Do not copy text between snippets. --- ## 8. Design system for the site itself - Typography: system font stack; headings weight 600, body 400. - Layout: max-width 1200px gallery, CSS grid `repeat(auto-fill, minmax(280px, 1fr))`. - Palette: neutral background, ONE accent color (`#7F77DD` violet), semantic greens/reds only for status. - Cards: 1px hairline borders, 12px radius, no drop shadows, subtle hover lift via `transform: translateY(-2px)`. - The site must score ≥ 95 on Lighthouse performance & accessibility. Verify before deploying. - Footer on every page: `© Simon-Pierre Boucher — contact@spboucher.ai — svgarden.dev`. --- ## 9. Deployment — node `m3u96b` + ngrok → www.svgarden.dev Target: the platform runs persistently on node **`m3u96b`** and is publicly reachable at **https://www.svgarden.dev** through an ngrok tunnel. ### Steps to implement 1. **Build**: `npm run build` → static output in `dist/`. 2. **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. 3. **ngrok**: - 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). - 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. - Tunnel config in `~/.config/ngrok/ngrok.yml` (create/extend via a documented block, not by overwriting): ```yaml tunnels: svgarden: proto: http addr: 4321 domain: www.svgarden.dev ``` - Start with `ngrok start svgarden`. 4. **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. 5. **`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. 6. **Health**: add a `/healthz` route returning build timestamp + snippet count. ### Deployment rules - Never commit secrets, tokens, or the ngrok authtoken to the repo. `.gitignore` must cover `ngrok.yml`, `.env*`, `node_modules`, `dist`. - If the tunnel fails (domain not reserved, auth missing), degrade gracefully: keep the local server running and print actionable instructions. --- ## 10. Quality gates & workflow Before considering ANY task done: 1. `node scripts/validate-snippets.mjs` passes (headers ✔, frontmatter ✔, scoping ✔, size limit ✔). 2. `npm run build` completes with zero warnings. 3. Every new snippet was visually verified (describe what you checked). 4. Copy button output pasted into a blank HTML file renders correctly — test at least 3 snippets this way per session. 5. Git: conventional commits (`feat(snippets): add blob-morph`, `fix(site): ...`). Commit in small, logical units. ### Working style - When asked to "add N snippets", follow §5 and §7 formats exactly, pick varied techniques, and update nothing else — the build handles the rest. - Prefer editing the build system once over hand-editing generated pages ever. - If a requirement in this file conflicts with a user instruction in chat, the chat instruction wins — but flag the conflict explicitly. --- ## 11. Roadmap summary | Phase | Deliverable | |---|---| | 1 | Repo scaffold, build pipeline, validation script, base layout | | 2 | 24 seed snippets (§7), gallery + detail pages | | 3 | Search, filters, customizer, copy/download, dark mode | | 4 | Deployment on `m3u96b` + ngrok + pm2 + deploy.sh | | 5 | V2 features (§6), grow the bank toward 100+ snippets | Build it beautifully. Every snippet is a small lesson; the site is the classroom.