S
Site Building SOPKnowledge Base
Search
← All topics

section-blocks

runnable

Philosophy Every block follows these non-negotiable principles: 1

site-buildingfrontendsectionblocks
Agent trigger phrases: section-blocks · section guide · blocks guide · section blocks · lego blocks · hero block

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.

Philosophy

Every block follows these non-negotiable principles:

  1. Self-contained — drop-in component, no cross-dependencies outside the shared stack
  2. Conversion-first — every visual decision serves a psychological trigger: trust, urgency, authority, social proof, reciprocity, or clarity
  3. Shortcode-driven — brand variables injected via {{SHORTCODE}} placeholders. Fill from BRAND.md before shipping
  4. Premium by default — no stock template feel. Dark surfaces, intentional typography, precise spacing
  5. Mobile-first — every block is responsive. Desktop enhances; mobile converts

The Stack

All blocks are written for:

  • Next.js 16+ (App Router compatible, Turbopack)
  • Tailwind CSS v4 — see architecture rule below
  • framer-motion v12+ (npm i framer-motion)
  • lucide-react (npm i lucide-react)
  • TypeScript

CRITICAL ARCHITECTURE RULE — Named CSS Classes (NOT Raw Tailwind Utilities)

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.

DO — Named CSS Classes:

<section className="hero">
  <div className="hero__inner">
    <h1 className="hero-headline">Tampa Bay's Most Trusted Roofer</h1>
    <a href="#" className="btn-primary-cta">Get Free Inspection</a>
  </div>
</section>
/* In globals.css — statically defined, always included */
.hero { background-color: var(--color-primary); min-height: 90vh; }
.hero__inner { max-width: 1280px; margin: 0 auto; padding: 8rem 1.5rem; }
.hero-headline { font-size: clamp(2.5rem, 6vw, 4.5rem); color: #ffffff; font-weight: 900; }
.btn-primary-cta { background-color: var(--color-accent); padding: 1rem 2rem; border-radius: 1rem; }

DO NOT — Raw Tailwind utilities for layout/color/spacing (these will NOT render in Tailwind 4 + Turbopack if generated by an agent):

<section className="bg-[#1a2744] min-h-[90vh]">
  <div className="max-w-7xl mx-auto px-6 py-32">

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

CSS Variables Pattern

Always define brand colors as CSS variables in globals.css:

:root {
  --color-primary: #1a2744;
  --color-primary-dark: #0d1526;
  --color-accent: #e8441a;
  --color-accent-hover: #d03a15;
  --max-width: 1280px;
}

Then reference them in named CSS classes. Never hardcode hex values in JSX className attributes.

framer-motion Rules for Section Blocks

  • Hero content: NO initial={{ opacity: 0 }} on hero elements — they must be visible on page load
  • Below-fold whileInView: Safe to use initial={{ opacity: 1, y: 20 }} with whileInView={{ opacity: 1, y: 0 }}
  • NEVER use initial={{ opacity: 0 }} with whileInView — content will be invisible until user scrolls
  • Mobile menus and accordions: initial={{ opacity: 0, height: 0 }} is correct for collapsed state

globals.css @source Directive

Always include at the top of globals.css to ensure Tailwind scans source files:

@import "tailwindcss";
@source "../../**/*.{ts,tsx,js,jsx}";

Shortcode Reference

| Shortcode | Description | Example | |---|---|---| | {{BUSINESS_NAME}} | Full business name | "Apex Roofing & Restoration" | | {{HERO_HEADLINE}} | Primary H1 — conversion-focused | "Roof Replacement Done Right the First Time" | | {{HERO_SUBHEADLINE}} | Supporting sentence under H1 | "Sarasota's most trusted roofing crew since 2009" | | {{PHONE}} | Click-to-call phone number | "(941) 555-1234" | | {{CTA_PRIMARY}} | Primary button text | "Get a Free Estimate" | | {{TRUST_STATEMENT}} | Short trust line | "Licensed • Insured • 5-Star Rated" | | {{YEARS_IN_BUSINESS}} | Years operating | "15" | | {{REVIEW_COUNT}} | Total review count | "400+" | | {{STAR_RATING}} | Average star rating | "4.9" | | {{JOBS_COMPLETED}} | Total jobs done | "2,400+" | | {{CITY}} | Primary city served | "Sarasota" | | {{FOUNDED_YEAR}} | Year founded | "2009" | | {{TAGLINE}} | Brand tagline | "Built Tough. Done Right." |

Block Catalog

| Category | Blocks | |----------|--------| | Hero Blocks | hero-dominant, hero-split, hero-statement, hero-form | | Trust Blocks | trust-bar, trust-badges, reviews-strip, reviews-featured, stats-row | | Service Blocks | services-grid-3, services-list, services-featured, services-tabs | | Process Blocks | process-steps, process-timeline | | CTA Blocks | cta-banner, cta-sticky-header, cta-footer-form | | Social Proof Blocks | proof-logos, proof-before-after, proof-case-study | | Local / Geo Blocks | areas-grid, areas-map-placeholder, local-trust | | Content Blocks | faq-accordion, about-split, guarantee-block |

Animation Standards — Required Pattern

NEVER use this pattern (causes blank page on load):

// BAD — entire section invisible until scroll triggers
const ref = useRef(null)
const isInView = useInView(ref, { once: true })
return (
  <motion.div ref={ref} initial={{ opacity: 0, y: 40 }}
    animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 40 }}>

ALWAYS use this pattern instead:

// GOOD — uses whileInView prop, no refs needed, content visible in DOM
<motion.div
  initial={{ opacity: 0, y: 30 }}
  whileInView={{ opacity: 1, y: 0 }}
  viewport={{ once: true, margin: "-100px" }}
  transition={{ duration: 0.5, ease: "easeOut" }}
>

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.

Page Assembly Recipes

Homepage — Home Services (Roofing, HVAC, Plumbing): HeroDominant → TrustBar → ServicesGrid3 → StatsRow → ReviewsStrip → ProcessSteps → CtaBanner → FaqAccordion → CtaFooterForm

Homepage — Premium / Professional Services (Law, Med Spa, Finance): HeroStatement → TrustBadges → ServicesGrid3 → ReviewsFeatured → ProcessSteps → GuaranteeBlock → CtaBanner → FaqAccordion → CtaFooterForm

Homepage — Multi-Service Contractor (Landscaping, Cleaning, Restoration): HeroSplit → TrustBar → ServicesFeatured → StatsRow → ProofBeforeAfter → ReviewsStrip → LocalTrust → CtaFooterForm

Service Page (Individual Service): HeroSplit → TrustBar → FaqAccordion → ReviewsStrip → CtaBanner

About Page: HeroStatement → StatsRow → AboutSplit → ReviewsFeatured → TrustBadges → CtaFooterForm

Contact / Estimate Page: HeroStatement → TrustBar → CtaFooterForm → ReviewsStrip

Service Area Page (City Landing Page): HeroSplit → TrustBar → ServicesGrid3 → ReviewsStrip → LocalTrust → CtaBanner