S
Site Building SOPKnowledge Base
Search
← All topics

Frankie's Accumulated Learnings

These are production patterns learned through real agency builds

site-buildingfrontendfrankie'saccumulatedlearnings
Agent trigger phrases: frankie's accumulated learnings · frankie's guide · accumulated guide · learnings guide

These are production patterns learned through real agency builds. Apply them on every project.

Tailwind 4 + Turbopack — Named CSS Classes Architecture

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.

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.

Never: className="bg-[#1a2744] px-6 py-4 text-white font-bold" Always: className="hero-card" with .hero-card { background-color: var(--color-primary); padding: 1.5rem 2rem; color: white; font-weight: bold; } in globals.css

ShadCN v5 Install Pattern

ShadCN 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.

Fix: 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.

Also: Add all brand vars to :root (not just .light) so they work as defaults without data-theme attr.

Server Components Event Handlers

Server components cannot have onMouseEnter/onMouseLeave or any event handlers. Add "use client" to any component with event handlers.

framer-motion Animation Patterns

NEVER 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" }}.

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.

Next.js Font Loading

Always use next/font/google for Google Fonts. Never use <link> tags or external CDN. Apply font variables on <html> element.

next/image Rules

ALL images use next/image. Never use <img> tags. Above-fold hero: use priority prop. Below-fold: default lazy loading.

Image sources: Always local (/images/site/). Never use Unsplash, Pexels, or any stock photo CDN.

Shared Working Trees (Multi-Agent Git)

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.

Class-Based Dark Mode Verification

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.

Mobile Patterns

Mobile horizontal scroll: flex overflow-x-auto snap-x snap-mandatory + min-w-[200px] snap-start flex-shrink-0 on items.

Gradient fade scroll indicator: absolute right-0 w-8 bg-gradient-to-l from-[page-bg] to-transparent pointer-events-none md:hidden

Touch target pattern: min-h-11 min-w-[44px] flex items-center justify-center

CSS Techniques

  • CSS conic-gradient for donut charts without SVG or JS
  • CSS keyframe radar sweep (rotating conic-gradient) — strong ops-aesthetic element
  • IntersectionObserver for scroll-spy: threshold 0.3 works for ~900px sections
  • Self-contained HTML galleries: @import for Google Fonts (single external dep), inline everything else

End of site-corpus.md — 18 skills compiled for Frankie's Site Building SOP knowledge base.