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%

docs: add project CLAUDE.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Simon-Pierre Boucher committed 4 h ago (Aug 10, 2026) parent 2c13901

Showing 1 changed file with +326 and −0

added CLAUDE.md +326 −0
@@ -0,0 +1,326 @@
1 +# CLAUDE.md — SVGarden Platform
2 +
3 +> **Project:** SVGarden — A massive, searchable bank of SVG + CSS animations with copy-ready code snippets.
4 +> **Author:** Simon-Pierre Boucher — contact@spboucher.ai
5 +> **Production URL:** https://www.svgarden.dev (served via ngrok from node `m3u96b`)
6 +
7 +---
8 +
9 +## 1. Mission
10 +
11 +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.
12 +
13 +The platform must be:
14 +
15 +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.
16 +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.
17 +3. **Pedagogical** — every snippet ships with a short "How it works" explanation.
18 +4. **Beautiful** — the site itself should demonstrate the craft it teaches.
19 +
20 +---
21 +
22 +## 2. Mandatory file header (NON-NEGOTIABLE)
23 +
24 +**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.
25 +
26 +### HTML / Snippet files
27 +```html
28 +<!--
29 + ============================================================
30 + SVGarden — https://www.svgarden.dev
31 + Author : Simon-Pierre Boucher
32 + Contact: contact@spboucher.ai
33 + File : {relative/path/to/file}
34 + Desc : {one-line description}
35 + ============================================================
36 +-->
37 +```
38 +
39 +### CSS files
40 +```css
41 +/*
42 + ============================================================
43 + SVGarden — https://www.svgarden.dev
44 + Author : Simon-Pierre Boucher
45 + Contact: contact@spboucher.ai
46 + File : {relative/path/to/file}
47 + Desc : {one-line description}
48 + ============================================================
49 +*/
50 +```
51 +
52 +### JavaScript / Node files
53 +```js
54 +/**
55 + * ============================================================
56 + * SVGarden — https://www.svgarden.dev
57 + * Author : Simon-Pierre Boucher
58 + * Contact: contact@spboucher.ai
59 + * File : {relative/path/to/file}
60 + * Desc : {one-line description}
61 + * ============================================================
62 + */
63 +```
64 +
65 +### Shell scripts / YAML / config
66 +```bash
67 +# ============================================================
68 +# SVGarden — https://www.svgarden.dev
69 +# Author : Simon-Pierre Boucher
70 +# Contact: contact@spboucher.ai
71 +# File : {relative/path/to/file}
72 +# Desc : {one-line description}
73 +# ============================================================
74 +```
75 +
76 +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.
77 +
78 +---
79 +
80 +## 3. Tech stack
81 +
82 +| 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` |
92 +
93 +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.
94 +
95 +---
96 +
97 +## 4. Repository structure
98 +
99 +```
100 +svgarden/
101 +├── CLAUDE.md ← this file
102 +├── README.md
103 +├── package.json
104 +├── astro.config.mjs
105 +├── ecosystem.config.cjs ← pm2 config (site + ngrok)
106 +├── scripts/
107 +│ ├── new-snippet.mjs ← scaffolds a new snippet file interactively
108 +│ ├── validate-snippets.mjs ← CI check: headers, metadata, self-containment
109 +│ └── deploy.sh ← build + pm2 restart + ngrok health check
110 +├── src/
111 +│ ├── layouts/Base.astro
112 +│ ├── pages/
113 +│ │ ├── index.astro ← gallery home (all snippets, filterable)
114 +│ │ ├── category/[cat].astro
115 +│ │ ├── snippet/[slug].astro ← detail page: preview + code + customizer
116 +│ │ └── about.astro
117 +│ ├── components/
118 +│ │ ├── SnippetCard.astro
119 +│ │ ├── LivePreview.astro ← sandboxed iframe preview
120 +│ │ ├── CodeBlock.astro ← Shiki-highlighted, copy button
121 +│ │ ├── Customizer.astro ← color/speed/size controls → live re-render
122 +│ │ ├── SearchBar.astro
123 +│ │ └── TagFilter.astro
124 +│ └── styles/global.css
125 +├── 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.svg
136 + └── og/ ← auto-generated OG images per snippet (stretch goal)
137 +```
138 +
139 +---
140 +
141 +## 5. Snippet file format (the heart of the platform)
142 +
143 +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.
144 +
145 +```html
146 +<!--
147 + ============================================================
148 + SVGarden — https://www.svgarden.dev
149 + Author : Simon-Pierre Boucher
150 + Contact: contact@spboucher.ai
151 + File : snippets/loaders/spinner-dash.html
152 + Desc : Rotating arc loader using animated stroke-dasharray
153 + ============================================================
154 +-->
155 +<!--svgarden
156 +title: Dash spinner
157 +slug: spinner-dash
158 +category: loaders
159 +tags: [loader, dasharray, keyframes, infinite]
160 +difficulty: beginner
161 +techniques: [stroke-dasharray, stroke-dashoffset, "@keyframes", transform-rotate]
162 +how_it_works: >
163 + The outer rotation is a simple 2s linear spin. The "chasing" effect
164 + comes from animating stroke-dasharray so the visible arc grows and
165 + shrinks while stroke-dashoffset shifts its starting point.
166 +customizable:
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 }
170 +created: 2026-08-10
171 +-->
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 +```
179 +
180 +### Hard rules for snippets
181 +1. **Self-contained**: no external fonts, images, scripts, or CSS. Inline everything.
182 +2. **Scoped**: all class names prefixed with `sg-` + snippet slug context to avoid collisions when users paste multiple snippets in one page.
183 +3. **Customizable via CSS custom properties** (`--sg-*`) declared on the root element — this is what powers the live Customizer.
184 +4. **Dark/light safe**: must look good on both `#ffffff` and `#111111` backgrounds. Preview iframe offers a background toggle.
185 +5. **No JS unless essential** (gauges/interactive snippets may use minimal vanilla JS, clearly marked with tag `js`).
186 +6. **Accessible**: decorative SVGs get `aria-hidden="true"`; meaningful ones get `role="img"` + `<title>`.
187 +7. **Max ~120 lines** per snippet. Elegance over bloat.
188 +
189 +### The build pipeline must
190 +- 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`).
193 +
194 +---
195 +
196 +## 6. Site features (in priority order)
197 +
198 +### MVP (build ALL of this)
199 +1. **Gallery home** — responsive card grid, each card shows the live animation (lazy-rendered iframe or inline with IntersectionObserver), title, category badge, tags.
200 +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.
201 +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.
202 +4. **Search & filters** — instant client-side search (title, tags, techniques) + category filter + difficulty filter.
203 +5. **Dark/light site theme** — respects `prefers-color-scheme` with a manual toggle.
204 +
205 +### V2 (build after MVP is deployed and validated)
206 +6. Keyboard navigation + `/` to focus search.
207 +7. "Random snippet" button.
208 +8. Per-snippet OG image generation at build time.
209 +9. RSS/JSON feed of newly added snippets.
210 +10. Simple analytics (self-hosted Plausible script placeholder — do NOT add third-party trackers).
211 +
212 +---
213 +
214 +## 7. Seed content — REQUIRED example snippets
215 +
216 +Create **at least 24 snippets** at initial build, spread across categories. Each one fully compliant with §5. Required list:
217 +
218 +**loaders/** (6)
219 +1. `spinner-dash` — rotating arc with animated dasharray
220 +2. `dots-pulse` — three SVG circles pulsing in sequence
221 +3. `ring-dual` — two counter-rotating arcs
222 +4. `bar-indeterminate` — sliding indeterminate progress bar
223 +5. `orbit-dots` — dots orbiting a center point
224 +6. `hourglass-flip` — hourglass shape flipping with rotate keyframes
225 +
226 +**stroke-draw/** (4)
227 +7. `signature-draw` — a scripted path "hand-drawing" itself (dashoffset)
228 +8. `checkmark-pop` — animated checkmark draw + scale pop (success state)
229 +9. `circuit-trace` — a circuit-like polyline tracing with staggered delays
230 +10. `underline-sketch` — sketchy underline that draws on load
231 +
232 +**hover/** (4)
233 +11. `star-spin` — star rotates + scales on hover
234 +12. `icon-morph-menu` — hamburger → X on hover/click (line transforms)
235 +13. `card-lift-border` — SVG border that draws itself around a card on hover
236 +14. `magnetic-arrow` — arrow that nudges along its axis on hover
237 +
238 +**gauges/** (3)
239 +15. `gauge-circle` — circular percentage gauge, JS slider driven (tag: js)
240 +16. `gauge-semicircle` — semicircle speedometer style
241 +17. `battery-fill` — battery icon with animated fill level
242 +
243 +**text/** (3)
244 +18. `text-on-path` — text following a curved `<textPath>`, animated startOffset
245 +19. `text-stroke-reveal` — outlined text that fills in via dashoffset
246 +20. `wave-text` — letters bouncing in a wave (staggered animation-delay)
247 +
248 +**morph/** (2)
249 +21. `blob-morph` — organic blob morphing between path shapes (CSS `d:` or SMIL fallback)
250 +22. `play-pause-morph` — play ⇄ pause icon morph on click (tag: js)
251 +
252 +**backgrounds/** (2)
253 +23. `wave-divider` — animated layered wave section divider
254 +24. `dots-drift` — subtle drifting dot-grid pattern background
255 +
256 +Each snippet's `how_it_works` must genuinely teach the technique in 2–4 sentences. Do not copy text between snippets.
257 +
258 +---
259 +
260 +## 8. Design system for the site itself
261 +
262 +- 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`.
268 +
269 +---
270 +
271 +## 9. Deployment — node `m3u96b` + ngrok → www.svgarden.dev
272 +
273 +Target: the platform runs persistently on node **`m3u96b`** and is publicly reachable at **https://www.svgarden.dev** through an ngrok tunnel.
274 +
275 +### Steps to implement
276 +1. **Build**: `npm run build` → static output in `dist/`.
277 +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.
278 +3. **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 + ```yaml
283 + tunnels:
284 + svgarden:
285 + proto: http
286 + addr: 4321
287 + domain: www.svgarden.dev
288 + ```
289 + - Start with `ngrok start svgarden`.
290 +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.
291 +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.
292 +6. **Health**: add a `/healthz` route returning build timestamp + snippet count.
293 +
294 +### Deployment rules
295 +- 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.
297 +
298 +---
299 +
300 +## 10. Quality gates & workflow
301 +
302 +Before considering ANY task done:
303 +1. `node scripts/validate-snippets.mjs` passes (headers ✔, frontmatter ✔, scoping ✔, size limit ✔).
304 +2. `npm run build` completes with zero warnings.
305 +3. Every new snippet was visually verified (describe what you checked).
306 +4. Copy button output pasted into a blank HTML file renders correctly — test at least 3 snippets this way per session.
307 +5. Git: conventional commits (`feat(snippets): add blob-morph`, `fix(site): ...`). Commit in small, logical units.
308 +
309 +### Working style
310 +- 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.
313 +
314 +---
315 +
316 +## 11. Roadmap summary
317 +
318 +| 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 |
325 +
326 +Build it beautifully. Every snippet is a small lesson; the site is the classroom.
327