Setup Client Website
One-time onboarding flow for a new (or rebuilt) client/consumer site. Produces a modern, SEO-optimized Next.js site with real content, images, video embeds, structured data, and the infrastructure needed for programmatic SEO guide pages.
Scope boundary: this skill leaves the repo in a state where /t/<slug> guide pages can be produced. It does NOT write guide pages. All guide-page content generation is handled by the gsc-seo-page skill, which drives ~/social-autoposter/seo/generate_page.py. After running this skill, register the site in ~/social-autoposter/config.json and hand off to gsc-seo-page for every page.
Arguments
Provide the client name, domain (if any), and existing site URL (if any). Example: "Paperback Expert at paperbackexpert.com"
Prerequisites
- Google Cloud project under the m13v.com org (or create a new one)
- GitHub org or personal account
- PostHog account for analytics
- Google Search Console access
- Isolated browser MCP for visual comparison
Stack
- Next.js 16 (App Router) + React 19 + TypeScript
- Tailwind CSS 4 (inline theme via
@theme) - next/image for optimized images
- Google Cloud Run for hosting (with HTTPS Load Balancer + Certificate Manager)
- PostHog for analytics (CTA clicks, pageviews)
Phase 1: Audit and Research
1a. SEO Audit (if existing site)
Run parallel SEO agents to baseline the current site:
Launch 5 agents in parallel:
- seo-technical: crawlability, indexability, Core Web Vitals, mobile
- seo-content: E-E-A-T signals, readability, content depth
- seo-schema: existing structured data (JSON-LD, Microdata, RDFa)
- seo-performance: Lighthouse scores, LCP, CLS, TBT (desktop + mobile)
- seo-geo: AI crawler accessibility, llms.txt, citation readiness
Record all scores. These become the "before" baseline and the fix list for the new site.
1b. Crawl All Pages
Use an agent with WebFetch to discover and extract content from every page on the site:
- Fetch the homepage, extract all navigation and footer links
- Try common paths: /about, /services, /contact, /faq, /blog, /pricing, /testimonials, /privacy
- For each discovered page, extract:
- URL and page title
- All headings (h1 through h6) with hierarchy
- Full body text (quotes, testimonials, stats, descriptions)
- CTA text and link targets
- Form fields (if any)
- Navigation links (to discover more pages)
Output: Complete content inventory organized by page.
1c. Extract Visual Assets
Use the isolated browser to catalog images, videos, and embeds:
// In isolated browser, navigate to each page and run:
() => {
const imgs = Array.from(document.querySelectorAll('img')).map((img, i) => {
const rect = img.getBoundingClientRect();
return { idx: i, src: img.src, y: Math.round(rect.y), w: Math.round(rect.width), h: Math.round(rect.height) };
}).filter(x => x.w > 50);
const iframes = Array.from(document.querySelectorAll('iframe')).map(f => f.src);
return { imgs, iframes };
}
Key assets to identify and download:
- Logo (usually first image, top of page, ~200px wide)
- Hero images or background photos
- Client/team headshot photos (circular, 100-200px)
- Product images (book covers, screenshots, etc.)
- Social proof imagery (awards, certifications, partner logos)
- Video embeds (Vimeo, YouTube URLs)
- Scheduling widgets (Calendly, Cal.com URLs)
- Book cover strips / product galleries
Download all identified images to public/images/ with descriptive filenames.
1d. Take Full Page Screenshots
Capture full-page screenshots of every key page on the original site for visual reference:
For each page:
1. browser_navigate to URL
2. browser_take_screenshot with fullPage: true
3. Save as original-{pagename}-full.png
Phase 2: Scaffold Project
2a. Create Next.js App
cd ~
npx create-next-app@latest CLIENT-website --typescript --tailwind --eslint --app --src-dir --no-turbopack --import-alias "@/*"
cd ~/CLIENT-website
2b. Install @seo/components
npm install @m13v/seo-components@latest
npm install @seo/components@npm:@m13v/seo-components@latest
Both entries will appear in package.json:
"@m13v/seo-components": "^0.8.15",
"@seo/components": "npm:@m13v/seo-components@^0.8.15"
2c. Configure Theme (globals.css)
The theme uses CSS custom properties in :root mapped into Tailwind 4 via @theme inline. Always define both the CSS variable AND the Tailwind mapping. Every client gets a primary color, a dark variant, and an accent color at minimum.
@import "tailwindcss";
:root {
--background: #ffffff;
--foreground: #1a1a1a;
--primary: #073c61; /* Main brand color (navy, blue, green, etc.) */
--primary-dark: #052d49; /* Darker shade for footer, dark sections */
--cta: #e11010; /* CTA button color (red, orange, etc.) */
--cta-dark: #ae0c0c; /* CTA hover state */
--accent: #d4a843; /* Accent/highlight color (gold, yellow, etc.) */
--accent-light: #f0d88a; /* Light accent for badges */
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
--color-primary-dark: var(--primary-dark);
--color-cta: var(--cta);
--color-cta-dark: var(--cta-dark);
--color-accent: var(--accent);
--color-accent-light: var(--accent-light);
--font-sans: var(--font-inter);
--font-heading: var(--font-oswald);
}
body {
background: var(--background);
color: var(--foreground);
}
html {
scroll-behavior: smooth;
}
Color naming convention: Use semantic names (primary, cta, accent) in the skill templates below. When building for a specific client, you can also add client-specific names (e.g., --color-navy, --color-red, --color-gold) for readability.
2d. Configure Fonts and @seo/components (layout.tsx)
Use next/font/google with CSS variable mode. The body font goes on --font-sans, the heading font on --font-heading. Apply both variables to the <html> tag.
IMPORTANT: Route group architecture. The root layout must NOT include Header/Footer directly. Instead, use a (main) route group with its own layout for pages that need the site Header/Footer. SEO guide pages under /t/ also go inside (main) so they share the same Header/Footer as the rest of the site.
Root layout (src/app/layout.tsx): fonts, metadata, Organization JSON-LD, @seo/components styles, and {children} only.
import { Inter, Oswald } from "next/font/google";
import { HeadingAnchors } from "@seo/components";
import { SeoComponentsStyles } from "@seo/components/server";
const inter = Inter({ variable: "--font-inter", subsets: ["latin"] });
const oswald = Oswald({ variable: "--font-oswald", subsets: ["latin"] });
// Root layout: NO Header/Footer here
<html lang="en" className={`${inter.variable} ${oswald.variable} h-full antialiased`}>
<head>
<SeoComponentsStyles />
</head>
<body className="min-h-full flex flex-col font-sans">
<HeadingAnchors />
{children}
{/* Organization JSON-LD here */}
</body>
</html>
SeoComponentsStylesinjects the package's prebuilt Tailwind CSS for all @seo/componentsHeadingAnchorsauto-injectsidattributes on H2 elements for sidebar linking and anchor navigation
Main layout (src/app/(main)/layout.tsx): wraps all pages with Header/Footer.
import { Header } from "@/components/Header";
import { Footer } from "@/components/Footer";
export default function MainLayout({ children }: { children: React.ReactNode }) {
return (
<>
<Header />
<main className="flex-1">{children}</main>
<Footer />
</>
);
}
All page routes (homepage, about, wins, faq, precall, AND /t/ guide pages) go inside src/app/(main)/. The (main) directory is a Next.js route group: it does not affect URLs.
Font pairing guide:
- Professional services: Inter + Oswald (clean, authoritative)
- Creative/lifestyle: Lato + Playfair Display
- Tech/SaaS: DM Sans + Space Grotesk
- Legal/finance: Source Sans 3 + Merriweather
Phase 3: Build All Pages (Design System & Component Blueprints)
This section contains the exact design patterns, Tailwind class combinations, and component structures that produce a polished, professional website. Follow these blueprints precisely for every client site.
3a. Header Component Blueprint
Sticky nav with logo, dropdown menus, mobile hamburger, and CTA button.
"use client";
import Image from "next/image";
import Link from "next/link";
import { useState } from "react";
// PATTERN: Separate simple links from dropdown groups
const navLinks = [
{ href: "/", label: "Home" },
{ href: "/how-it-works", label: "How It Works" },
{ href: "/wins", label: "Client Results" },
];
const dropdowns = [
{
label: "About",
items: [
{ href: "/about", label: "Our Story" },
{ href: "/faq", label: "FAQ" },
{ href: "/blog", label: "Blog" },
{ href: "/contact", label: "Contact" },
],
},
// Add more dropdown groups as needed
];
export function Header() {
const [mobileOpen, setMobileOpen] = useState(false);
return (
<header className="sticky top-0 z-50 bg-white border-b border-gray-100 shadow-sm">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="flex h-16 items-center justify-between">
{/* Logo: always use next/image with priority */}
<Link href="/" className="flex items-center">
<Image src="/images/logo.png" alt="CLIENT_NAME" width={200} height={66} priority />
</Link>
{/* Desktop Nav */}
<nav className="hidden lg:flex items-center gap-6">
{navLinks.map((link) => (
<Link
key={link.href}
href={link.href}
className="font-heading text-sm font-semibold uppercase tracking-wider text-gray-700 hover:text-primary transition-colors"
/>
))}
{/* DROPDOWN PATTERN: group + group-hover for CSS-only dropdowns */}
{dropdowns.map((dropdown) => (
<div key={dropdown.label} className="relative group">
<button className="font-heading text-sm font-semibold uppercase tracking-wider text-gray-700 hover:text-primary transition-colors flex items-center gap-1">
{dropdown.label}
<svg className="h-4 w-4 transition-transform group-hover:rotate-180" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</button>
<div className="invisible opacity-0 group-hover:visible group-hover:opacity-100 transition-all duration-200 absolute top-full left-0 mt-1 w-56 rounded-md bg-white shadow-lg ring-1 ring-black/5 py-2 z-50">
{dropdown.items.map((item) => (
<Link key={item.href} href={item.href} className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 hover:text-primary transition-colors" />
))}
</div>
</div>
))}
{/* CTA BUTTON in nav */}
<Link
href="/precall"
className="rounded-md bg-cta px-5 py-2.5 font-heading text-sm font-semibold uppercase tracking-wider text-white hover:bg-cta-dark transition-colors"
/>
</nav>
{/* MOBILE HAMBURGER */}
<button className="lg:hidden p-2 text-gray-700" => setMobileOpen(!mobileOpen)}>
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
{mobileOpen ? (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
) : (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
)}
</svg>
</button>
</div>
{/* MOBILE NAV: flat list with section headers */}
{mobileOpen && (
<nav className="lg:hidden pb-4 space-y-1">
{navLinks.map((link) => (
<Link key={link.href} href={link.href} className="block py-2 font-heading text-sm font-semibold uppercase tracking-wider text-gray-700 hover:text-primary" => setMobileOpen(false)} />
))}
{dropdowns.map((dropdown) => (
<div key={dropdown.label}>
<span className="block py-2 font-heading text-xs font-bold uppercase tracking-wider text-gray-400 mt-2">{dropdown.label}</span>
{dropdown.items.map((item) => (
<Link key={item.href} href={item.href} className="block py-2 pl-4 font-heading text-sm font-semibold uppercase tracking-wider text-gray-700 hover:text-primary" => setMobileOpen(false)} />
))}
</div>
))}
<Link href="/precall" className="block rounded-md bg-cta px-5 py-2.5 text-center font-heading text-sm font-semibold uppercase tracking-wider text-white hover:bg-cta-dark mt-3" => setMobileOpen(false)} />
</nav>
)}
</div>
</header>
);
}
Key classes: sticky top-0 z-50, font-heading text-sm font-semibold uppercase tracking-wider, invisible opacity-0 group-hover:visible group-hover:opacity-100
3b. Footer Component Blueprint
4-column layout: Brand + description, Company links, Resource links, CTA + contact info. Social icons row at bottom.
import Image from "next/image";
import Link from "next/link";
const companyLinks = [
{ href: "/about", label: "About" },
{ href: "/how-it-works", label: "How It Works" },
{ href: "/faq", label: "FAQ" },
{ href: "/contact", label: "Contact" },
{ href: "/blog", label: "Blog" },
{ href: "/privacy-policy", label: "Privacy Policy" },
];
const resourceLinks = [
{ href: "/wins", label: "Client Results" },
{ href: "/testimonials", label: "Testimonials" },
// ...more resource links
];
export function Footer() {
return (
<footer className="bg-primary-dark text-white">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-12">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{/* Column 1: Brand */}
<div>
<div className="mb-4">
<Image src="/images/logo.png" alt="CLIENT_NAME" width={200} height={66} />
</div>
<p className="text-gray-300 text-sm leading-relaxed">
Short brand description here.
</p>
</div>
{/* Column 2: Company links */}
<div>
<h3 className="font-heading text-sm font-semibold uppercase tracking-wider text-accent mb-4">Company</h3>
<ul className="space-y-2">
{companyLinks.map((link) => (
<li key={link.href}>
<Link href={link.href} className="text-gray-300 hover:text-white text-sm transition-colors">{link.label}</Link>
</li>
))}
</ul>
</div>
{/* Column 3: Resource links */}
<div>
<h3 className="font-heading text-sm font-semibold uppercase tracking-wider text-accent mb-4">Resources</h3>
<ul className="space-y-2">
{resourceLinks.map((link) => (
<li key={link.href}>
<Link href={link.href} className="text-gray-300 hover:text-white text-sm transition-colors">{link.label}</Link>
</li>
))}
</ul>
</div>
{/* Column 4: CTA + Contact */}
<div>
<h3 className="font-heading text-sm font-semibold uppercase tracking-wider text-accent mb-4">Ready to Get Started?</h3>
<p className="text-gray-300 text-sm mb-4">Short CTA teaser text.</p>
<Link href="/precall" className="inline-block rounded-md bg-cta px-6 py-3 font-heading text-sm font-semibold uppercase tracking-wider text-white hover:bg-cta-dark transition-colors mb-6" />
<div className="space-y-1 text-sm text-gray-300">
<p><a href="mailto:EMAIL" className="hover:text-white transition-colors">EMAIL</a></p>
<p><a href="tel:+1PHONE" className="hover:text-white transition-colors">PHONE</a></p>
<p>CITY, STATE</p>
</div>
</div>
</div>
{/* SOCIAL ICONS ROW */}
<div className="mt-8 flex justify-center gap-4">
{/* Each social: circular button with SVG icon */}
{socialLinks.map((social) => (
<a key={social.label} href={social.href} aria-label={social.label}
className="flex h-10 w-10 items-center justify-center rounded-full bg-gray-700 text-white transition-colors hover:bg-accent hover:text-primary">
{social.icon}
</a>
))}
</div>
{/* COPYRIGHT */}
<div className="mt-8 border-t border-gray-600 pt-8 text-center">
<p className="text-gray-400 text-sm">© {new Date().getFullYear()} CLIENT_NAME. All rights reserved.</p>
</div>
</div>
</footer>
);
}
Key classes: bg-primary-dark text-white, text-accent for section headers, h-10 w-10 rounded-full bg-gray-700 hover:bg-accent hover:text-primary for social icons
3c. Section Layout Patterns
These are the exact section patterns used throughout the site. Each section follows a consistent structure.
Universal Section Wrapper
<section className="bg-{COLOR} py-20 sm:py-28">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
{/* content */}
</div>
</section>
- Light sections:
bg-whiteorbg-gray-50 - Dark sections:
bg-primarywith white text - Section padding:
py-20 sm:py-28(standard),py-16 sm:py-24(compact),py-12(stats bar) - Content max width:
max-w-7xlfor grids,max-w-3xlfor prose,max-w-4xlfor CTAs
Section Header Pattern
<div className="text-center max-w-2xl mx-auto mb-16">
<h2 className="font-heading text-3xl sm:text-4xl font-bold text-primary mb-4">
Section Title
</h2>
<p className="text-gray-600 text-lg">
Section subtitle/description text.
</p>
</div>
On dark backgrounds, use text-white for h2 and text-gray-300 for description.
3d. Homepage Section Blueprints
The homepage follows this exact section order:
1. Hero Section (White/Light Background)
<section className="relative bg-white overflow-hidden">
<div className="relative mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24 sm:py-32 lg:py-40">
<div className="max-w-3xl">
<p className="font-heading text-primary text-sm sm:text-base font-semibold uppercase tracking-[0.2em] mb-4">
TAGLINE / CATEGORY
</p>
<h1 className="font-heading text-4xl sm:text-5xl lg:text-6xl font-bold text-primary leading-tight mb-6">
Main Headline <span className="text-accent">(Accent Phrase)</span>
</h1>
<p className="text-lg sm:text-xl text-gray-700 leading-relaxed mb-4">
Primary subheadline.
</p>
<p className="text-base sm:text-lg text-gray-500 leading-relaxed mb-10">
Secondary description with more detail.
</p>
<div className="flex flex-col sm:flex-row gap-4">
{/* PRIMARY CTA */}
<Link href="/wins" className="inline-flex items-center justify-center rounded-md bg-cta px-8 py-4 font-heading text-base font-semibold uppercase tracking-wider text-white hover:bg-cta-dark transition-colors">
Primary Action
</Link>
{/* SECONDARY CTA (outline) */}
<Link href="/about#contact" className="inline-flex items-center justify-center rounded-md border-2 border-primary px-8 py-4 font-heading text-base font-semibold uppercase tracking-wider text-primary hover:bg-primary hover:text-white transition-colors">
Secondary Action
</Link>
</div>
</div>
</div>
</section>
Key details:
- Two CTA buttons side by side: solid bg + outline border
- CTA text:
font-heading text-base font-semibold uppercase tracking-wider - CTA padding:
px-8 py-4 - Hero padding is larger than other sections:
py-24 sm:py-32 lg:py-40 - Accent color used on a key phrase in the headline via
<span className="text-accent">
2. Product/Image Strip
<section className="bg-white py-8 overflow-hidden">
<div className="mx-auto max-w-7xl px-4">
<Image src="/images/product-strip.png" alt="Description" width={1116} height={134} className="w-full h-auto" />
</div>
</section>
3. Stats Bar
<section className="bg-white border-b border-gray-100">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-12">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8">
{stats.map((stat) => (
<div key={stat.label} className="text-center">
<p className="font-heading text-4xl sm:text-5xl font-bold text-primary">{stat.value}</p>
<p className="mt-2 text-sm font-semibold uppercase tracking-wider text-gray-500">{stat.label}</p>
</div>
))}
</div>
</div>
</section>
Data shape: { value: "275+", label: "Books Published" }
4. Benefits Card Grid (3 columns)
<section className="bg-gray-50 py-20 sm:py-28">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
{/* Section header (centered) */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{benefits.map((benefit) => (
<div key={benefit.title} className="bg-white rounded-xl p-8 shadow-sm border border-gray-100 hover:shadow-md transition-shadow">
{/* Icon in colored circle */}
<div className="inline-flex items-center justify-center w-14 h-14 rounded-lg bg-primary/10 text-primary mb-6">
{benefit.icon}
</div>
<h3 className="font-heading text-xl font-bold text-primary mb-3">{benefit.title}</h3>
<p className="text-gray-600 leading-relaxed">{benefit.description}</p>
</div>
))}
</div>
</div>
</section>
Card pattern: bg-white rounded-xl p-8 shadow-sm border border-gray-100 hover:shadow-md transition-shadow
Icon container: w-14 h-14 rounded-lg bg-primary/10 text-primary
5. Process/How It Works (4 columns, numbered)
<section className="bg-white py-20 sm:py-28">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
{/* Section header (centered) */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{steps.map((step) => (
<div key={step.step} className="relative">
<div className="text-6xl font-heading font-bold text-primary/10 mb-2">{step.step}</div>
<h3 className="font-heading text-xl font-bold text-primary mb-3">{step.title}</h3>
<p className="text-gray-600 leading-relaxed">{step.description}</p>
</div>
))}
</div>
{/* Optional team/product photo below */}
<div className="mt-12">
<Image src="/images/team-photo.png" alt="Team" width={1024} height={768} className="w-full h-auto rounded-xl shadow-lg" />
</div>
</div>
</section>
Step number: text-6xl font-heading font-bold text-primary/10 (large, faded background number)
6. Testimonials Section (Dark Background, Glass Cards)
<section className="bg-primary py-20 sm:py-28">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="text-center max-w-2xl mx-auto mb-16">
<h2 className="font-heading text-3xl sm:text-4xl font-bold text-white mb-4">Real Results from Real Clients</h2>
<p className="text-gray-300 text-lg">Description text.</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{testimonials.map((t) => (
<div key={t.name} className="bg-white/5 border border-white/10 rounded-xl p-8 backdrop-blur-sm">
{/* Star rating */}
<div className="flex items-center gap-1 mb-4">
{[...Array(5)].map((_, i) => (
<svg key={i} className="h-5 w-5 text-accent" fill="currentColor" viewBox="0 0 20 20">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
</svg>
))}
</div>
{/* Quote */}
<blockquote className="text-white/90 leading-relaxed mb-6 italic">
“{t.quote}”
</blockquote>
{/* Author with headshot */}
<div className="border-t border-white/10 pt-4 flex items-start gap-4">
<Image src={t.image} alt={t.name} width={64} height={64} className="w-16 h-16 rounded-full object-cover flex-shrink-0" />
<div>
<p className="font-heading font-bold text-white">{t.name}</p>
<p className="text-gray-400 text-sm">{t.title}</p>
<p className="mt-2 text-accent font-heading font-semibold text-sm uppercase tracking-wider">{t.result}</p>
</div>
</div>
</div>
))}
</div>
{/* CTA button centered below */}
<div className="text-center mt-12">
<Link href="/wins" className="inline-flex items-center justify-center rounded-md bg-cta px-8 py-4 font-heading text-base font-semibold uppercase tracking-wider text-white hover:bg-cta-dark transition-colors">
See All Client Results
</Link>
</div>
</div>
</section>
Glass card: bg-white/5 border border-white/10 rounded-xl p-8 backdrop-blur-sm
Star SVG path: M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z
7. Final CTA Section (White Background)
<section className="bg-white py-20 sm:py-28">
<div className="mx-auto max-w-4xl px-4 sm:px-6 lg:px-8 text-center">
<h2 className="font-heading text-3xl sm:text-4xl font-bold text-primary mb-6">
Ready to Get Started?
</h2>
<p className="text-gray-600 text-lg mb-10 max-w-2xl mx-auto">
Join our clients who have used [PRODUCT] to grow their business.
</p>
<div className="flex flex-col sm:flex-row justify-center gap-4">
<Link href="/precall" className="inline-flex items-center justify-center rounded-md bg-cta px-8 py-4 font-heading text-base font-semibold uppercase tracking-wider text-white hover:bg-cta-dark transition-colors">
Primary CTA
</Link>
<Link href="/wins" className="inline-flex items-center justify-center rounded-md border-2 border-primary px-8 py-4 font-heading text-base font-semibold uppercase tracking-wider text-primary hover:bg-primary hover:text-white transition-colors">
Secondary CTA
</Link>
</div>
</div>
</section>
3e. Inner Page Hero Pattern (Dark Background)
Used on About, Wins, FAQ, and all non-homepage pages:
<section className="bg-primary py-16 sm:py-24">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 text-center">
<h1 className="font-heading text-4xl sm:text-5xl lg:text-6xl font-bold text-white mb-6">
Page Title
</h1>
<p className="text-gray-300 text-lg sm:text-xl max-w-2xl mx-auto">
Page subtitle.
</p>
</div>
</section>
Variant with gradient overlay (precall, FAQ):
<section className="relative bg-primary overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-br from-primary-dark to-primary opacity-90" />
<div className="relative mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24 sm:py-32">
{/* content with z-index above gradient */}
</div>
</section>
Variant with accent highlight (FAQ):
<h1 className="font-heading text-4xl sm:text-5xl lg:text-6xl font-bold text-white leading-tight">
Frequently Asked <span className="text-accent">Questions</span>
</h1>
3f. FAQ Accordion Component Blueprint
Client component with useState for expand/collapse:
"use client";
import { useState } from "react";
export function FAQItem({ question, answer }: { question: string; answer: string }) {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="border border-gray-100 rounded-xl overflow-hidden">
<button
=> setIsOpen(!isOpen)}
className="w-full flex items-center justify-between p-6 text-left bg-white hover:bg-gray-50 transition-colors"
>
<span className="font-heading text-lg font-bold text-primary pr-4">{question}</span>
<svg
className={`h-6 w-6 text-primary shrink-0 transition-transform ${isOpen ? "rotate-180" : ""}`}
fill="none" viewBox="0 0 24 24" stroke="currentColor"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</button>
{isOpen && (
<div className="px-6 pb-6 bg-white">
<p className="text-gray-600 leading-relaxed">{answer}</p>
</div>
)}
</div>
);
}
Usage: Render in a <div className="space-y-4"> container within a bg-gray-50 section. Always include JSON-LD FAQPage schema alongside.
3g. Case Study / Wins Page Blueprint
Two tiers: featured case studies (detailed cards) and additional testimonials (grid).
Featured Case Study Card
interface CaseStudy {
name: string;
location: string;
company: string;
industry: string;
books: string[]; // or products, services
quote: string;
results: string[];
highlight: string; // e.g., "30 to 40x ROI"
headshot: string;
bookCover?: string; // optional product image
}
{/* Card with alternating bg */}
<article className={`rounded-2xl border border-gray-100 overflow-hidden shadow-sm ${idx % 2 === 0 ? "bg-gray-50" : "bg-white"}`}>
<div className="p-8 sm:p-12">
<div className="flex flex-col lg:flex-row lg:items-start gap-8">
{/* LEFT COLUMN (2/5): Info */}
<div className="lg:w-2/5">
{/* Industry badge */}
<span className="inline-block bg-primary text-white text-xs font-heading font-semibold uppercase tracking-wider px-3 py-1 rounded-full">
{cs.industry}
</span>
{/* Headshot + name */}
<div className="flex items-center gap-4 mb-4">
<Image src={cs.headshot} alt={cs.name} width={80} height={80} className="rounded-full object-cover w-20 h-20" />
<div>
<h3 className="font-heading text-2xl sm:text-3xl font-bold text-primary mb-1">{cs.name}</h3>
<p className="text-gray-500 mb-0.5">{cs.company}</p>
<p className="text-gray-400 text-sm">{cs.location}</p>
</div>
</div>
{/* Book/product tags */}
<div className="flex flex-wrap gap-2">
{cs.books.map((book) => (
<span key={book} className="inline-block bg-accent/20 text-primary text-sm font-medium px-3 py-1 rounded-md italic">{book}</span>
))}
</div>
{/* Highlight metric box */}
<div className="bg-primary rounded-lg p-4 text-center">
<p className="text-accent font-heading font-bold text-xl">{cs.highlight}</p>
</div>
</div>
{/* RIGHT COLUMN (3/5): Quote + Results */}
<div className="lg:w-3/5">
<blockquote className="text-lg sm:text-xl text-gray-700 italic leading-relaxed mb-8 border-l-4 border-accent pl-6">
“{cs.quote}”
</blockquote>
<p className="text-sm font-semibold uppercase tracking-wider text-gray-500 mb-3">Key Results</p>
<ul className="space-y-2">
{cs.results.map((result) => (
<li key={result} className="flex items-start gap-3">
<svg className="h-5 w-5 text-green-500 mt-0.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
<span className="text-gray-700">{result}</span>
</li>
))}
</ul>
</div>
</div>
</div>
</article>
Additional Testimonials Grid
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{testimonials.map((t) => (
<div key={t.name} className="bg-white rounded-xl p-6 shadow-sm border border-gray-100 hover:shadow-md transition-shadow flex flex-col">
{/* Star rating */}
<div className="flex items-center gap-1 mb-3">
{[...Array(5)].map((_, i) => (
<svg key={i} className="h-4 w-4 text-accent" fill="currentColor" viewBox="0 0 20 20">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l..." />
</svg>
))}
</div>
<blockquote className="text-gray-700 italic leading-relaxed mb-4 flex-1">
“{t.quote}”
</blockquote>
<div className="border-t border-gray-100 pt-3">
<p className="font-heading font-bold text-primary text-sm">{t.name}</p>
<p className="text-gray-500 text-xs">{t.company}</p>
{t.result && (
<p className="mt-1 text-accent font-heading font-semibold text-xs uppercase tracking-wider">{t.result}</p>
)}
</div>
</div>
))}
</div>
3h. Book a Call / Precall Page Blueprint
Two-column layout: left (2/3) has video + scheduling widget, right (1/3) has testimonials sidebar.
{/* Hero with founder headshot + gradient */}
<section className="relative bg-primary overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-br from-primary-dark to-primary opacity-90" />
<div className="relative mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24 sm:py-32">
<div className="max-w-3xl mx-auto text-center">
<Image src="/images/founder.png" alt="Founder Name" width={200} height={200} className="rounded-full mx-auto mb-6" />
<h1 className="font-heading text-4xl sm:text-5xl lg:text-6xl font-bold text-white leading-tight mb-6">
Ready to Get Started? <span className="text-accent">Book a Call Today!</span>
</h1>
</div>
</div>
</section>
{/* Main Content: 2-column */}
<section className="bg-white py-20 sm:py-28">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-12">
{/* LEFT (2/3): Video + Calendly */}
<div className="lg:col-span-2 space-y-16">
{/* Video */}
<div>
<h2 className="font-heading text-2xl sm:text-3xl font-bold text-primary mb-6">Watch This Video</h2>
<div className="aspect-video rounded-xl overflow-hidden shadow-lg">
<iframe src="https://player.vimeo.com/video/VIDEO_ID?badge=0&autopause=0" width="100%" height="100%" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen className="w-full h-full" />
</div>
</div>
{/* Scheduling */}
<div>
<h2 className="font-heading text-2xl sm:text-3xl font-bold text-primary mb-6">Select a Time Below</h2>
<div className="bg-white rounded-xl shadow-lg overflow-hidden" style={{ minHeight: '700px' }}>
<iframe src="https://calendly.com/USER/MEETING?embed_type=Inline&hide_event_type_details=1" width="100%" height="700" frameBorder="0" className="w-full" />
</div>
</div>
</div>
{/* RIGHT (1/3): Testimonial Sidebar */}
<div className="space-y-6">
<h3 className="font-heading text-xl font-bold text-primary mb-4">What Our Clients Say</h3>
{testimonials.map((t) => (
<div key={t.name} className="bg-gray-50 rounded-xl p-6 border border-gray-100">
{/* Stars */}
<blockquote className="text-gray-700 leading-relaxed mb-3 italic text-sm">“{t.quote}”</blockquote>
<div className="flex items-center gap-3">
{t.headshot && <Image src={t.headshot} alt={t.name} width={48} height={48} className="w-12 h-12 rounded-full object-cover" />}
<p className="font-heading font-bold text-primary text-sm">{t.name}</p>
</div>
</div>
))}
{/* Contact Info Card */}
<div className="bg-primary rounded-xl p-6 mt-8">
<h3 className="font-heading text-lg font-bold text-white mb-4">Get in Touch</h3>
<div className="space-y-3">
<a href="mailto:EMAIL" className="flex items-center gap-3 text-gray-300 hover:text-white transition-colors text-sm">
{/* Email SVG icon in text-accent */} EMAIL
</a>
<a href="tel:+1PHONE" className="flex items-center gap-3 text-gray-300 hover:text-white transition-colors text-sm">
{/* Phone SVG icon in text-accent */} PHONE
</a>
</div>
</div>
</div>
</div>
</div>
</section>
3i. About Page Blueprint
Section order: Dark Hero, Stats Bar, Founder Story (prose with photo), Team Photo, Values Grid (2-col), "Who We Serve" Checklist Grid (3-col), Contact CTA (dark bg with glass card).
Values card grid:
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
{values.map((v) => (
<div key={v.title} className="bg-white rounded-xl p-8 shadow-sm border border-gray-100">
<h3 className="font-heading text-xl font-bold text-primary mb-3">{v.title}</h3>
<p className="text-gray-600 leading-relaxed">{v.description}</p>
</div>
))}
</div>
"Who We Serve" checklist grid:
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 max-w-4xl mx-auto">
{professions.map((profession) => (
<div key={profession} className="flex items-center gap-3 bg-gray-50 rounded-lg p-4">
<svg className="h-5 w-5 text-accent shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
<span className="text-primary font-medium">{profession}</span>
</div>
))}
</div>
Contact CTA glass card (dark section):
<div className="bg-white/10 border border-white/20 rounded-2xl p-8 sm:p-12 max-w-xl mx-auto">
<h3 className="font-heading text-2xl font-bold text-white mb-6">Card Title</h3>
<div className="space-y-4 text-left mb-8">
{items.map((item) => (
<div key={item} className="flex items-start gap-3">
<svg className="h-5 w-5 text-accent mt-0.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
<span className="text-gray-300">{item}</span>
</div>
))}
</div>
<Link href="/precall" className="inline-flex items-center justify-center w-full rounded-md bg-cta px-8 py-4 font-heading text-base font-semibold uppercase tracking-wider text-white hover:bg-cta-dark transition-colors">
CTA Text
</Link>
</div>
3j. Reusable SVG Icons
Checkmark (for results, features, checklists):
<svg className="h-5 w-5 text-green-500 mt-0.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
Chevron down (for dropdowns, accordions):
<svg className="h-4 w-4" fill="none" viewBo
…(truncated)