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

# 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
<!--
  ============================================================
  SVGarden — https://www.svgarden.dev
  Author : Simon-Pierre Boucher
  Contact: contact@spboucher.ai
  File   : {relative/path/to/file}
  Desc   : {one-line description}
  ============================================================
-->

# 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

text
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
<!--
  ============================================================
  SVGarden — https://www.svgarden.dev
  Author : Simon-Pierre Boucher
  Contact: contact@spboucher.ai
  File   : snippets/loaders/spinner-dash.html
  Desc   : Rotating arc loader using animated stroke-dasharray
  ============================================================
-->
<!--svgarden
title: Dash spinner
slug: spinner-dash
category: loaders
tags: [loader, dasharray, keyframes, infinite]
difficulty: beginner
techniques: [stroke-dasharray, stroke-dashoffset, "@keyframes", transform-rotate]
how_it_works: >
  The outer rotation is a simple 2s linear spin. The "chasing" effect
  comes from animating stroke-dasharray so the visible arc grows and
  shrinks while stroke-dashoffset shifts its starting point.
customizable:
  - { var: "--sg-color",    label: "Color",  type: color,  default: "#7F77DD" }
  - { var: "--sg-size",     label: "Size",   type: range,  min: 24, max: 120, default: 48, unit: px }
  - { var: "--sg-duration", label: "Speed",  type: range,  min: 0.5, max: 4, step: 0.1, default: 1.5, unit: s }
created: 2026-08-10
-->
<div class="sg-spinner" style="--sg-color:#7F77DD; --sg-size:48px; --sg-duration:1.5s;">
  <svg viewBox="0 0 50 50" width="var(--sg-size)" ...>...</svg>
</div>
<style>
  /* scoped: every class is prefixed sg- and unique per snippet */
</style>

# 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" + <title>.
  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)

  1. Keyboard navigation + / to focus search.
  2. "Random snippet" button.
  3. Per-snippet OG image generation at build time.
  4. RSS/JSON feed of newly added snippets.
  5. 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 pullnpm cinpm run buildpm2 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.