{"slug":"section-blocks","title":"section-blocks","tags":["site-building","frontend","section","blocks"],"agent_summary":"Philosophy Every block follows these non-negotiable principles: 1","trigger_phrases":["section-blocks","section guide","blocks guide","section blocks","lego blocks","hero block"],"runnable":true,"markdown":"**Trigger:** Use when \"section blocks\", \"lego blocks\", \"hero block\". Next.js + Tailwind + framer-motion blocks. A catalog of production-ready, conversion-optimized TSX section components for local business websites.\n\n### Philosophy\n\nEvery block follows these non-negotiable principles:\n1. Self-contained — drop-in component, no cross-dependencies outside the shared stack\n2. Conversion-first — every visual decision serves a psychological trigger: trust, urgency, authority, social proof, reciprocity, or clarity\n3. Shortcode-driven — brand variables injected via `{{SHORTCODE}}` placeholders. Fill from BRAND.md before shipping\n4. Premium by default — no stock template feel. Dark surfaces, intentional typography, precise spacing\n5. Mobile-first — every block is responsive. Desktop enhances; mobile converts\n\n### The Stack\n\nAll blocks are written for:\n- Next.js 16+ (App Router compatible, Turbopack)\n- Tailwind CSS v4 — see architecture rule below\n- framer-motion v12+ (npm i framer-motion)\n- lucide-react (npm i lucide-react)\n- TypeScript\n\n### CRITICAL ARCHITECTURE RULE — Named CSS Classes (NOT Raw Tailwind Utilities)\n\nTailwind 4 with Turbopack does NOT scan utility classes from large agent-generated files. This means raw Tailwind utilities in className will NOT be in the compiled CSS and the page will render completely unstyled.\n\nDO — Named CSS Classes:\n```tsx\n<section className=\"hero\">\n  <div className=\"hero__inner\">\n    <h1 className=\"hero-headline\">Tampa Bay's Most Trusted Roofer</h1>\n    <a href=\"#\" className=\"btn-primary-cta\">Get Free Inspection</a>\n  </div>\n</section>\n```\n\n```css\n/* In globals.css — statically defined, always included */\n.hero { background-color: var(--color-primary); min-height: 90vh; }\n.hero__inner { max-width: 1280px; margin: 0 auto; padding: 8rem 1.5rem; }\n.hero-headline { font-size: clamp(2.5rem, 6vw, 4.5rem); color: #ffffff; font-weight: 900; }\n.btn-primary-cta { background-color: var(--color-accent); padding: 1rem 2rem; border-radius: 1rem; }\n```\n\nDO NOT — Raw Tailwind utilities for layout/color/spacing (these will NOT render in Tailwind 4 + Turbopack if generated by an agent):\n```tsx\n<section className=\"bg-[#1a2744] min-h-[90vh]\">\n  <div className=\"max-w-7xl mx-auto px-6 py-32\">\n```\n\nWhat IS safe to use inline: Standard responsive utilities that exist in Tailwind's default config — `hidden`, `block`, `flex`, `grid`, `sm:block`, `md:flex`, `lg:grid`, `lg:hidden`, `sm:flex`.\n\n### CSS Variables Pattern\n\nAlways define brand colors as CSS variables in globals.css:\n```css\n:root {\n  --color-primary: #1a2744;\n  --color-primary-dark: #0d1526;\n  --color-accent: #e8441a;\n  --color-accent-hover: #d03a15;\n  --max-width: 1280px;\n}\n```\n\nThen reference them in named CSS classes. Never hardcode hex values in JSX className attributes.\n\n### framer-motion Rules for Section Blocks\n\n- Hero content: NO `initial={{ opacity: 0 }}` on hero elements — they must be visible on page load\n- Below-fold whileInView: Safe to use `initial={{ opacity: 1, y: 20 }}` with `whileInView={{ opacity: 1, y: 0 }}`\n- NEVER use `initial={{ opacity: 0 }}` with whileInView — content will be invisible until user scrolls\n- Mobile menus and accordions: `initial={{ opacity: 0, height: 0 }}` is correct for collapsed state\n\n### globals.css @source Directive\n\nAlways include at the top of globals.css to ensure Tailwind scans source files:\n```css\n@import \"tailwindcss\";\n@source \"../../**/*.{ts,tsx,js,jsx}\";\n```\n\n### Shortcode Reference\n\n| Shortcode | Description | Example |\n|---|---|---|\n| `{{BUSINESS_NAME}}` | Full business name | \"Apex Roofing & Restoration\" |\n| `{{HERO_HEADLINE}}` | Primary H1 — conversion-focused | \"Roof Replacement Done Right the First Time\" |\n| `{{HERO_SUBHEADLINE}}` | Supporting sentence under H1 | \"Sarasota's most trusted roofing crew since 2009\" |\n| `{{PHONE}}` | Click-to-call phone number | \"(941) 555-1234\" |\n| `{{CTA_PRIMARY}}` | Primary button text | \"Get a Free Estimate\" |\n| `{{TRUST_STATEMENT}}` | Short trust line | \"Licensed • Insured • 5-Star Rated\" |\n| `{{YEARS_IN_BUSINESS}}` | Years operating | \"15\" |\n| `{{REVIEW_COUNT}}` | Total review count | \"400+\" |\n| `{{STAR_RATING}}` | Average star rating | \"4.9\" |\n| `{{JOBS_COMPLETED}}` | Total jobs done | \"2,400+\" |\n| `{{CITY}}` | Primary city served | \"Sarasota\" |\n| `{{FOUNDED_YEAR}}` | Year founded | \"2009\" |\n| `{{TAGLINE}}` | Brand tagline | \"Built Tough. Done Right.\" |\n\n### Block Catalog\n\n| Category | Blocks |\n|----------|--------|\n| Hero Blocks | hero-dominant, hero-split, hero-statement, hero-form |\n| Trust Blocks | trust-bar, trust-badges, reviews-strip, reviews-featured, stats-row |\n| Service Blocks | services-grid-3, services-list, services-featured, services-tabs |\n| Process Blocks | process-steps, process-timeline |\n| CTA Blocks | cta-banner, cta-sticky-header, cta-footer-form |\n| Social Proof Blocks | proof-logos, proof-before-after, proof-case-study |\n| Local / Geo Blocks | areas-grid, areas-map-placeholder, local-trust |\n| Content Blocks | faq-accordion, about-split, guarantee-block |\n\n### Animation Standards — Required Pattern\n\nNEVER use this pattern (causes blank page on load):\n```tsx\n// BAD — entire section invisible until scroll triggers\nconst ref = useRef(null)\nconst isInView = useInView(ref, { once: true })\nreturn (\n  <motion.div ref={ref} initial={{ opacity: 0, y: 40 }}\n    animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 40 }}>\n```\n\nALWAYS use this pattern instead:\n```tsx\n// GOOD — uses whileInView prop, no refs needed, content visible in DOM\n<motion.div\n  initial={{ opacity: 0, y: 30 }}\n  whileInView={{ opacity: 1, y: 0 }}\n  viewport={{ once: true, margin: \"-100px\" }}\n  transition={{ duration: 0.5, ease: \"easeOut\" }}\n>\n```\n\nHero Section Exception — NO animations. Hero content (H1, subheadline, CTAs, trust bar) 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### Page Assembly Recipes\n\n**Homepage — Home Services (Roofing, HVAC, Plumbing):**\nHeroDominant → TrustBar → ServicesGrid3 → StatsRow → ReviewsStrip → ProcessSteps → CtaBanner → FaqAccordion → CtaFooterForm\n\n**Homepage — Premium / Professional Services (Law, Med Spa, Finance):**\nHeroStatement → TrustBadges → ServicesGrid3 → ReviewsFeatured → ProcessSteps → GuaranteeBlock → CtaBanner → FaqAccordion → CtaFooterForm\n\n**Homepage — Multi-Service Contractor (Landscaping, Cleaning, Restoration):**\nHeroSplit → TrustBar → ServicesFeatured → StatsRow → ProofBeforeAfter → ReviewsStrip → LocalTrust → CtaFooterForm\n\n**Service Page (Individual Service):**\nHeroSplit → TrustBar → FaqAccordion → ReviewsStrip → CtaBanner\n\n**About Page:**\nHeroStatement → StatsRow → AboutSplit → ReviewsFeatured → TrustBadges → CtaFooterForm\n\n**Contact / Estimate Page:**\nHeroStatement → TrustBar → CtaFooterForm → ReviewsStrip\n\n**Service Area Page (City Landing Page):**\nHeroSplit → TrustBar → ServicesGrid3 → ReviewsStrip → LocalTrust → CtaBanner\n\n---\n","html":"<p><strong>Trigger:</strong> Use when \"section blocks\", \"lego blocks\", \"hero block\". Next.js + Tailwind + framer-motion blocks. A catalog of production-ready, conversion-optimized TSX section components for local business websites.</p>\n<h3>Philosophy</h3>\n<p>Every block follows these non-negotiable principles:</p>\n<ol>\n<li>Self-contained — drop-in component, no cross-dependencies outside the shared stack</li>\n<li>Conversion-first — every visual decision serves a psychological trigger: trust, urgency, authority, social proof, reciprocity, or clarity</li>\n<li>Shortcode-driven — brand variables injected via <code>{{SHORTCODE}}</code> placeholders. Fill from BRAND.md before shipping</li>\n<li>Premium by default — no stock template feel. Dark surfaces, intentional typography, precise spacing</li>\n<li>Mobile-first — every block is responsive. Desktop enhances; mobile converts</li>\n</ol>\n<h3>The Stack</h3>\n<p>All blocks are written for:</p>\n<ul>\n<li>Next.js 16+ (App Router compatible, Turbopack)</li>\n<li>Tailwind CSS v4 — see architecture rule below</li>\n<li>framer-motion v12+ (npm i framer-motion)</li>\n<li>lucide-react (npm i lucide-react)</li>\n<li>TypeScript</li>\n</ul>\n<h3>CRITICAL ARCHITECTURE RULE — Named CSS Classes (NOT Raw Tailwind Utilities)</h3>\n<p>Tailwind 4 with Turbopack does NOT scan utility classes from large agent-generated files. This means raw Tailwind utilities in className will NOT be in the compiled CSS and the page will render completely unstyled.</p>\n<p>DO — Named CSS Classes:</p>\n<pre><code class=\"language-tsx\">&#x3C;section className=\"hero\">\n  &#x3C;div className=\"hero__inner\">\n    &#x3C;h1 className=\"hero-headline\">Tampa Bay's Most Trusted Roofer&#x3C;/h1>\n    &#x3C;a href=\"#\" className=\"btn-primary-cta\">Get Free Inspection&#x3C;/a>\n  &#x3C;/div>\n&#x3C;/section>\n</code></pre>\n<pre><code class=\"language-css\">/* In globals.css — statically defined, always included */\n.hero { background-color: var(--color-primary); min-height: 90vh; }\n.hero__inner { max-width: 1280px; margin: 0 auto; padding: 8rem 1.5rem; }\n.hero-headline { font-size: clamp(2.5rem, 6vw, 4.5rem); color: #ffffff; font-weight: 900; }\n.btn-primary-cta { background-color: var(--color-accent); padding: 1rem 2rem; border-radius: 1rem; }\n</code></pre>\n<p>DO NOT — Raw Tailwind utilities for layout/color/spacing (these will NOT render in Tailwind 4 + Turbopack if generated by an agent):</p>\n<pre><code class=\"language-tsx\">&#x3C;section className=\"bg-[#1a2744] min-h-[90vh]\">\n  &#x3C;div className=\"max-w-7xl mx-auto px-6 py-32\">\n</code></pre>\n<p>What IS safe to use inline: Standard responsive utilities that exist in Tailwind's default config — <code>hidden</code>, <code>block</code>, <code>flex</code>, <code>grid</code>, <code>sm:block</code>, <code>md:flex</code>, <code>lg:grid</code>, <code>lg:hidden</code>, <code>sm:flex</code>.</p>\n<h3>CSS Variables Pattern</h3>\n<p>Always define brand colors as CSS variables in globals.css:</p>\n<pre><code class=\"language-css\">:root {\n  --color-primary: #1a2744;\n  --color-primary-dark: #0d1526;\n  --color-accent: #e8441a;\n  --color-accent-hover: #d03a15;\n  --max-width: 1280px;\n}\n</code></pre>\n<p>Then reference them in named CSS classes. Never hardcode hex values in JSX className attributes.</p>\n<h3>framer-motion Rules for Section Blocks</h3>\n<ul>\n<li>Hero content: NO <code>initial={{ opacity: 0 }}</code> on hero elements — they must be visible on page load</li>\n<li>Below-fold whileInView: Safe to use <code>initial={{ opacity: 1, y: 20 }}</code> with <code>whileInView={{ opacity: 1, y: 0 }}</code></li>\n<li>NEVER use <code>initial={{ opacity: 0 }}</code> with whileInView — content will be invisible until user scrolls</li>\n<li>Mobile menus and accordions: <code>initial={{ opacity: 0, height: 0 }}</code> is correct for collapsed state</li>\n</ul>\n<h3>globals.css @source Directive</h3>\n<p>Always include at the top of globals.css to ensure Tailwind scans source files:</p>\n<pre><code class=\"language-css\">@import \"tailwindcss\";\n@source \"../../**/*.{ts,tsx,js,jsx}\";\n</code></pre>\n<h3>Shortcode Reference</h3>\n<p>| Shortcode | Description | Example |\n|---|---|---|\n| <code>{{BUSINESS_NAME}}</code> | Full business name | \"Apex Roofing &#x26; Restoration\" |\n| <code>{{HERO_HEADLINE}}</code> | Primary H1 — conversion-focused | \"Roof Replacement Done Right the First Time\" |\n| <code>{{HERO_SUBHEADLINE}}</code> | Supporting sentence under H1 | \"Sarasota's most trusted roofing crew since 2009\" |\n| <code>{{PHONE}}</code> | Click-to-call phone number | \"(941) 555-1234\" |\n| <code>{{CTA_PRIMARY}}</code> | Primary button text | \"Get a Free Estimate\" |\n| <code>{{TRUST_STATEMENT}}</code> | Short trust line | \"Licensed • Insured • 5-Star Rated\" |\n| <code>{{YEARS_IN_BUSINESS}}</code> | Years operating | \"15\" |\n| <code>{{REVIEW_COUNT}}</code> | Total review count | \"400+\" |\n| <code>{{STAR_RATING}}</code> | Average star rating | \"4.9\" |\n| <code>{{JOBS_COMPLETED}}</code> | Total jobs done | \"2,400+\" |\n| <code>{{CITY}}</code> | Primary city served | \"Sarasota\" |\n| <code>{{FOUNDED_YEAR}}</code> | Year founded | \"2009\" |\n| <code>{{TAGLINE}}</code> | Brand tagline | \"Built Tough. Done Right.\" |</p>\n<h3>Block Catalog</h3>\n<p>| Category | Blocks |\n|----------|--------|\n| Hero Blocks | hero-dominant, hero-split, hero-statement, hero-form |\n| Trust Blocks | trust-bar, trust-badges, reviews-strip, reviews-featured, stats-row |\n| Service Blocks | services-grid-3, services-list, services-featured, services-tabs |\n| Process Blocks | process-steps, process-timeline |\n| CTA Blocks | cta-banner, cta-sticky-header, cta-footer-form |\n| Social Proof Blocks | proof-logos, proof-before-after, proof-case-study |\n| Local / Geo Blocks | areas-grid, areas-map-placeholder, local-trust |\n| Content Blocks | faq-accordion, about-split, guarantee-block |</p>\n<h3>Animation Standards — Required Pattern</h3>\n<p>NEVER use this pattern (causes blank page on load):</p>\n<pre><code class=\"language-tsx\">// BAD — entire section invisible until scroll triggers\nconst ref = useRef(null)\nconst isInView = useInView(ref, { once: true })\nreturn (\n  &#x3C;motion.div ref={ref} initial={{ opacity: 0, y: 40 }}\n    animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 40 }}>\n</code></pre>\n<p>ALWAYS use this pattern instead:</p>\n<pre><code class=\"language-tsx\">// GOOD — uses whileInView prop, no refs needed, content visible in DOM\n&#x3C;motion.div\n  initial={{ opacity: 0, y: 30 }}\n  whileInView={{ opacity: 1, y: 0 }}\n  viewport={{ once: true, margin: \"-100px\" }}\n  transition={{ duration: 0.5, ease: \"easeOut\" }}\n>\n</code></pre>\n<p>Hero Section Exception — NO animations. Hero content (H1, subheadline, CTAs, trust bar) 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>Page Assembly Recipes</h3>\n<p><strong>Homepage — Home Services (Roofing, HVAC, Plumbing):</strong>\nHeroDominant → TrustBar → ServicesGrid3 → StatsRow → ReviewsStrip → ProcessSteps → CtaBanner → FaqAccordion → CtaFooterForm</p>\n<p><strong>Homepage — Premium / Professional Services (Law, Med Spa, Finance):</strong>\nHeroStatement → TrustBadges → ServicesGrid3 → ReviewsFeatured → ProcessSteps → GuaranteeBlock → CtaBanner → FaqAccordion → CtaFooterForm</p>\n<p><strong>Homepage — Multi-Service Contractor (Landscaping, Cleaning, Restoration):</strong>\nHeroSplit → TrustBar → ServicesFeatured → StatsRow → ProofBeforeAfter → ReviewsStrip → LocalTrust → CtaFooterForm</p>\n<p><strong>Service Page (Individual Service):</strong>\nHeroSplit → TrustBar → FaqAccordion → ReviewsStrip → CtaBanner</p>\n<p><strong>About Page:</strong>\nHeroStatement → StatsRow → AboutSplit → ReviewsFeatured → TrustBadges → CtaFooterForm</p>\n<p><strong>Contact / Estimate Page:</strong>\nHeroStatement → TrustBar → CtaFooterForm → ReviewsStrip</p>\n<p><strong>Service Area Page (City Landing Page):</strong>\nHeroSplit → TrustBar → ServicesGrid3 → ReviewsStrip → LocalTrust → CtaBanner</p>\n<hr>\n"}