toolkit DESIGN.md
12 kB · 200 lines
Markdown
at main

Design record #

tilde.style — initiated 2026-06-17. Rebuilt as a three-style switcher 2026-07-21 (see Provenance).

Design intention #

  1. What is this site for? The homepage for the tilde.style toolkit itself — its job is to demonstrate what the toolkit produces, not to commit to one metaphor the way a real tilde site would.
  2. Who tends it? Torsten — alone.
  3. What physical space does it remind you of? Not one space — three, shown side by side: a pond garden, a bonfire clearing, a glider aloft. A visitor picks one and the whole page becomes it.
  4. What should a visitor feel in the first 10 seconds? That these are real, distinct, lived-in design languages — not palette swatches. The photo strip under each gallery card exists to prove that at a glance.
  5. What would feel completely wrong here? Corporate design language, scale-first vocabulary, anything that feels like a product launch. Also wrong: treating the switcher itself as license to mix seasons/styles silently anywhere else — see tend.md's season-mixing section, which names this page as the one deliberate, declared exception.

Active configuration: theme switcher, not a single style #

This page is the specific, named exception in the toolkit's own guidance (skill/reference/tend.md): "build a real theme switcher only when a site's actual job is to demonstrate the style system itself... not as the default answer to a season-mixing bug." A real tilde site should still commit to one style. This one is the toolkit's own kitchen sink.

Three styles ship, each fully documented — and fully self-contained — in its own directory. This file no longer duplicates their palettes/typography/ components, and neither does the CSS:

  • Gardening — styles/gardening/style.md + styles/gardening/style.css
  • Bonfire — styles/bonfire/style.md (+ style-v0.1.md for the pre-grounded original) + styles/bonfire/style.css
  • Sailplane — styles/sailplane/style.md + DESIGN.md + styles/sailplane/style.css

index.html links all four stylesheets (site.css + the three styles/{name}/style.css). This is genuinely just CSS's own cascade doing the work — the browser merges everything it loads into one rule set before resolving conflicts, regardless of how many files it came from, so there was never a need to hand-concatenate them into one site.css. Each style's tokens are scoped to its own [data-theme="…"] selector (not a shared :root), so two styles could even reuse a token name without collision — confirmed non-colliding by name anyway, but the scoping makes that guaranteed rather than just currently-true.

site.css itself now owns only what's unique to this page and nothing style-specific: the reset, the gallery/contact-sheet layout, the switcher chrome, and the .theme-panel show/hide toggle. Adding a fourth style is: write styles/newstyle/style.css, add one <link> line, add one gallery card + panel + switcher button — no existing file needs editing.

Tooling (added 2026-07-21): ./wiggle + ./wiggle-verify #

That last paragraph used to be a recipe a human followed by hand. It's now code: two Cobra CLIs, source under tools/cmd/wiggle/ and tools/cmd/wiggle-verify/ (a Go module — go.work at the repo root wires it into the workspace), built via make build (see the repo-root Makefile; both compiled binaries are gitignored).

Named wiggle, not toolkit or tilde-style-tools. ~ is informally called "squiggle"/"wiggle" for its wavy shape, so the name is grounded in the actual tilde character this whole project is about — and as a verb it describes what using it does: click a different style, the whole page wiggles into a new shape (matching the homepage's own framing: "click one to see the whole page become it"). Styles get noun/gerund names (Gardening, Bonfire, Sailplane, things); the tool that operates on them gets a verb. Modeled loosely on hmans/beans' CLI structure (the same beans this project's own .beans/ tracking already runs on) — thin main.go per binary, Cobra subcommands, one binary per weight class. Credit where due: reading its actual source (not just its README) is where the two-binary split and the PersistentPreRunE shared-init pattern came from.

Two binaries, split by dependency weight (same reasoning as beans splitting beans-serve/beans-tui out from core beans): verify needs chromedp — a full headless-Chrome automation stack — while add/link need almost nothing. Splitting them means the everyday tool (./wiggle, ~6MB) never links in a browser-automation dependency it doesn't use; ./wiggle-verify (~13MB) carries that weight alone, and isn't needed for the common case of just adding a style.

  • ./wiggle add <name> — scaffolds styles/<name>/style.css with loud placeholder-magenta tokens: scaffolded, not designed. Never touches index.html. The toolkit's own central constraint ("you bring the design intention, the AI executes it") still applies to filling it in — this only removes the copy-paste, never invents a metaphor.
  • ./wiggle link <name> — wires an existing styles/<name>/style.css into index.html at four marker comments (<!-- tools/cmd/addstyle:links --> etc. — see index.html itself): <link>, gallery card, switcher button, placeholder panel. Requires the file from add to already exist. Splitting add/link means a style can be drafted and iterated on before it's wired into the live page at all, or a style built by /tilde-style language some other way can be linked in without re-scaffolding it.
    ./wiggle add morphing
    # ... design it for real, replace the placeholder tokens ...
    ./wiggle link morphing --tagline "Transition as content, not decoration." --chip easing
    
  • ./wiggle-verify — the regression harness, driving real Chrome via chromedp (Go's equivalent of Playwright/Puppeteer, CDP-based). No subcommand layer — this binary only ever does one thing. Discovers every style straight from the live DOM (no hardcoded theme list — a new style added by add/link or by hand is covered automatically), clicks each switcher button for real, and asserts: exactly one panel visible, a non-transparent computed background, the gallery-card/switcher-button three-way sync, and that the choice survives a reload (the localStorage contract). --screenshots <dir> optionally drops a full-page PNG per theme — chromedp already drives the browser, so an artifact per theme is one more action, not a separate manual step.
    ./wiggle-verify --screenshots /tmp/tilde-style-shots
    

The background-transparency check exists because of a real incident: a stray */ inside a CSS comment (styles/*/, meaning "each style's own directory") closed the comment early and silently dropped tilde.style's entire :root token block, so every var(--token) background resolved to nothing. It was caught by eye, from a screenshot, after the fact. verify would have caught it the moment it shipped.

Page structure #

  • #gallery — a static strip of 3 .gallery-card buttons (not a rotating carousel — deliberately simultaneous, so all three are visible at once). Each card carries its own colors, a real named component as a chip (Lernhappen / kindling / Variometer), and a contact-sheet photo strip: two small real photographs the style's palette was sampled from, so the "grounded in a real photo, not a mood board" claim is checkable at a glance, not just asserted in prose.
  • #style-switcher — sticky nav, three buttons, mirrors the gallery's selection.
  • Three .theme-panel[data-theme] blocks — full page (header/main/footer) per style, display:none unless .active. Only the selected panel's markup is visible; the other two stay in the DOM (simplest correct approach for a small, single-page site — no need for lazy mounting).
  • setTheme() — one shared JS function syncs switcher buttons, gallery cards, and panels together, persists the choice to localStorage['tilde-style-theme'], and restores it on load.

Photo provenance (added 2026-07-21) #

Every style's palette is sampled from real photographs, not invented — copied into the project as durable assets rather than left as session scratch files or external URLs:

Style Photos Source
Gardening styles/gardening/photos/pond-teich-morgen.jpg, pond-overview.jpg The literal pond behind chatbot-garden's Teich-Morgen palette (also used in ~/chatbot-garden/backend/ui/assets/pond/)
Bonfire styles/bonfire/photos/funkenflug-sparks.jpg, erntetag-gathering.jpg A long-exposure night shot of sparks (Funkenflug) and a real Erntedank harvest-festival bonfire in daylight (Erntetag)
Sailplane styles/sailplane/photos/dusk-tideline.jpg, aloft-cloud-deck.jpg Dusk on the Vancouver tideline, and the view above the cloud deck from an actual glider flight

All resized to a max 900px edge and stripped of EXIF before committing (originals were camera-resolution, up to 8MB — unnecessary for a 56px thumbnail). Referenced both as the gallery cards' contact-sheet strip and named explicitly in each panel's own Styles section copy, so the claim appears at both the point of proof (thumbnail) and the point of assertion (prose).

Anti-patterns #

  • Corporate chrome — Stripe gradients, Notion toggles, Linear dark mode out of context
  • Scale-first vocabulary — no "users", "growth", "engagement", "onboarding"
  • Product launch aesthetics — no countdown CTAs, no "Get started free", no hero animations
  • Cold palette without warmth — no slate-and-teal, no purple gradients
  • Infinite scroll
  • Authorless generation — no AI output without recorded intention in this file or a style's own style.md
  • Silent season/style mixing anywhere but here — this page is the named exception; a real tilde site commits to one style
  • Letting the switcher become an excuse to skip grounding — every style added here must still pass through /tilde-style language and get its own real metaphor + (ideally) real photos, not just a plausible palette

Motion #

  • Minimal. Panel switching is instant (no crossfade) — deliberate, since a transition between three unrelated visual worlds reads as a glitch, not polish.
  • Hover transitions on cards/links: 150ms–300ms ease max.
  • All animations have a prefers-reduced-motion: reduce counterpart.

Known gaps #

  • Mobile nav pattern for #style-switcher not yet stress-tested beyond the existing gallery breakpoint at 720px.
  • Only 2 photos shown per style; more exist for Bonfire/Sailplane (Immich, ~/Pictures/sailing/) if a deeper "provenance" page is ever built.
  • No defined grid for multi-column layouts beyond what each style's own style.md specifies.

Provenance #

  • v0.1 (2026-06-17–2026-07-20) — single-style homepage, Bonfire only, night-first, no dawn mode built. Superseded, not deleted: preserved as styles/bonfire/style-v0.1.md.
  • v0.2 (2026-07-21) — rebuilt as the three-style gallery + switcher described above, once Gardening and a properly-grounded Sailplane/Bonfire v0.2 all existed as real, documented, contributed styles worth showing side by side. Photo contact-sheets added same day, after the initial switcher build shipped without them.