# Anelia Wolf – Build-Plan & Komponenten-Vertrag Stand: 2026-09-02 · Grundlage: `docs/superpowers/specs/2026-09-02-anelia-wolf-website-design.md` (Abschnitt A = verbindliche Abweichungen, danach die Jury-Synthese). Dieser Plan ist der Vertrag, nach dem parallel arbeitende Agenten bauen. **Pfade, Exportnamen und Props sind verbindlich.** ## 0. Bereits vorhanden (nicht neu anlegen, nur erweitern) - `next.config.ts` (static export, trailingSlash), `src/app/globals.css` (Tokens, `.grain`, `.gold-text`, `.rule-gold`, `[data-theme]`), `src/app/layout.tsx` (Fonts Jost/DM Mono/Bodoni Moda → `--font-jost`, `--font-mono-face`, `--font-bodoni`; Tailwind `font-sans`/`font-mono`/`font-display`; Skip-Link; `SmoothScroll`). - `src/lib/site.ts` (`site`, `nav`, `legal`), `src/lib/utils.ts` (`cn`), `src/hooks/usePrefersReducedMotion.ts`, `src/components/providers/SmoothScroll.tsx` (Lenis + GSAP-Ticker, `window.lenis`). - `src/components/brand/WolfMark.tsx` (SVG-Näherung des Monogramms; Klassen `.wolfmark-v`, `.wolfmark-wolf`, Pfade mit `data-draw` + `pathLength="1"`, Gradient-Id `${idPrefix}wolf-gold`; Props `className`, `title`, `idPrefix`, `strokeWidth`). **Nicht verändern.** - `public/brand/README.md`, `public/photos/README.md` (Drop-in-Slots), `.claude/launch.json` (`anelia-dev`, Port 3000). Pakete: next 16.3, react 19.2, tailwindcss 4.3, motion 13 (`motion/react`), gsap 3.15 (`gsap/ScrollTrigger`, `gsap/SplitText`, `gsap/DrawSVGPlugin` – alle frei), lenis 1.3, clsx, tailwind-merge. Nichts weiteres installieren außer `server-only` (falls gewünscht). Tailwind v4: Utilities aus den Tokens: `bg-ink bg-ink-2 bg-ivory bg-bone text-gold text-gold-deep text-grey-warm text-grey-deep border-line-dark border-line-light` und Live-Tokens `bg-bg text-fg text-fg-muted text-accent border-line bg-surface`. Schrift: `font-sans` (Jost), `font-mono` (DM Mono), `font-display` (Bodoni Moda). ## 1. Globale Regeln für alle Agenten 1. Next 16 App Router, statischer Export: Server-Komponenten standardmäßig; `"use client"` nur wo Hooks/DOM. Keine `params`/`searchParams`, keine Route Handler, keine `fetch` zur Laufzeit, kein `localStorage`/`sessionStorage`/ `document.cookie`, keine externen Skripte/iframes/Fonts. Externe Links `target="_blank" rel="noopener noreferrer"`. 2. Alle GSAP-Nutzung in `useEffect`/`useLayoutEffect` mit `gsap.context()` + `ctx.revert()` im Cleanup; Plugins nur über `src/lib/gsap.ts`. `gsap.matchMedia()` mit Bedingungen `reduce: "(prefers-reduced-motion: reduce)"`, `desktop: "(min-width: 1024px) and (pointer: fine)"`. 3. Reduced motion: Endzustand sofort sichtbar. Ohne JS: Inhalte sichtbar (Initialzustände nur unter `html.js` setzen – `layout.tsx` fügt ein 1-Zeilen-Inline-Script hinzu, das `document.documentElement.classList.add("js")` setzt). 4. Bodoni Moda nie < 28 px; Gold-Text (`text-gold`, `.gold-text`) nur in `data-theme="dark"`; auf hell `text-gold-deep`. Radius 0 überall, keine Schatten, kein Bold (max. 500), ein Italic-Wort pro Headline (`` in `font-display italic`). 5. Alle Texte kommen aus `src/content/*.ts` – kein Copy in JSX. Deutsche Anführungszeichen „…“, Gedankenstrich „–“. 6. Ein `

` pro Seite, Landmarken (`header`, `main#inhalt`, `footer`), Alt-Texte, sichtbarer Fokus. 7. Jeder Agent arbeitet NUR in den ihm zugewiesenen Dateien. Fremde Dateien werden importiert, nicht editiert. Am Ende `npx tsc --noEmit`; Fehler in eigenen Dateien beheben. Fehlende Module aus dem Vertrag (noch nicht gebaut) sind der einzige erlaubte Fehlertyp und werden gemeldet. 8. Kein `next dev`/`next build` durch Foundation-/Page-Agenten (nur `tsc`). Build und Browser-QA übernehmen die Integrations-/QA-Agenten. ## 2. Komponenten-Vertrag ### 2.1 `src/lib/gsap.ts` (F1) ```ts export { gsap, ScrollTrigger, SplitText, DrawSVGPlugin }; // registriert, SSR-sicher (typeof window guard) export const EASE = { out: "expo.out", inOut: "power3.inOut", none: "none" } as const; export const DUR = { micro: 0.3, reveal: 0.6, lines: 0.9, door: 1.1, draw: 1.2, sheen: 0.8, rule: 0.9 } as const; export const MM = { reduce: "(prefers-reduced-motion: reduce)", desktop: "(min-width: 1024px) and (pointer: fine)", touch: "(pointer: coarse)" } as const; ``` ### 2.2 `src/lib/site.ts` (F2 erweitert) ```ts export const flags = { showPlaceholders: true, showFaq: true, showStimmen: false, showSpeakerPdf: false, showSecondTalk: false, show24hPromise: false, showIndustry: false, showTwins: true } as const; export const routes = { home: "/", coaching: "/leistungen/coaching/", trainings: "/leistungen/trainings/", keynotes: "/leistungen/keynotes/", impressum: "/impressum/", datenschutz: "/datenschutz/" } as const; export const mailto = { kennenlernen: "mailto:info@anelia-wolf.com?subject=Kennenlerngespr%C3%A4ch", training: "mailto:info@anelia-wolf.com?subject=Training%20anfragen", keynote: "mailto:info@anelia-wolf.com?subject=Keynote%20anfragen" } as const; ``` ### 2.3 `src/lib/assets.ts` (F2, nur in Server-Komponenten importieren) ```ts export function hasPublicFile(relPath: string): boolean; // fs.existsSync(path.join(process.cwd(), "public", relPath)) export function getPhotos(): { hero: string | null; portrait: string | null; stage: string | null }; export function getLogoSvg(): string | null; // Inhalt von public/brand/logo-mark.svg oder null ``` ### 2.4 `src/lib/legal.ts` (F2) ```ts export const LEGAL_TODO: string[]; // offene Pflichtangaben export function ph(label: string): string; // liefert "[label]" – Platzhalter-Text ``` ### 2.5 Content (F2) – `src/content/*.ts`, alle `as const`, Typen exportieren - `home.ts`: `hero`, `positioning`, `services`, `principle`, `about`, `audience`, `contact` (+ `termine`) – Copy 1:1 aus Spec §6. - `coaching.ts`, `trainings.ts`, `keynotes.ts`: `{ meta: {title, description}, masthead, eyebrow, h1: {before, em, after}, subline, cta: {label, href, suffix?, micro?}, facts: {label, value}[], situations: {h2, rows[]}, questions?, modules, rahmen, ablauf, faq, band: {h2, cta, micro} , ... }` – Copy 1:1 aus Spec §7. - `legal.ts`: Impressum- und Datenschutz-Abschnitte (`{ h2, paragraphs[] }[]`) aus `docs/superpowers/specs/legal-templates.md`, Platzhalter über `ph()`; kein OS-Plattform-Link; „Bezeichnung WOLF-Prinzip“. ### 2.6 Motion-Primitive (F1) – `src/components/motion/` ```tsx // 1px, scaleX 0→1, once children // SplitText lines + mask; wartet document.fonts.ready (Timeout 1.5s); reduce → statisch; setzt aria-label children // motion whileInView, once {svg} // animiert alle [data-draw]-Pfade im Kind (stroke-dasharray/offset, pathLength=1); scrub: ScrollTrigger auf eigenem Element // in clip-path-Maske, scale 1.06→1, 6% Parallax desktop // einmal pro Seite (template.tsx): tweent body-Variablen --bg --fg --fg-muted --accent --line --surface an [data-theme]-Grenzen (start "top 70%", end "top 30%", scrub 0.4) // 1px --accent Linie unter dem Header children // nur desktop+no-preference, ref + ein rAF // Vorhang + router.push; Modifier/extern/Anker → normal // einmal in layout.tsx; hört auf transition-store // src/components/motion/transition-store.ts: startTransition(href, label), subscribe(cb) ``` ### 2.7 Brand (F1) – `src/components/brand/` ```tsx // Server: getLogoSvg() ? inline SVG (Pfade bekommen data-draw, Klassen wie WolfMark) : {} // Client-Hülle um BrandMark: Draw-Sequenz V-links → V-rechts → Wolf → (handoff-Linie nach unten) → Sheen // HTML-Wordmark ANELIA WOLF + Regel + Unterzeile ``` ### 2.8 Layout (F1) – `src/components/layout/` ```tsx
// Client; fixed; Zeile 1 Masthead (≥1024, kollabiert nach 80px), Zeile 2 Logo | 3 Nav-Links | Kontakt + Button (≥1280) | Menü (<1024) // drei Slots (Rolle | center | „Deutsch & Englisch“), Hairlines oben/unten // Fullscreen, nummerierter Ledger, Fokus-Trap, Esc, inert