{"slug":"frankies-accumulated-learnings","title":"Frankie's Accumulated Learnings","tags":["site-building","frontend","frankie's","accumulated","learnings"],"agent_summary":"These are production patterns learned through real agency builds","trigger_phrases":["frankie's accumulated learnings","frankie's guide","accumulated guide","learnings guide"],"runnable":false,"markdown":"These are production patterns learned through real agency builds. Apply them on every project.\n\n### Tailwind 4 + Turbopack — Named CSS Classes Architecture\n\nTailwind 4 with Turbopack does NOT scan utility classes from large agent-generated files. This is both a Mike standing order AND a technical requirement.\n\nRule: All layout, color, and spacing go in named CSS classes in globals.css. Only structural Tailwind utilities (flex, grid, hidden, responsive breakpoints) are safe inline.\n\nNever: `className=\"bg-[#1a2744] px-6 py-4 text-white font-bold\"`\nAlways: `className=\"hero-card\"` with `.hero-card { background-color: var(--color-primary); padding: 1.5rem 2rem; color: white; font-weight: bold; }` in globals.css\n\n### ShadCN v5 Install Pattern\n\nShadCN v5 init (base-nova style) injects `@import \"tw-animate-css\"` and `@import \"shadcn/tailwind.css\"` into globals.css. These BREAK builds in workspace-root situations.\n\nFix: Remove both injected imports. Tailwind v3 projects only need `@tailwind base/components/utilities`. ShadCN v5 semantic tokens (bg-card, text-foreground, text-muted-foreground, bg-muted) need CSS custom properties in :root. Reference them in tailwind.config.ts using `hsl(var(--token))` pattern.\n\nAlso: Add all brand vars to :root (not just .light) so they work as defaults without data-theme attr.\n\n### Server Components Event Handlers\n\nServer components cannot have onMouseEnter/onMouseLeave or any event handlers. Add \"use client\" to any component with event handlers.\n\n### framer-motion Animation Patterns\n\nNEVER use `initial={{ opacity: 0 }}` with `useInView` — content will be invisible until JS fires AND user scrolls. Use `whileInView` instead with `viewport={{ once: true, margin: \"-100px\" }}`.\n\nHero content must NEVER use initial opacity animations. Hero content must be visible immediately on page load. Use static rendering for all above-the-fold content.\n\n### Next.js Font Loading\n\nAlways use `next/font/google` for Google Fonts. Never use `<link>` tags or external CDN. Apply font variables on `<html>` element.\n\n### next/image Rules\n\nALL images use `next/image`. Never use `<img>` tags. Above-fold hero: use `priority` prop. Below-fold: default lazy loading.\n\nImage sources: Always local (/images/site/). Never use Unsplash, Pexels, or any stock photo CDN.\n\n### Shared Working Trees (Multi-Agent Git)\n\nWhen sharing a git working tree with another agent: stage ONLY your files. Never use git add -A. Commit on isolated branch. Never git add files owned by other agents.\n\n### Class-Based Dark Mode Verification\n\nPlaywright emulateMedia colorScheme dark does NOT trigger next-themes class-based dark mode. CSS .dark selectors are correct — just can't verify via Playwright media emulation. Verify dark mode manually in browser.\n\n### Mobile Patterns\n\nMobile horizontal scroll: `flex overflow-x-auto snap-x snap-mandatory` + `min-w-[200px] snap-start flex-shrink-0` on items.\n\nGradient fade scroll indicator: `absolute right-0 w-8 bg-gradient-to-l from-[page-bg] to-transparent pointer-events-none md:hidden`\n\nTouch target pattern: `min-h-11 min-w-[44px] flex items-center justify-center`\n\n### CSS Techniques\n\n- CSS conic-gradient for donut charts without SVG or JS\n- CSS keyframe radar sweep (rotating conic-gradient) — strong ops-aesthetic element\n- IntersectionObserver for scroll-spy: threshold 0.3 works for ~900px sections\n- Self-contained HTML galleries: @import for Google Fonts (single external dep), inline everything else\n\n---\n\n*End of site-corpus.md — 18 skills compiled for Frankie's Site Building SOP knowledge base.*\n","html":"<p>These are production patterns learned through real agency builds. Apply them on every project.</p>\n<h3>Tailwind 4 + Turbopack — Named CSS Classes Architecture</h3>\n<p>Tailwind 4 with Turbopack does NOT scan utility classes from large agent-generated files. This is both a Mike standing order AND a technical requirement.</p>\n<p>Rule: All layout, color, and spacing go in named CSS classes in globals.css. Only structural Tailwind utilities (flex, grid, hidden, responsive breakpoints) are safe inline.</p>\n<p>Never: <code>className=\"bg-[#1a2744] px-6 py-4 text-white font-bold\"</code>\nAlways: <code>className=\"hero-card\"</code> with <code>.hero-card { background-color: var(--color-primary); padding: 1.5rem 2rem; color: white; font-weight: bold; }</code> in globals.css</p>\n<h3>ShadCN v5 Install Pattern</h3>\n<p>ShadCN v5 init (base-nova style) injects <code>@import \"tw-animate-css\"</code> and <code>@import \"shadcn/tailwind.css\"</code> into globals.css. These BREAK builds in workspace-root situations.</p>\n<p>Fix: Remove both injected imports. Tailwind v3 projects only need <code>@tailwind base/components/utilities</code>. ShadCN v5 semantic tokens (bg-card, text-foreground, text-muted-foreground, bg-muted) need CSS custom properties in :root. Reference them in tailwind.config.ts using <code>hsl(var(--token))</code> pattern.</p>\n<p>Also: Add all brand vars to :root (not just .light) so they work as defaults without data-theme attr.</p>\n<h3>Server Components Event Handlers</h3>\n<p>Server components cannot have onMouseEnter/onMouseLeave or any event handlers. Add \"use client\" to any component with event handlers.</p>\n<h3>framer-motion Animation Patterns</h3>\n<p>NEVER use <code>initial={{ opacity: 0 }}</code> with <code>useInView</code> — content will be invisible until JS fires AND user scrolls. Use <code>whileInView</code> instead with <code>viewport={{ once: true, margin: \"-100px\" }}</code>.</p>\n<p>Hero content must NEVER use initial opacity animations. Hero content must be visible immediately on page load. Use static rendering for all above-the-fold content.</p>\n<h3>Next.js Font Loading</h3>\n<p>Always use <code>next/font/google</code> for Google Fonts. Never use <code>&#x3C;link></code> tags or external CDN. Apply font variables on <code>&#x3C;html></code> element.</p>\n<h3>next/image Rules</h3>\n<p>ALL images use <code>next/image</code>. Never use <code>&#x3C;img></code> tags. Above-fold hero: use <code>priority</code> prop. Below-fold: default lazy loading.</p>\n<p>Image sources: Always local (/images/site/). Never use Unsplash, Pexels, or any stock photo CDN.</p>\n<h3>Shared Working Trees (Multi-Agent Git)</h3>\n<p>When sharing a git working tree with another agent: stage ONLY your files. Never use git add -A. Commit on isolated branch. Never git add files owned by other agents.</p>\n<h3>Class-Based Dark Mode Verification</h3>\n<p>Playwright emulateMedia colorScheme dark does NOT trigger next-themes class-based dark mode. CSS .dark selectors are correct — just can't verify via Playwright media emulation. Verify dark mode manually in browser.</p>\n<h3>Mobile Patterns</h3>\n<p>Mobile horizontal scroll: <code>flex overflow-x-auto snap-x snap-mandatory</code> + <code>min-w-[200px] snap-start flex-shrink-0</code> on items.</p>\n<p>Gradient fade scroll indicator: <code>absolute right-0 w-8 bg-gradient-to-l from-[page-bg] to-transparent pointer-events-none md:hidden</code></p>\n<p>Touch target pattern: <code>min-h-11 min-w-[44px] flex items-center justify-center</code></p>\n<h3>CSS Techniques</h3>\n<ul>\n<li>CSS conic-gradient for donut charts without SVG or JS</li>\n<li>CSS keyframe radar sweep (rotating conic-gradient) — strong ops-aesthetic element</li>\n<li>IntersectionObserver for scroll-spy: threshold 0.3 works for ~900px sections</li>\n<li>Self-contained HTML galleries: @import for Google Fonts (single external dep), inline everything else</li>\n</ul>\n<hr>\n<p><em>End of site-corpus.md — 18 skills compiled for Frankie's Site Building SOP knowledge base.</em></p>\n"}