Cold-Outreach Demo Prompts (25 Shipped Demos)
Generated 2026-05-07 from the same lead list as
23-outreach-list-st-george.md. 25 self-contained 7-phase Claude prompts, one per shipped demo business. Each prompt covers research, design lock, build, local verify, deploy, live verify, and a pre-flight checklist before declaring done.
How to use these
- Open Claude Code in the project root:
C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business - Fork the chat (start a new Claude Code session)
- Paste one prompt below as the first message of the new session
- Claude will research the business, lock the design, duplicate the
mixed-greenstemplate, customize for the vertical, build, deploy, and verify - When done, you have a live URL like
https://[slug].pages.devto text the prospect as the cold-call hook - Use the live URL in the cold call (see
01-cold-call-script.md) - When the business says yes, the demo migrates to their custom domain
What's in every prompt
Each of the 25 prompts walks through 7 phases:
- Research the business: scrape Google, check directory listings, walk competitors, save
RESEARCH.md - Design lock: typography (specific Google Fonts + weights), color palette (specific hex codes), motion direction, named inspirations
- Build: vertical-specific sections, photo strategy with verified Unsplash IDs, style mandates (no em dashes, no AI-tell language, no photo-shoot copy), layout safety rules
- Local verify: clean build, content sanity check via curl + grep
- Deploy to Cloudflare Pages
- Live verify: HTTP 200, content grep, em-dash scan, AI-tell scan, mobile walkthrough, Lighthouse spot-check
- Pre-flight checklist: 23-item boolean go/no-go list before declaring done
Why each prompt is structured this way
- Research-first. The CSV is a scrape and might be stale. Phase 1 verifies phone, address, rating, hours against live public sources. The model also reads competitors and reviews to inform tone and "Why us" reasons.
- Design locked. Each vertical has a typography pairing, hex-code palette, motion direction, and named inspirations. The model can't generic-template its way out of the brief.
- Visual signature per vertical. Law firm = editorial newspaper drop caps. Roofing = blueprint grid + safety-orange chevron. Restaurant = full-bleed food + handwritten menu accent. The demos look different from each other instead of feeling like template variants.
- Per-business twist. Where two businesses share a vertical (Mexican restaurants, auto shops, pest control), each one gets a short twist note that differentiates the visual direction.
- Style mandates baked in. No em dashes. No AI-tell phrasing. No "(Sample, replace with...)" meta copy visible to readers. No photo-shoot language.
- Layout safety baked in. Explicit col-span warnings, hero-on-first-paint requirement, no-orphan-card grids.
- Verification gates between phases. Local build sanity check, live HTTP check, content grep for banned phrases, em-dash scan, mobile walkthrough.
- Pre-flight checklist. 23 boolean go/no-go items the model must answer YES to before reporting back.
Tips for running these in parallel
- One Claude session per demo. Fork the chat 25 times if you really want them all in parallel. Otherwise batch in sets of 3 to 5.
- Stagger Cloudflare Pages projects. Each demo creates a new Pages project. Cloudflare allows up to 100 projects.
- Verify Unsplash URLs. Broken stock photo links and wrong-subject photos are recurring issues. The prompt tells Claude to test each URL with
curl -IAND open it in a browser to confirm subject match. - Track which demos got sent. Add a column to your CRM: "Demo URL", "Demo sent (date)", "Demo viewed (Cloudflare Analytics)".
The 25 prompts
1. Law Offices of David Laurence Altman
Vertical: Law firm
Slug: altman-law
Phone (CSV): (435) 688-9999
Address (CSV): 640 E 700 S, St. George, UT 84770
Google rating (CSV): 5★ (264 reviews)
Live URL after deploy: https://altman-law.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Law Offices of David Laurence Altman
- **Vertical:** Law firm
- **Phone:** (435) 688-9999
- **Address:** 640 E 700 S, St. George, UT 84770
- **Google rating:** 5★ (264 reviews)
- **Slug:** `altman-law`
- **Live URL after deploy:** `https://altman-law.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Law%20Offices%20of%20David%20Laurence%20Altman+St+George+UT`
Confirm phone matches CSV ((435) 688-9999). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "law firm St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Look up the firm on the Utah State Bar member directory: https://www.utahbar.org/find-a-lawyer/. Confirm the attorney's bar number and year admitted.
- Check FindLaw and Martindale-Hubbell for the attorney's profile and any peer ratings.
- Search the Washington County courthouse case search to confirm the attorney has filed cases recently. This is for verification only, do NOT include this on the site.
- Note any disciplinary history. Also for verification only, NEVER on the site.
6. **Save the research** to `apps/altman-law/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for law firm
Editorial newspaper layout. Big serif drop caps on the first paragraph of the About section. A pull-quote bar between Practice Areas and About in the style of a print case-law citation. Numbered chapter labels (01, 02, 03) on every section. Subtle 1px hairline dividers in cream over deep ink. The site reads like a quiet, serious law-review essay, not a marketing splash.
This is the most important creative direction. Lean in. The site should look like a law firm site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Solo attorney, established 1995. Lean into the long-tenure-quiet-professional angle. The hero copy is short and serious, no superlatives. Use the Altman Law deployed reference at https://altman-law.pages.dev as the visual quality bar (already shipped).
## Typography
Display: Fraunces (Google Fonts, opsz 144, weights 400 + 500 + 600). Body: DM Sans (weights 400 + 500). Mono: JetBrains Mono (weights 400 + 500). Use Fraunces italic for the accent phrase in every headline. Display letter-spacing tight (-0.025em). Display line-height 0.92 on hero h1. Body line-height 1.6. Mono for chapter labels and small caps, uppercased, tracked 0.18em.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: Ink-900 #100e0c. Foreground primary: Cream-50 #fbf6e9. Foreground muted: Cream-200 #ebdfb8 with 85% opacity. Italic accent + section numbers: Sand-300 #d39558. Primary CTA: Sand-500 #b85f30. Hairline dividers: rgba(244, 236, 214, 0.16). Avoid the navy-and-gold cliche every other Utah firm uses. The palette should feel like St. George red rock at dusk plus the gravitas of an old legal letterhead.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Restrained. Hero renders fully static (no scroll-triggered reveals on hero content, the intersection observer races with hydration on first paint). Below-fold sections use Reveal with 24px y-slide plus 6px blur, 700ms duration, easing cubic-bezier(0.16, 1, 0.3, 1). Cards lift opacity on hover (60 to 80) with a 700ms transition. One MagneticButton on the primary Free Consultation CTA. No CursorHalo, no TiltCard.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Pentagram editorial spreads. The New York Times Magazine cover typography. The quiet authority of Sullivan & Cromwell's website without the corporate stuffiness. The site should feel like an inside-cover page from a print volume, not a SaaS landing page.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/altman-law/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"altman-law"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: small monogram logo, links for Practice / About / Office, click-to-call phone, and a Free consultation CTA. Sticky on scroll, subtle border on scroll past hero.
- Hero: editorial top line with EST. + city + state on the left, italic Vol. 01 tagline on the right, separated by a hairline border. Below: Google rating badge (real data from the CSV). Then a static h1 headline that names the city, with one italic Fraunces accent phrase. Then a two-or-three-sentence sub-paragraph naming the practice angle. Two CTAs: Free consultation primary, click-to-call outline. On the right (lg:col-span-4): a firm summary card with attorney name, office address, direct line, in a small datasheet layout. Hero MUST render visible on first paint (static, no Reveal wrappers).
- Marquee: a horizontal scrolling band of practice keywords and trust signals, separated by section markers (the section sign §). Used between hero and Practice Areas as a visual breath.
- Practice Areas: 4 OR 6 cards (never 5, never 7), uniform 2x3 grid. Each card has a numeral label (01, 02, ...), a short serif heading, one sentence of plain copy, and one verified Unsplash photo. Use generic Utah practice areas as natural-sounding copy: estate planning and wills, family law, personal injury, criminal defense, business and contracts, real estate. Write as if the firm wrote it themselves. Card photos must match the section topic (verified, not random query).
- Pull quote: a print case-law citation between Practice Areas and About. One quotation mark in italic Fraunces. One short, declarative sentence. One small caption underneath in mono uppercase, tracked 0.22em, like a footnote citation. Example caption pattern: § Office practice, since 1995.
- About the attorney: two-column layout (lg:col-span-7 and lg:col-span-5). Left column has the headline (Practicing law in St. George since YYYY with italic accent on the year), then THREE plain-English paragraphs about the attorney. The first paragraph carries the editorial drop cap (a large Fraunces initial letter floated left, sized to span three lines). Below the bio, a three-cell datasheet: Bar admission, Practicing X years (since YYYY), Consultation (Free, 30 min). Right column: a single dignified photo of legal materials with a simple natural caption like 'Inside the firm office on 700 South.'
- Why this office: three numbered reasons in a 3-column grid with hairline gaps between cells. 01 Local, not regional. 02 Free initial consultation. 03 Direct attorney access. One short paragraph each, plain language.
- Free consultation CTA block: full-bleed band in the sand accent color. Two-column. Left side has the headline (Talk to the attorney, italic Not an intake screener), then a paragraph explaining the consultation, then a primary click-to-call CTA. Below: hours and address strip, two columns. Right side: a simple form (name, phone, brief description) with a Request consultation submit button. Form helper text natural, no template-meta language.
- Office: two-column. Left has the headline (Downtown St. George, italic Walking-distance to the courthouse), then four icon rows for Address, Direct line, Office hours, Parking. Two CTAs at the bottom: Call now and Driving directions. Right has an embedded Google Map iframe at the real address with a soft sepia/grayscale filter applied via CSS for visual cohesion.
- Footer: monogram logo, address, phone, sections links. Two disclaimer paragraphs across 12 columns: attorney advertising disclaimer + past results disclaimer (standard for U.S. law firm sites under model rules).
## Photo strategy
Verified Unsplash IDs (curated, all 200 + correct subject). photo-1589994965851-a8f479c573a9 (law books on shelf, hero backdrop), photo-1521133573892-e44906baee46 (estate planning card), photo-1568992687947-868a62a9f521 (legal documents on desk, family law), photo-1453873531674-2151bcd01707 (urban scene, personal injury), photo-1589216532372-1c2a367900d9 (gavel, criminal defense), photo-1554224154-26032ffc0d07 (papers on desk, business law), photo-1564013799919-ab600027ffc6 (modern home exterior, real estate), photo-1521587760476-6c12a4b040da (law books, About). DO NOT use the source.unsplash.com random query format. It returned a t-shirt photo on a previous build. Always use images.unsplash.com/photo-XXX with a verified ID.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`5★ on Google, 264 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/altman-law"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "5★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=altman-law --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://altman-law.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://altman-law.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://altman-law.pages.dev | grep -c "5★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://altman-law.pages.dev | grep -c "(435) 688-9999"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://altman-law.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://altman-law.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://altman-law.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/altman-law/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 688-9999`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`5★`, 264 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://altman-law.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://altman-law.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
2. Irmita's Casita Mexican Restaurant
Vertical: Restaurant
Slug: irmitas-casita
Phone (CSV): (435) 703-9162
Address (CSV): 95 W 700 S, St. George, UT 84770
Google rating (CSV): 4.6★ (2162 reviews)
Live URL after deploy: https://irmitas-casita.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Irmita's Casita Mexican Restaurant
- **Vertical:** Restaurant
- **Phone:** (435) 703-9162
- **Address:** 95 W 700 S, St. George, UT 84770
- **Google rating:** 4.6★ (2162 reviews)
- **Slug:** `irmitas-casita`
- **Live URL after deploy:** `https://irmitas-casita.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Irmita's%20Casita%20Mexican%20Restaurant+St+George+UT`
Confirm phone matches CSV ((435) 703-9162). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "restaurant St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Find the restaurant on Yelp and DoorDash. Note hours, menu (if visible), and any photos of dishes.
- Check Google Maps photos to see what their actual interior and food looks like (informs photo direction without claiming the photos are theirs).
- Read 5 to 10 reviews. Note recurring praised dishes (don't quote anyone). The owner can confirm during onboarding.
- Check if they're on Instagram. If yes, link the handle in the footer placeholder.
6. **Save the research** to `apps/irmitas-casita/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for restaurant
Full-bleed food photography. A handwritten or hand-drawn accent script for menu category labels and specials. Warm grain texture overlay over hero photos. Dish names large, prices small. Navigation feels like a printed menu, not a SaaS landing page.
This is the most important creative direction. Lean in. The site should look like a restaurant site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Warm Mexican cantina feel. Deep red #8B0000 plus warm cream #F5E6CA plus lime #84A93C accent plus charcoal #1A0F0A. Use Playfair Display for the restaurant name (Mexican-deco serif vibe), Crimson Text for body, Caveat as the handwritten accent on menu category labels (Specials, Family Style, etc.). Food photography leans handmade: salsas, charro plates, hand-pressed tortillas. Skip minimalist plating shots.
## Typography
See per-business twist for the cuisine-specific pairing. General direction: a strong serif or display sans for dish names + a clean humanist sans for body + a single hand-script accent (Caveat or Permanent Marker) used SPARINGLY on category labels.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
See per-business twist. Mexican leans deep red plus warm cream plus lime accent plus earthy clay. American cafe leans off-white parchment plus forest green plus gold plus bookcloth red. Healthy bowl leans sage plus cream plus white plus a small coral accent. Always warm and food-appropriate.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Generous but never flashy. Hero food photo has a subtle slow ken-burns (3 to 5 percent scale, 8 to 12 second loop). Below-fold sections use Reveal with 18px y-slide, no blur, 600ms. Menu cards lift on hover (TiltCard primitive, 6 degrees max rotation). Marquee scrolls at a calm 38 second loop.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Per cuisine: Mexican leans Hijos de Villa style cantina warmth crossed with editorial food magazine. American cafe leans Penguin Classics covers crossed with Boulder bookstore signage. Healthy bowl leans Sweetgreen-but-better, with full-bleed editorial food shots like Bon Appetit.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/irmitas-casita/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"irmitas-casita"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: short logo, Menu, About, Hours, click-to-call, Order CTA primary.
- Hero: a single appetizing close-up dish photo as a full-bleed background with a subtle ken-burns. Restaurant name on top in display type. One-line tagline naming the cuisine and city. Two CTAs: Order primary, Reservations or click-to-call outline. A small strip below shows hours and address. Hero must render visible on first paint (static).
- Marquee: scrolling kitchen-language band of dish keywords plus trust signals.
- Featured menu: 6 OR 8 cards in a uniform grid (3x2 or 4x2). Each card has a verified dish photo, a name, a one-line description, and a price. Use cuisine-appropriate generic dishes that the owner can edit.
- About the restaurant: two-column. Left column has the headline plus a short two-or-three-sentence story (family owned, from-scratch cooking, neighborhood feel). Right column has a single interior photo with a natural caption.
- Photo gallery: 6 to 9 verified food and interior shots in a clean masonry or grid layout.
- Hours and location: simple table for the week + a real Google Maps iframe at the real address.
- Order CTA: full-bleed band. Big click-to-call using the real phone, plus DoorDash and UberEats ghost buttons if applicable.
- Footer: hours, address, phone, social handles as placeholders.
## Photo strategy
Verified IDs by cuisine. Mexican: photo-1565299585323-38d6b0865b47 (tacos), photo-1599974579688-8dbdd335c77f (enchiladas), photo-1551504734-5ee1c4a1479b (salsa and chips), photo-1565958011703-44f9829ba187 (charro plate). American cafe: photo-1509440159596-0249088772ff (latte art), photo-1495474472287-4d71bcdd2085 (pastry case), photo-1525351484163-7529414344d8 (brunch plate). Healthy bowl: photo-1546069901-ba9599a7e63c (grain bowl), photo-1540420773420-3366772f4999 (greens). Verify each ID returns HTTP 200 with curl AND open in a browser to confirm the subject. NEVER use source.unsplash.com.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.6★ on Google, 2162 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/irmitas-casita"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.6★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=irmitas-casita --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://irmitas-casita.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://irmitas-casita.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://irmitas-casita.pages.dev | grep -c "4.6★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://irmitas-casita.pages.dev | grep -c "(435) 703-9162"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://irmitas-casita.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://irmitas-casita.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://irmitas-casita.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/irmitas-casita/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 703-9162`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.6★`, 2162 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://irmitas-casita.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://irmitas-casita.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
3. St. George Roofing Pros
Vertical: Roofing contractor
Slug: sg-roofing-pros
Phone (CSV): (435) 236-3082
Address (CSV): 485 E 600 S, St. George, UT 84770
Google rating (CSV): 4.9★ (81 reviews)
Live URL after deploy: https://sg-roofing-pros.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** St. George Roofing Pros
- **Vertical:** Roofing contractor
- **Phone:** (435) 236-3082
- **Address:** 485 E 600 S, St. George, UT 84770
- **Google rating:** 4.9★ (81 reviews)
- **Slug:** `sg-roofing-pros`
- **Live URL after deploy:** `https://sg-roofing-pros.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=St.%20George%20Roofing%20Pros+St+George+UT`
Confirm phone matches CSV ((435) 236-3082). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "roofing contractor St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check the Utah Division of Professional Licensing for the contractor license: https://secure.utah.gov/llv/search/index.html. Note the license number and class.
- Check BBB profile for any complaints (don't include on site, note for discovery call).
- Check Google Photos for past projects to inform photo direction.
- Note the actual service area (some 'St. George roofers' actually serve all of Washington County or beyond).
6. **Save the research** to `apps/sg-roofing-pros/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for roofing contractor
Industrial blueprint motif. A faint blueprint-grid background behind hero. A safety-orange chevron used as a callout shape. Bold uppercase condensed sans labels for service names. Photographs of finished work shown big and centered with a thin metallic border. Trades-pro, not marketing-agency.
This is the most important creative direction. Lean in. The site should look like a roofing contractor site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Roofing. The Pros in the name leans heavy and confident. Bold typography, big roofing portfolio.
## Typography
Display: Bebas Neue or Anton (condensed bold display, weight 700). Body: Inter (weights 400 + 500). Mono: JetBrains Mono. Use uppercase tracked 0.05em headlines. Numerals tabular for trust signals.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: charcoal #1A1D24. Foreground: cream-white #F8F9FA. Steel gray secondary: #3F4451. Single safety-orange accent: #FF6B1F (CTAs and chevrons only). Optional brick-red secondary accent: #8B2525. Hairline dividers: rgba(248, 249, 250, 0.12).
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Bold and direct. Hero renders fully static. Below-fold sections use Reveal with 24px y-slide plus 4px blur, 600ms. Cards reveal on scroll, no TiltCard. CTAs have a chevron arrow that translates 4px on hover.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Carhartt's marketing, Klein Tools branding, the Caterpillar website. Trade-pro confidence with no fluff.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/sg-roofing-pros/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"sg-roofing-pros"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Service area, About, Contact, click-to-call, Free estimate CTA primary.
- Hero: photo of a finished roof or a crew on a job. Heavy condensed display headline with the business name plus one-line position statement naming Southern Utah. Two CTAs (Free estimate primary, click-to-call outline). Trust strip below: Licensed and insured, family owned, free written estimates, in three pills with the safety-orange chevron divider. Headline visible on first paint.
- Services: 4 OR 6 cards in 2x2 or 2x3 grid. Roof replacement, roof repair, storm damage, gutters, inspection, commercial. Each card has a numeral label, condensed heading, plain one-sentence copy, and a verified roofing photo. Cards must fill rows, no orphans.
- Recent work: before-and-after photo grid, 4 OR 6 pairs. Each caption names the neighborhood and a one-line description of the job.
- Why us: 4 plain bullets in a one-row grid. Licensed. Insured. Local and family owned. Free written estimate.
- Service area: chip list with St. George, Washington, Hurricane, Ivins, Santa Clara, La Verkin, Toquerville, Cedar City.
- Free estimate block: full-bleed band in safety-orange. Headline plus simple form (name, phone, address, brief description) plus click-to-call alternate.
- Footer: license number from Phase 1 research, phone, address.
## Photo strategy
Verified IDs. photo-1632154815762-4b1e1f4cae5e (shingle roof close-up), photo-1564540586988-aa4e53c3d799 (residential exterior), photo-1605276374104-dee2a0ed3cd6 (construction crew), photo-1570173263302-c93e30be0a51 (worker on roof), photo-1572029269289-d728e83ee98d (residential reroof). Verify subject match in browser before use.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 81 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/sg-roofing-pros"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=sg-roofing-pros --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://sg-roofing-pros.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://sg-roofing-pros.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://sg-roofing-pros.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://sg-roofing-pros.pages.dev | grep -c "(435) 236-3082"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://sg-roofing-pros.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://sg-roofing-pros.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://sg-roofing-pros.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/sg-roofing-pros/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 236-3082`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 81 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://sg-roofing-pros.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://sg-roofing-pros.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
4. Mixed Greens (refresh, site already exists)
Vertical: Restaurant
Slug: mixed-greens (site already at apps/mixed-greens/)
Phone: (435) 705-5203
Address: 661 E St George Blvd suite 1, St. George, UT 84770
Google rating: 4.8★ (919 reviews)
Note: Mixed Greens is your existing demo and lives at apps/mixed-greens/. Use this prompt only if you want to rebuild it with the new agency design system. Otherwise skip to #5.
[BEGIN COPY-PASTE PROMPT]
# Mission
Refresh the Mixed Greens demo (apps/mixed-greens/) with the new agency design system. Keep all existing menu data intact. Upgrade the visual layer only.
Repo root: C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business
# Phase 1: Audit the existing site
1. Open https://mixed-greens.pages.dev to see the live version.
2. Walk every section. Note what works, what feels dated, what needs the new agency primitives.
3. Confirm the menu data in lib/menu.ts is intact and the verified Unsplash URLs still resolve (curl each).
# Phase 2: Lock the design
Mixed Greens palette: bright sage green plus cream plus white plus a single coral spark for live indicators. Drop any acid green elsewhere. Typography: Inter for body, GT Walsheim or DM Sans for display, JetBrains Mono for caption. Motion: subtle, food-magazine-style.
Inspirations: Sweetgreen-but-better. Bon Appetit's full-bleed editorial food shots. Aesop's product photography quality bar.
# Phase 3: Bring in the agency primitives
Bring in these from apps/agency/components/primitives/:
- ChapterHeader (numbered section labels with mono caption)
- WordsReveal (per-word stagger on big headlines, but NOT on the hero)
- Reveal / RevealGroup / RevealItem (scroll-triggered fade plus slide plus blur)
- Bars (the 3-stacked-bars motif as a hover or decoration element)
- ScrollProgress (top-of-page scroll-progress bar)
- Marquee (kinetic ticker between sections)
- MagneticButton (cursor-attraction on the primary CTA only)
- TiltCard (3D tilt on hover for menu cards)
# Style mandates
- No em dashes anywhere on the site.
- No template-meta phrases visible to the reader.
- No mention of photo shoots.
- No banned AI phrases (we pride ourselves, delivering excellence, leveraging, ensuring, navigate the complexities, your trusted partner, elevate, seamless, crafted with).
- No tilde-prefix numbers.
# Layout safety
- Hero must render visible on first paint. Do NOT wrap hero content in whileInView Reveals.
- Any <Reveal> in a 12-col grid MUST carry the md:col-span-X class.
- Card grids must fill rows. No orphans.
# Phase 4: Local verify
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/mixed-greens"
rm -rf .next out
npm run build
Required outcomes:
- Exit code 0
- No TypeScript errors
- No broken-image warnings
- First Load JS under 200kB
Then preview locally and walk every section.
# Phase 5: Deploy
wrangler pages deploy out --project-name=mixed-greens --branch=main --commit-dirty=true
# Phase 6: Live verify
curl -sI https://mixed-greens.pages.dev | head -3 (expect HTTP/2 200)
Open the live URL in a browser. Walk every section. Confirm hero paints on first frame, no broken photos, mobile layout works.
# Report back
1. Live URL.
2. Build stats (size, page count).
3. Any visual changes between old and new.
4. Any photo swaps.
5. Any layout fixes.
[END COPY-PASTE PROMPT]
5. Richard L. Denos, D.D.S., Pc
Vertical: Dental practice
Slug: denos-dental
Phone (CSV): (435) 628-0800
Address (CSV): 437 S Bluff St #101, St. George, UT 84770
Google rating (CSV): 4.9★ (58 reviews)
Live URL after deploy: https://denos-dental.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Richard L. Denos, D.D.S., Pc
- **Vertical:** Dental practice
- **Phone:** (435) 628-0800
- **Address:** 437 S Bluff St #101, St. George, UT 84770
- **Google rating:** 4.9★ (58 reviews)
- **Slug:** `denos-dental`
- **Live URL after deploy:** `https://denos-dental.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Richard%20L.%20Denos%2C%20D.D.S.%2C%20Pc+St+George+UT`
Confirm phone matches CSV ((435) 628-0800). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "dental practice St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Note the dentist's specialties (pediatric? cosmetic? implants? orthodontics?). Their Google profile usually lists this.
- Check insurance accepted (most Utah dentists list Delta Dental, BlueCross, Aetna, Cigna). Don't fabricate, but most accept the major carriers.
- Read reviews to find out if it's a family-friendly practice or more cosmetic-focused. Adjust the copy tone.
6. **Save the research** to `apps/denos-dental/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for dental practice
Airy medical-infographic feel. Lots of whitespace. Soft circular backdrops behind service icons. A simple line-art tooth motif used sparingly as a section break. Family photography that feels candid, not stock-clinical.
This is the most important creative direction. Lean in. The site should look like a dental practice site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Solo dentist. Family-practice angle. Photography leans candid family-and-smile, not clinical close-ups.
## Typography
Display: DM Serif Display (weight 400). Body: Inter (weights 400 + 500). Mono: JetBrains Mono. Soft humanist personality, generous line-height (1.7 on body), large body type (18 to 20px).
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: warm white #FBF8F2. Foreground: navy #1A3A52. Secondary blue: #7DB6E8. Accent terracotta: #C8704F (CTAs only). Cream neutral: #F2EAD9. Avoid bright cyan blues (look corporate medical). Aim for soft and trustworthy.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Calm. Hero static. Below-fold Reveal with 16px y-slide, no blur, 500ms. Service icons fade in on scroll with a 100ms stagger. No magnetic buttons. No tilt cards.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Mejuri's understated luxury crossed with a friendly local family business. Lever's airy product pages. The opposite of a cold corporate medical site.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/denos-dental/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"denos-dental"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, New patients, About, click-to-call, Book CTA primary.
- Hero: candid family or smile-focused photo. Practice name in serif display. One-line tagline naming the city. Book and click-to-call CTAs. Headline visible on first paint.
- Services: 4 OR 6 cards in 2x2 or 2x3 grid. General, cosmetic, implants, pediatric, orthodontics. Standard card pattern (numeral, heading, sentence, photo).
- New patients: clean two-column block. Left side has an ordered list of three steps for a first visit. Right side has insurance accepted as a chip list with the major Utah carriers, plus a one-line note that the office can confirm coverage on a call.
- About the doctor: two-column. Left has bio in three plain paragraphs. Right has a dignified portrait or office photo with a natural caption.
- Office hours and location: simple table plus a Google Maps iframe.
- Book block: large click-to-call CTA plus a Book online ghost button (placeholder for a scheduler like LocalMed).
- Footer.
## Photo strategy
Verified IDs. photo-1606811971618-4486d14f3f99 (dental tools), photo-1581585504104-f3e7e9d8a8e9 (smile portrait), photo-1559757148-5c350d0d3c56 (dental chair), photo-1588776814546-1ffcf47267a5 (modern clinic interior). Avoid scary mouth close-ups.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 58 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/denos-dental"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=denos-dental --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://denos-dental.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://denos-dental.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://denos-dental.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://denos-dental.pages.dev | grep -c "(435) 628-0800"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://denos-dental.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://denos-dental.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://denos-dental.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/denos-dental/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 628-0800`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 58 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://denos-dental.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://denos-dental.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
6. Wright Automotive LLC
Vertical: Auto repair shop
Slug: wright-automotive
Phone (CSV): (435) 256-6593
Address (CSV): 630 N 3050 E B2, St. George, UT 84790
Google rating (CSV): 4.7★ (324 reviews)
Live URL after deploy: https://wright-automotive.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Wright Automotive LLC
- **Vertical:** Auto repair shop
- **Phone:** (435) 256-6593
- **Address:** 630 N 3050 E B2, St. George, UT 84790
- **Google rating:** 4.7★ (324 reviews)
- **Slug:** `wright-automotive`
- **Live URL after deploy:** `https://wright-automotive.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Wright%20Automotive%20LLC+St+George+UT`
Confirm phone matches CSV ((435) 256-6593). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "auto repair shop St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check ASE certification listing if available: https://www.ase.com/find-a-shop. Confirm ASE-certified status if claimed.
- Note brands they specialize in (some are domestic-focused, some import-focused, some are both).
- Read reviews for tone (some shops lean honest-mechanic, some lean technical-expert, some lean family-friendly).
6. **Save the research** to `apps/wright-automotive/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for auto repair shop
Garage chalkboard plus mechanical schematic motif. Service prices written in a chalk-style accent font (used sparingly as labels). A schematic line-drawing of a car as a hero overlay or section divider. Authentic shop photography. The site feels like a working bay, not a corporate dealer site.
This is the most important creative direction. Lean in. The site should look like a auto repair shop site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Auto repair shop. Lean honest-mechanic angle. ASE-certified and warranty front and center on the trust strip.
## Typography
Display: Bebas Neue (condensed bold). Body: Inter (weights 400 + 500). Accent: Permanent Marker or Special Elite (chalk-style, sparingly on price labels only). Mono: JetBrains Mono.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: near-black #0F0F0F. Foreground: cream #F4ECD8. Steel gray secondary: #3A3A3A. Bold red accent: #D9302E (CTAs). Amber secondary accent: #F4A623 (price labels). Concrete gray for textures: #9B9B9B.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Bold but not gimmicky. Hero static. Below-fold Reveal with 20px y-slide, 600ms. Cards have a subtle wrench-icon hover state.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Singer Vehicle Design's website (premium automotive heritage). Iron and Resin's branding. The vintage shop signage of Highway 89.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/wright-automotive/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"wright-automotive"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Hours, Contact, click-to-call, Free estimate CTA.
- Hero: shop interior or under-the-hood photo. Bold display headline with the shop name. One-line tagline naming the city. Two CTAs (Free estimate primary, click-to-call outline). Trust strip with three pills (ASE-certified if real, family owned, warranty on all work). Headline visible on first paint.
- Services: 6 OR 8 cards. Oil change, brakes, transmission, A/C, diagnostics, tires, suspension, engine. Prime Tire variant: lead with tire services. Each card has a chalk-style price label in amber.
- Why us: 4 short bullets. ASE certified, family owned, X years in business, warranty on all work.
- Brands serviced: chip list. Toyota, Honda, Ford, Chevy, Subaru, Nissan, Dodge, Jeep, Ram, GMC.
- Hours and location: simple table plus map iframe.
- Free estimate block: click-to-call plus optional simple form.
- Footer.
## Photo strategy
Verified IDs. photo-1487754180451-c456f719a1fc (mechanic at work), photo-1632823469850-1b7b1e8b7f0c (engine bay), photo-1632823471565-1ec3a1e89a6f (shop interior wide), photo-1486006920555-c77dcf18193c (tools rack).
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.7★ on Google, 324 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/wright-automotive"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.7★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=wright-automotive --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://wright-automotive.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://wright-automotive.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://wright-automotive.pages.dev | grep -c "4.7★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://wright-automotive.pages.dev | grep -c "(435) 256-6593"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://wright-automotive.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://wright-automotive.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://wright-automotive.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/wright-automotive/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 256-6593`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.7★`, 324 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://wright-automotive.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://wright-automotive.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
7. Outlaw Pest Control Service
Vertical: Pest control
Slug: outlaw-pest
Phone (CSV): (435) 322-0890
Address (CSV): 5699 S Garnet Dr, St. George, UT 84790
Google rating (CSV): 4.9★ (124 reviews)
Live URL after deploy: https://outlaw-pest.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Outlaw Pest Control Service
- **Vertical:** Pest control
- **Phone:** (435) 322-0890
- **Address:** 5699 S Garnet Dr, St. George, UT 84790
- **Google rating:** 4.9★ (124 reviews)
- **Slug:** `outlaw-pest`
- **Live URL after deploy:** `https://outlaw-pest.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Outlaw%20Pest%20Control%20Service+St+George+UT`
Confirm phone matches CSV ((435) 322-0890). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "pest control St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check Utah Department of Agriculture pesticide applicator license (https://ag.utah.gov/) for the company's license.
- Note Utah-specific pests (scorpions are a real St. George concern, mention them).
- Check if they offer monthly contracts or one-time service (informs the CTA).
6. **Save the research** to `apps/outlaw-pest/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for pest control
Home blueprint plus family-safe motif. A faint house-blueprint background behind the service grid. Pet-safe and family-friendly imagery (yards, kids, dogs) instead of pest close-ups. A small shield icon used as the trust badge motif.
This is the most important creative direction. Lean in. The site should look like a pest control site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Pest control. The wordmark Outlaw can carry a slight Western-typography accent (a single display serif on the wordmark, the rest stays clean).
## Typography
Display: Familjen Grotesk or Manrope (clean grotesque, weight 600 + 700). Body: Inter (400 + 500). Mono: JetBrains Mono. Friendly humanist personality.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: cream-white #FAF6EE. Foreground: forest green #2D5F3F. Secondary earth #9B7A4E. Accent safety-orange #E66A26 (CTAs and warning chevrons only). Avoid bright greens, they look amateur.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Friendly. Hero static. Below-fold Reveal with 18px y-slide, 500ms. Shield icons gently fade in.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Truly Nolen's premium service site without the cartoon mouse. Orkin's clean information architecture. Modern home service brands like Hippo or Lemonade.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/outlaw-pest/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"outlaw-pest"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Service area, Contact, click-to-call, Free inspection CTA primary.
- Hero: family-friendly home exterior photo. Clean grotesque headline with the company name. One-line tagline naming Southern Utah. Two CTAs. Trust strip (pet safe, family friendly, local). Headline visible on first paint.
- Services: 4 OR 6 cards in 2x2 or 2x3 grid. Residential, commercial, ants, spiders, scorpions and roaches, rodents, termites. Standard card pattern.
- Pet-safe block: wide horizontal block with one large image of a yard or dog and three plain bullets explaining pet and family safety.
- Service area: chip list with St. George, Washington, Hurricane, Ivins, Santa Clara, La Verkin, Cedar City.
- Free inspection block: simple form (name, phone, address, brief description) plus click-to-call.
- Why us: 3 plain bullets. Licensed. Insured. Locally owned.
- Footer.
## Photo strategy
Verified IDs. photo-1564540583246-934409427776 (residential exterior), photo-1583912086296-be5b665036d3 (yard with green grass), photo-1493780474520-aff4e8af265c (dog on porch), photo-1542621334-a254cf47733d (Utah desert landscape). Avoid pest close-ups.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 124 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/outlaw-pest"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=outlaw-pest --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://outlaw-pest.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://outlaw-pest.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://outlaw-pest.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://outlaw-pest.pages.dev | grep -c "(435) 322-0890"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://outlaw-pest.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://outlaw-pest.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://outlaw-pest.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/outlaw-pest/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 322-0890`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 124 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://outlaw-pest.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://outlaw-pest.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
8. Advanced Spine & Rehab
Vertical: Chiropractor
Slug: advanced-spine
Phone (CSV): (435) 656-0234
Address (CSV): 136 E Riverside Dr Unit 200, St. George, UT 84770
Google rating (CSV): 4.9★ (84 reviews)
Live URL after deploy: https://advanced-spine.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Advanced Spine & Rehab
- **Vertical:** Chiropractor
- **Phone:** (435) 656-0234
- **Address:** 136 E Riverside Dr Unit 200, St. George, UT 84770
- **Google rating:** 4.9★ (84 reviews)
- **Slug:** `advanced-spine`
- **Live URL after deploy:** `https://advanced-spine.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Advanced%20Spine%20%26%20Rehab+St+George+UT`
Confirm phone matches CSV ((435) 656-0234). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "chiropractor St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Note the chiropractor's specialties (sports injury? auto accident? pregnancy?). Adjust the service grid.
- Check insurance accepted (most Utah chiros take major medical and auto-injury insurance).
- Note if they have a massage therapist on staff (many do, add Massage to services if so).
6. **Save the research** to `apps/advanced-spine/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for chiropractor
Calm wellness with a touch of medical credibility. A faint anatomy line-art motif used sparingly (one spine illustration as a single section divider). Soft organic-shape backgrounds. The site feels modern medical, not gimmicky wellness.
This is the most important creative direction. Lean in. The site should look like a chiropractor site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Chiropractic with a rehab-and-injury angle. Lean medical-credible side of the chiropractor template, less spa-wellness.
## Typography
Display: DM Serif Display (weight 400). Body: DM Sans (weights 400 + 500). Mono: JetBrains Mono.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: warm cream #F4EFE0. Foreground: deep green #3A4A2E. Secondary sage #9CAF8B. Accent terracotta #C68A6E (CTAs only).
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Calm. Hero static. Below-fold Reveal with 16px y-slide, 500ms. Subtle organic-blob motion in the background of the hero.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Hims & Hers' health-tech minimalism. Squarespace's wellness templates done well. The opposite of the typical strip-mall chiro site.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/advanced-spine/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"advanced-spine"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Insurance, About, click-to-call, Book CTA primary.
- Hero: clinic or wellness photo. Serif headline. One-line tagline naming the city. Book and click-to-call CTAs. Headline visible on first paint.
- Services: 4 OR 6 cards. Adjustment, massage, rehab, sports injury, auto accident, pregnancy or pediatric.
- New patient info: clean two-column. Left side ordered list of what to expect. Right side insurance accepted chip list, plus a sentence saying call to confirm coverage.
- About the doctor: two-column, bio plus portrait.
- Conditions we treat: chip list (back pain, neck pain, headaches, sciatica, sports injury).
- Book block: click-to-call plus a placeholder Book online ghost button.
- Footer.
## Photo strategy
Verified IDs. photo-1559757175-5700dde675bc (clinic interior), photo-1540497077202-7c8a3999166f (massage table), photo-1571019614242-c5c5dee9f50b (calm consultation room).
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 84 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/advanced-spine"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=advanced-spine --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://advanced-spine.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://advanced-spine.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://advanced-spine.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://advanced-spine.pages.dev | grep -c "(435) 656-0234"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://advanced-spine.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://advanced-spine.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://advanced-spine.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/advanced-spine/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 656-0234`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 84 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://advanced-spine.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://advanced-spine.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
9. Patriot Painting LLC
Vertical: Painting contractor
Slug: patriot-painting
Phone (CSV): (435) 574-9459
Address (CSV): 1150 E Riverside Dr Ste 910745, St. George, UT 84790
Google rating (CSV): 4.7★ (65 reviews)
Live URL after deploy: https://patriot-painting.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Patriot Painting LLC
- **Vertical:** Painting contractor
- **Phone:** (435) 574-9459
- **Address:** 1150 E Riverside Dr Ste 910745, St. George, UT 84790
- **Google rating:** 4.7★ (65 reviews)
- **Slug:** `patriot-painting`
- **Live URL after deploy:** `https://patriot-painting.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Patriot%20Painting%20LLC+St+George+UT`
Confirm phone matches CSV ((435) 574-9459). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "painting contractor St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check Utah DOPL if they claim contractor licensing, but do not display a license number unless verified.
- Look for project photos on Google, Facebook, Instagram, or Yelp to understand interior versus exterior focus.
- Read reviews for repeated praise around clean lines, prep work, speed, communication, or cabinet work.
6. **Save the research** to `apps/patriot-painting/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for painting contractor
Clean color-consultant trades motif. Large paint swatches, crisp masked edges, and before-and-after wall details. Use tasteful residential exterior and interior photography. It should feel detail-oriented and visually confident, not like a generic contractor site.
This is the most important creative direction. Lean in. The site should look like a painting contractor site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Painting lead. Build the service grid around interior and exterior painting, cabinet refinishing, drywall repair, and prep work. Lean a touch more polished than a typical trades site because painters compete partly on aesthetic taste.
## Typography
Display: Fraunces or Playfair Display (weight 600) for warmth. Body: Inter (weights 400 + 500). Mono: JetBrains Mono for estimate labels. Use relaxed headings with no aggressive all-caps except tiny utility labels.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: warm white #FBF7EF. Foreground: deep navy #172033. Primary accent: heritage red #B33A2B. Secondary accent: muted blue #446B7C. Swatch neutrals: #E7D8C8, #D8C7AF, #EEE7DA. Dividers: rgba(23, 32, 51, 0.14).
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Polished and calm. Hero static. Below-fold sections use Reveal with 16px y-slide, no blur, 500ms. Swatch chips can slide slightly on hover.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Farrow & Ball color pages, Benjamin Moore editorial, and a clean custom-home portfolio.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/patriot-painting/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"patriot-painting"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Gallery, Process, Contact, click-to-call, Free estimate CTA primary.
- Hero: tasteful interior or exterior painting photo. Business name in refined display type. One-line Southern Utah painting position statement. Two CTAs: Free estimate primary and click-to-call outline. Trust strip: prep work, clean lines, written estimates.
- Services: 4 OR 6 cards. Interior painting, exterior painting, cabinet refinishing, drywall repair, staining, pressure washing prep. Each card has a verified painting or finished-home photo.
- Work gallery: 6 project-style images with room or neighborhood captions. Do not claim these are their projects unless verified.
- Process: prep, protect, paint, walkthrough as a four-step timeline.
- Why us: 4 plain bullets around prep, communication, clean job sites, and written estimates.
- Estimate block: form with name, phone, address, rooms or surfaces, and timeline plus click-to-call alternate.
- Footer: phone, address, service area, social placeholders.
## Photo strategy
Verified IDs. photo-1562259949-e8e7689d7828 (paint roller wall), photo-1589939705384-5185137a7f0f (painting tools), photo-1600607687939-ce8a6c25118c (finished interior), photo-1598928506311-c55ded91a20c (interior room), photo-1598300042247-d088f8ab3a91 (home exterior). Verify subject match in browser before use.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.7★ on Google, 65 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/patriot-painting"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.7★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=patriot-painting --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://patriot-painting.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://patriot-painting.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://patriot-painting.pages.dev | grep -c "4.7★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://patriot-painting.pages.dev | grep -c "(435) 574-9459"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://patriot-painting.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://patriot-painting.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://patriot-painting.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/patriot-painting/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 574-9459`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.7★`, 65 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://patriot-painting.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://patriot-painting.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
10. Eric Gubler Realtor
Vertical: Real estate agent
Slug: eric-gubler
Phone (CSV): (435) 619-2841
Address (CSV): 90 E 100 S, St. George, UT 84770
Google rating (CSV): 4.9★ (44 reviews)
Live URL after deploy: https://eric-gubler.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Eric Gubler Realtor
- **Vertical:** Real estate agent
- **Phone:** (435) 619-2841
- **Address:** 90 E 100 S, St. George, UT 84770
- **Google rating:** 4.9★ (44 reviews)
- **Slug:** `eric-gubler`
- **Live URL after deploy:** `https://eric-gubler.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Eric%20Gubler%20Realtor+St+George+UT`
Confirm phone matches CSV ((435) 619-2841). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "real estate agent St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check the brokerage the agent is licensed under (look for 'eXp Realty', 'Equity Real Estate', 'Berkshire Hathaway HomeServices' in their public profile).
- Find their MLS listings if visible.
- Note their specialty (luxury? first-time buyer? investor? relocation?).
6. **Save the research** to `apps/eric-gubler/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for real estate agent
Magazine spread with the Southern Utah landscape doing the heavy lifting. Big serif name typography for the agent. Photo essays of red rock and homes paired with editorial captions. Address-card aesthetic for listings (small, structured, like a real-estate flyer).
This is the most important creative direction. Lean in. The site should look like a real estate agent site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Solo agent. Lean fully into the Eric Gubler personal brand. Big editorial portrait, his name as the headline, Southern Utah as the supporting visual. Avoid generic 'real estate group' framing.
## Typography
Display: Cormorant Garamond (weight 400 + 500 + 600). Body: Inter (400 + 500). Mono: JetBrains Mono. Display sized very large on the agent name (up to 9rem on desktop).
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: cream #F0E5D1. Foreground: deep navy #1A2742. Primary terracotta #C46A4A. Accent red rock #8B3A2F (used sparingly). Hairline lines: rgba(26, 39, 66, 0.15).
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Editorial. Hero static. Below-fold Reveal with 24px y-slide, 700ms. Listing cards lift on hover with TiltCard at 4 degrees max.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Compass and The Agency's listing presentation. National Geographic photography spreads. Kinfolk magazine layout.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/eric-gubler/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"eric-gubler"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo or agent monogram, About, Listings, Buy, Sell, Contact, click-to-call.
- Hero: agent portrait OR a Southern Utah red rock landscape photo. Agent name in big editorial serif (up to 7rem on desktop). One-line tagline (Your Southern Utah Realtor or similar in plain language). Contact and click-to-call CTAs. Headline visible on first paint.
- About the agent: bio in three short paragraphs. Areas served chip list. Specialties chip list.
- Current listings: 3 OR 6 placeholder address-card listings. Each card has a photo, address line, beds and baths, square footage, and price. Add a small caption above the grid that says listings update from MLS once IDX is wired up. Write that caption in natural English (the brokerage IDX comes online once we kick off).
- Process: three columns. Buy. Sell. Invest. One paragraph each in plain language.
- Contact block: click-to-call plus simple form.
- Footer with Equal Housing Opportunity mark plus brokerage disclaimer placeholder.
## Photo strategy
Verified IDs. photo-1502780402662-acc01917b40c (St. George red rock vista), photo-1564013799919-ab600027ffc6 (modern home exterior), photo-1600585154340-be6161a56a0c (luxury home interior), photo-1494526585095-c41746248156 (Utah desert sunset). The red rock is the visual signature.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 44 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/eric-gubler"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=eric-gubler --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://eric-gubler.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://eric-gubler.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://eric-gubler.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://eric-gubler.pages.dev | grep -c "(435) 619-2841"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://eric-gubler.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://eric-gubler.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://eric-gubler.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/eric-gubler/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 619-2841`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 44 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://eric-gubler.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://eric-gubler.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
11. Rick C. Mellen
Vertical: Law firm
Slug: mellen-law
Phone (CSV): (435) 673-4892
Address (CSV): 187 100 W, St. George, UT 84770
Google rating (CSV): 4.9★ (34 reviews)
Live URL after deploy: https://mellen-law.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Rick C. Mellen
- **Vertical:** Law firm
- **Phone:** (435) 673-4892
- **Address:** 187 100 W, St. George, UT 84770
- **Google rating:** 4.9★ (34 reviews)
- **Slug:** `mellen-law`
- **Live URL after deploy:** `https://mellen-law.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Rick%20C.%20Mellen+St+George+UT`
Confirm phone matches CSV ((435) 673-4892). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "law firm St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Look up the firm on the Utah State Bar member directory: https://www.utahbar.org/find-a-lawyer/. Confirm the attorney's bar number and year admitted.
- Check FindLaw and Martindale-Hubbell for the attorney's profile and any peer ratings.
- Search the Washington County courthouse case search to confirm the attorney has filed cases recently. This is for verification only, do NOT include this on the site.
- Note any disciplinary history. Also for verification only, NEVER on the site.
6. **Save the research** to `apps/mellen-law/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for law firm
Editorial newspaper layout. Big serif drop caps on the first paragraph of the About section. A pull-quote bar between Practice Areas and About in the style of a print case-law citation. Numbered chapter labels (01, 02, 03) on every section. Subtle 1px hairline dividers in cream over deep ink. The site reads like a quiet, serious law-review essay, not a marketing splash.
This is the most important creative direction. Lean in. The site should look like a law firm site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Solo attorney. Same template direction as Altman but let this site feel a little less old-school newspaper and a little more current. Cream and deep green palette instead of navy and gold. Differentiate.
## Typography
Display: Fraunces (Google Fonts, opsz 144, weights 400 + 500 + 600). Body: DM Sans (weights 400 + 500). Mono: JetBrains Mono (weights 400 + 500). Use Fraunces italic for the accent phrase in every headline. Display letter-spacing tight (-0.025em). Display line-height 0.92 on hero h1. Body line-height 1.6. Mono for chapter labels and small caps, uppercased, tracked 0.18em.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: Ink-900 #100e0c. Foreground primary: Cream-50 #fbf6e9. Foreground muted: Cream-200 #ebdfb8 with 85% opacity. Italic accent + section numbers: Sand-300 #d39558. Primary CTA: Sand-500 #b85f30. Hairline dividers: rgba(244, 236, 214, 0.16). Avoid the navy-and-gold cliche every other Utah firm uses. The palette should feel like St. George red rock at dusk plus the gravitas of an old legal letterhead.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Restrained. Hero renders fully static (no scroll-triggered reveals on hero content, the intersection observer races with hydration on first paint). Below-fold sections use Reveal with 24px y-slide plus 6px blur, 700ms duration, easing cubic-bezier(0.16, 1, 0.3, 1). Cards lift opacity on hover (60 to 80) with a 700ms transition. One MagneticButton on the primary Free Consultation CTA. No CursorHalo, no TiltCard.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Pentagram editorial spreads. The New York Times Magazine cover typography. The quiet authority of Sullivan & Cromwell's website without the corporate stuffiness. The site should feel like an inside-cover page from a print volume, not a SaaS landing page.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/mellen-law/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"mellen-law"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: small monogram logo, links for Practice / About / Office, click-to-call phone, and a Free consultation CTA. Sticky on scroll, subtle border on scroll past hero.
- Hero: editorial top line with EST. + city + state on the left, italic Vol. 01 tagline on the right, separated by a hairline border. Below: Google rating badge (real data from the CSV). Then a static h1 headline that names the city, with one italic Fraunces accent phrase. Then a two-or-three-sentence sub-paragraph naming the practice angle. Two CTAs: Free consultation primary, click-to-call outline. On the right (lg:col-span-4): a firm summary card with attorney name, office address, direct line, in a small datasheet layout. Hero MUST render visible on first paint (static, no Reveal wrappers).
- Marquee: a horizontal scrolling band of practice keywords and trust signals, separated by section markers (the section sign §). Used between hero and Practice Areas as a visual breath.
- Practice Areas: 4 OR 6 cards (never 5, never 7), uniform 2x3 grid. Each card has a numeral label (01, 02, ...), a short serif heading, one sentence of plain copy, and one verified Unsplash photo. Use generic Utah practice areas as natural-sounding copy: estate planning and wills, family law, personal injury, criminal defense, business and contracts, real estate. Write as if the firm wrote it themselves. Card photos must match the section topic (verified, not random query).
- Pull quote: a print case-law citation between Practice Areas and About. One quotation mark in italic Fraunces. One short, declarative sentence. One small caption underneath in mono uppercase, tracked 0.22em, like a footnote citation. Example caption pattern: § Office practice, since 1995.
- About the attorney: two-column layout (lg:col-span-7 and lg:col-span-5). Left column has the headline (Practicing law in St. George since YYYY with italic accent on the year), then THREE plain-English paragraphs about the attorney. The first paragraph carries the editorial drop cap (a large Fraunces initial letter floated left, sized to span three lines). Below the bio, a three-cell datasheet: Bar admission, Practicing X years (since YYYY), Consultation (Free, 30 min). Right column: a single dignified photo of legal materials with a simple natural caption like 'Inside the firm office on 700 South.'
- Why this office: three numbered reasons in a 3-column grid with hairline gaps between cells. 01 Local, not regional. 02 Free initial consultation. 03 Direct attorney access. One short paragraph each, plain language.
- Free consultation CTA block: full-bleed band in the sand accent color. Two-column. Left side has the headline (Talk to the attorney, italic Not an intake screener), then a paragraph explaining the consultation, then a primary click-to-call CTA. Below: hours and address strip, two columns. Right side: a simple form (name, phone, brief description) with a Request consultation submit button. Form helper text natural, no template-meta language.
- Office: two-column. Left has the headline (Downtown St. George, italic Walking-distance to the courthouse), then four icon rows for Address, Direct line, Office hours, Parking. Two CTAs at the bottom: Call now and Driving directions. Right has an embedded Google Map iframe at the real address with a soft sepia/grayscale filter applied via CSS for visual cohesion.
- Footer: monogram logo, address, phone, sections links. Two disclaimer paragraphs across 12 columns: attorney advertising disclaimer + past results disclaimer (standard for U.S. law firm sites under model rules).
## Photo strategy
Verified Unsplash IDs (curated, all 200 + correct subject). photo-1589994965851-a8f479c573a9 (law books on shelf, hero backdrop), photo-1521133573892-e44906baee46 (estate planning card), photo-1568992687947-868a62a9f521 (legal documents on desk, family law), photo-1453873531674-2151bcd01707 (urban scene, personal injury), photo-1589216532372-1c2a367900d9 (gavel, criminal defense), photo-1554224154-26032ffc0d07 (papers on desk, business law), photo-1564013799919-ab600027ffc6 (modern home exterior, real estate), photo-1521587760476-6c12a4b040da (law books, About). DO NOT use the source.unsplash.com random query format. It returned a t-shirt photo on a previous build. Always use images.unsplash.com/photo-XXX with a verified ID.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 34 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/mellen-law"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=mellen-law --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://mellen-law.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://mellen-law.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://mellen-law.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://mellen-law.pages.dev | grep -c "(435) 673-4892"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://mellen-law.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://mellen-law.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://mellen-law.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/mellen-law/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 673-4892`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 34 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://mellen-law.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://mellen-law.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
12. Derays Park St Automotive
Vertical: Auto repair shop
Slug: derays-auto
Phone (CSV): (435) 628-1655
Address (CSV): 375 N Park St A, St. George, UT 84770
Google rating (CSV): 4.8★ (117 reviews)
Live URL after deploy: https://derays-auto.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Derays Park St Automotive
- **Vertical:** Auto repair shop
- **Phone:** (435) 628-1655
- **Address:** 375 N Park St A, St. George, UT 84770
- **Google rating:** 4.8★ (117 reviews)
- **Slug:** `derays-auto`
- **Live URL after deploy:** `https://derays-auto.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Derays%20Park%20St%20Automotive+St+George+UT`
Confirm phone matches CSV ((435) 628-1655). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "auto repair shop St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check ASE certification listing if available: https://www.ase.com/find-a-shop. Confirm ASE-certified status if claimed.
- Note brands they specialize in (some are domestic-focused, some import-focused, some are both).
- Read reviews for tone (some shops lean honest-mechanic, some lean technical-expert, some lean family-friendly).
6. **Save the research** to `apps/derays-auto/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for auto repair shop
Garage chalkboard plus mechanical schematic motif. Service prices written in a chalk-style accent font (used sparingly as labels). A schematic line-drawing of a car as a hero overlay or section divider. Authentic shop photography. The site feels like a working bay, not a corporate dealer site.
This is the most important creative direction. Lean in. The site should look like a auto repair shop site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Auto repair shop. Slightly more vintage-shop heritage feel, sepia-leaning hero photography.
## Typography
Display: Bebas Neue (condensed bold). Body: Inter (weights 400 + 500). Accent: Permanent Marker or Special Elite (chalk-style, sparingly on price labels only). Mono: JetBrains Mono.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: near-black #0F0F0F. Foreground: cream #F4ECD8. Steel gray secondary: #3A3A3A. Bold red accent: #D9302E (CTAs). Amber secondary accent: #F4A623 (price labels). Concrete gray for textures: #9B9B9B.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Bold but not gimmicky. Hero static. Below-fold Reveal with 20px y-slide, 600ms. Cards have a subtle wrench-icon hover state.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Singer Vehicle Design's website (premium automotive heritage). Iron and Resin's branding. The vintage shop signage of Highway 89.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/derays-auto/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"derays-auto"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Hours, Contact, click-to-call, Free estimate CTA.
- Hero: shop interior or under-the-hood photo. Bold display headline with the shop name. One-line tagline naming the city. Two CTAs (Free estimate primary, click-to-call outline). Trust strip with three pills (ASE-certified if real, family owned, warranty on all work). Headline visible on first paint.
- Services: 6 OR 8 cards. Oil change, brakes, transmission, A/C, diagnostics, tires, suspension, engine. Prime Tire variant: lead with tire services. Each card has a chalk-style price label in amber.
- Why us: 4 short bullets. ASE certified, family owned, X years in business, warranty on all work.
- Brands serviced: chip list. Toyota, Honda, Ford, Chevy, Subaru, Nissan, Dodge, Jeep, Ram, GMC.
- Hours and location: simple table plus map iframe.
- Free estimate block: click-to-call plus optional simple form.
- Footer.
## Photo strategy
Verified IDs. photo-1487754180451-c456f719a1fc (mechanic at work), photo-1632823469850-1b7b1e8b7f0c (engine bay), photo-1632823471565-1ec3a1e89a6f (shop interior wide), photo-1486006920555-c77dcf18193c (tools rack).
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.8★ on Google, 117 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/derays-auto"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.8★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=derays-auto --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://derays-auto.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://derays-auto.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://derays-auto.pages.dev | grep -c "4.8★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://derays-auto.pages.dev | grep -c "(435) 628-1655"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://derays-auto.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://derays-auto.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://derays-auto.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/derays-auto/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 628-1655`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.8★`, 117 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://derays-auto.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://derays-auto.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
13. Washington Service & Repair
Vertical: Auto repair shop
Slug: washington-auto
Phone (CSV): (435) 628-5205
Address (CSV): 214 W Telegraph St, Washington, UT 84780
Google rating (CSV): 4.7★ (138 reviews)
Live URL after deploy: https://washington-auto.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Washington Service & Repair
- **Vertical:** Auto repair shop
- **Phone:** (435) 628-5205
- **Address:** 214 W Telegraph St, Washington, UT 84780
- **Google rating:** 4.7★ (138 reviews)
- **Slug:** `washington-auto`
- **Live URL after deploy:** `https://washington-auto.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Washington%20Service%20%26%20Repair+St+George+UT`
Confirm phone matches CSV ((435) 628-5205). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "auto repair shop St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check ASE certification listing if available: https://www.ase.com/find-a-shop. Confirm ASE-certified status if claimed.
- Note brands they specialize in (some are domestic-focused, some import-focused, some are both).
- Read reviews for tone (some shops lean honest-mechanic, some lean technical-expert, some lean family-friendly).
6. **Save the research** to `apps/washington-auto/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for auto repair shop
Garage chalkboard plus mechanical schematic motif. Service prices written in a chalk-style accent font (used sparingly as labels). A schematic line-drawing of a car as a hero overlay or section divider. Authentic shop photography. The site feels like a working bay, not a corporate dealer site.
This is the most important creative direction. Lean in. The site should look like a auto repair shop site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Auto repair shop. Lean local-Washington-County angle, service-area chip list emphasizes Washington and Hurricane.
## Typography
Display: Bebas Neue (condensed bold). Body: Inter (weights 400 + 500). Accent: Permanent Marker or Special Elite (chalk-style, sparingly on price labels only). Mono: JetBrains Mono.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: near-black #0F0F0F. Foreground: cream #F4ECD8. Steel gray secondary: #3A3A3A. Bold red accent: #D9302E (CTAs). Amber secondary accent: #F4A623 (price labels). Concrete gray for textures: #9B9B9B.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Bold but not gimmicky. Hero static. Below-fold Reveal with 20px y-slide, 600ms. Cards have a subtle wrench-icon hover state.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Singer Vehicle Design's website (premium automotive heritage). Iron and Resin's branding. The vintage shop signage of Highway 89.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/washington-auto/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"washington-auto"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Hours, Contact, click-to-call, Free estimate CTA.
- Hero: shop interior or under-the-hood photo. Bold display headline with the shop name. One-line tagline naming the city. Two CTAs (Free estimate primary, click-to-call outline). Trust strip with three pills (ASE-certified if real, family owned, warranty on all work). Headline visible on first paint.
- Services: 6 OR 8 cards. Oil change, brakes, transmission, A/C, diagnostics, tires, suspension, engine. Prime Tire variant: lead with tire services. Each card has a chalk-style price label in amber.
- Why us: 4 short bullets. ASE certified, family owned, X years in business, warranty on all work.
- Brands serviced: chip list. Toyota, Honda, Ford, Chevy, Subaru, Nissan, Dodge, Jeep, Ram, GMC.
- Hours and location: simple table plus map iframe.
- Free estimate block: click-to-call plus optional simple form.
- Footer.
## Photo strategy
Verified IDs. photo-1487754180451-c456f719a1fc (mechanic at work), photo-1632823469850-1b7b1e8b7f0c (engine bay), photo-1632823471565-1ec3a1e89a6f (shop interior wide), photo-1486006920555-c77dcf18193c (tools rack).
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.7★ on Google, 138 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/washington-auto"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.7★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=washington-auto --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://washington-auto.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://washington-auto.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://washington-auto.pages.dev | grep -c "4.7★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://washington-auto.pages.dev | grep -c "(435) 628-5205"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://washington-auto.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://washington-auto.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://washington-auto.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/washington-auto/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 628-5205`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.7★`, 138 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://washington-auto.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://washington-auto.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
14. Preferred Pressure Washing
Vertical: Pressure washing service
Slug: preferred-pressure
Phone (CSV): (435) 773-7576
Address (CSV): 47 S 400 E, St. George, UT 84770
Google rating (CSV): 4.9★ (36 reviews)
Live URL after deploy: https://preferred-pressure.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Preferred Pressure Washing
- **Vertical:** Pressure washing service
- **Phone:** (435) 773-7576
- **Address:** 47 S 400 E, St. George, UT 84770
- **Google rating:** 4.9★ (36 reviews)
- **Slug:** `preferred-pressure`
- **Live URL after deploy:** `https://preferred-pressure.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Preferred%20Pressure%20Washing+St+George+UT`
Confirm phone matches CSV ((435) 773-7576). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "pressure washing service St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check Google, Facebook, and Instagram for actual before-after photos and service list.
- Confirm whether they offer soft washing, roof washing, gutter cleaning, fleet washing, or sealing before displaying those services.
- Read reviews for repeated praise around punctuality, results, careful plant protection, and communication.
6. **Save the research** to `apps/preferred-pressure/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for pressure washing service
Fresh exterior-cleaning transformation motif. Split before-after surfaces, water-line dividers, and bright clean concrete photography. The design should feel crisp, local, and practical, not industrial roofing.
This is the most important creative direction. Lean in. The site should look like a pressure washing service site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Exterior-cleaning lead. Build around pressure washing, soft washing, driveway and patio cleaning, gutter cleaning if verified, and surface protection. Photography should emphasize clean residential exteriors and before-after surface details.
## Typography
Display: Manrope or Sora (weight 700). Body: Inter (weights 400 + 500). Mono: JetBrains Mono for estimate details and route labels.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: white #FAFCFD. Foreground: deep slate #14212B. Water blue #0E7BA7 for CTAs. Clean concrete #E6EDF1. Sunlit clay #C9784A as a small accent. Dividers: rgba(20, 33, 43, 0.12).
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Clean and snappy. Hero static. Below-fold Reveal with 18px y-slide, 500ms. Before-after sliders may animate only after visible, never on first paint.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Simple field-service websites, Method's clean product photography, and polished driveway-cleaning before-after reels translated into a website.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/preferred-pressure/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"preferred-pressure"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Results, Areas, Contact, click-to-call, Free estimate CTA primary.
- Hero: clean driveway, home exterior, or washing-in-action photo. Business name plus one-line exterior cleaning position statement. Two CTAs: Free estimate primary and call now outline. Trust strip: soft wash available, written estimates, residential and commercial.
- Services: 6 cards. House soft wash, driveways, patios, windows or storefronts, gutters, fleet or commercial, concrete sealing only if verified.
- Before-after: 4 transformation panels using verified surface photos, clearly labeled as sample surface types unless real project photos are verified.
- Process: walk, protect, pre-treat, wash, final check.
- Service area: St. George, Washington, Hurricane, Ivins, Santa Clara, La Verkin, Toquerville.
- Estimate block: form with name, phone, property address, surfaces to clean, timeline plus click-to-call alternate.
- Footer: phone, address, service area, social placeholders.
## Photo strategy
Verified IDs. photo-1607113364993-4f639eb54ebb (driveway or concrete), photo-1564013799919-ab600027ffc6 (home exterior), photo-1600596542815-ffad4c1539a9 (patio), photo-1571055107559-3e67626fa8be (storefront), photo-1592365559101-19adfefdf294 (commercial vehicle). Verify subject match in browser before use.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 36 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/preferred-pressure"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=preferred-pressure --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://preferred-pressure.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://preferred-pressure.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://preferred-pressure.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://preferred-pressure.pages.dev | grep -c "(435) 773-7576"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://preferred-pressure.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://preferred-pressure.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://preferred-pressure.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/preferred-pressure/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 773-7576`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 36 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://preferred-pressure.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://preferred-pressure.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
15. Provent Pest Control
Vertical: Pest control
Slug: provent-pest
Phone (CSV): (435) 619-7568
Address (CSV): St. George, UT
Google rating (CSV): 4.8★ (71 reviews)
Live URL after deploy: https://provent-pest.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Provent Pest Control
- **Vertical:** Pest control
- **Phone:** (435) 619-7568
- **Address:** St. George, UT
- **Google rating:** 4.8★ (71 reviews)
- **Slug:** `provent-pest`
- **Live URL after deploy:** `https://provent-pest.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Provent%20Pest%20Control+St+George+UT`
Confirm phone matches CSV ((435) 619-7568). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "pest control St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check Utah Department of Agriculture pesticide applicator license (https://ag.utah.gov/) for the company's license.
- Note Utah-specific pests (scorpions are a real St. George concern, mention them).
- Check if they offer monthly contracts or one-time service (informs the CTA).
6. **Save the research** to `apps/provent-pest/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for pest control
Home blueprint plus family-safe motif. A faint house-blueprint background behind the service grid. Pet-safe and family-friendly imagery (yards, kids, dogs) instead of pest close-ups. A small shield icon used as the trust badge motif.
This is the most important creative direction. Lean in. The site should look like a pest control site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Pest control. Lean modern-clean-corporate feel, more polished than Outlaw.
## Typography
Display: Familjen Grotesk or Manrope (clean grotesque, weight 600 + 700). Body: Inter (400 + 500). Mono: JetBrains Mono. Friendly humanist personality.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: cream-white #FAF6EE. Foreground: forest green #2D5F3F. Secondary earth #9B7A4E. Accent safety-orange #E66A26 (CTAs and warning chevrons only). Avoid bright greens, they look amateur.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Friendly. Hero static. Below-fold Reveal with 18px y-slide, 500ms. Shield icons gently fade in.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Truly Nolen's premium service site without the cartoon mouse. Orkin's clean information architecture. Modern home service brands like Hippo or Lemonade.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/provent-pest/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"provent-pest"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Service area, Contact, click-to-call, Free inspection CTA primary.
- Hero: family-friendly home exterior photo. Clean grotesque headline with the company name. One-line tagline naming Southern Utah. Two CTAs. Trust strip (pet safe, family friendly, local). Headline visible on first paint.
- Services: 4 OR 6 cards in 2x2 or 2x3 grid. Residential, commercial, ants, spiders, scorpions and roaches, rodents, termites. Standard card pattern.
- Pet-safe block: wide horizontal block with one large image of a yard or dog and three plain bullets explaining pet and family safety.
- Service area: chip list with St. George, Washington, Hurricane, Ivins, Santa Clara, La Verkin, Cedar City.
- Free inspection block: simple form (name, phone, address, brief description) plus click-to-call.
- Why us: 3 plain bullets. Licensed. Insured. Locally owned.
- Footer.
## Photo strategy
Verified IDs. photo-1564540583246-934409427776 (residential exterior), photo-1583912086296-be5b665036d3 (yard with green grass), photo-1493780474520-aff4e8af265c (dog on porch), photo-1542621334-a254cf47733d (Utah desert landscape). Avoid pest close-ups.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.8★ on Google, 71 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/provent-pest"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.8★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=provent-pest --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://provent-pest.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://provent-pest.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://provent-pest.pages.dev | grep -c "4.8★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://provent-pest.pages.dev | grep -c "(435) 619-7568"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://provent-pest.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://provent-pest.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://provent-pest.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/provent-pest/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 619-7568`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.8★`, 71 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://provent-pest.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://provent-pest.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
16. Cool Mechanical
Vertical: HVAC contractor
Slug: cool-mechanical
Phone (CSV): (435) 231-5895
Address (CSV): St. George, UT
Google rating (CSV): 5★ (29 reviews)
Live URL after deploy: https://cool-mechanical.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Cool Mechanical
- **Vertical:** HVAC contractor
- **Phone:** (435) 231-5895
- **Address:** St. George, UT
- **Google rating:** 5★ (29 reviews)
- **Slug:** `cool-mechanical`
- **Live URL after deploy:** `https://cool-mechanical.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Cool%20Mechanical+St+George+UT`
Confirm phone matches CSV ((435) 231-5895). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "hvac contractor St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check Utah Division of Professional Licensing for the HVAC contractor license.
- Note brands carried (Trane, Carrier, Lennox, Goodman). Adjust the brands chip list.
- Note if they offer 24/7 emergency service (some do, some don't, don't fabricate).
6. **Save the research** to `apps/cool-mechanical/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for hvac contractor
Cool, calibrated, instrumentation feel. A small thermostat-dial UI element near the hero, showing a comfortable temperature. A weather strip showing local Utah temps. Strong photography of comfortable home interiors.
This is the most important creative direction. Lean in. The site should look like a hvac contractor site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
HVAC. Lean modern minimal, not industrial. The wordmark Cool Mechanical wants a clean sans treatment.
## Typography
Display: Manrope (weights 600 + 700) or Inter Display. Body: Inter. Mono: JetBrains Mono.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: white #FFFFFF. Foreground: deep navy #0F2433. Primary sky blue #3B8DDC. Steel gray secondary #5A6B7A. Accent warm orange #F26B1F (emergency CTAs only, not standard CTAs).
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Modern minimal. Hero static. Below-fold Reveal with 16px y-slide, 500ms. Thermostat dial has a subtle tick animation.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Ecobee's product site. Nest's old marketing pages. Carrier's modern marketing without the corporate feel.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/cool-mechanical/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"cool-mechanical"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Maintenance plans, Contact, click-to-call, Free estimate CTA.
- Hero: comfortable family interior or home exterior. Modern sans headline. One-line tagline naming the city. Free estimate and click-to-call CTAs. Trust strip (licensed, 24/7 emergency if true, local). Small thermostat dial UI element near the headline. Headline visible on first paint.
- Services: 6 OR 8 cards. AC repair, AC install, heating, heat pumps, maintenance, indoor air quality, ductwork.
- Emergency block: only if 24/7 service is real. Big orange-accent banner with click-to-call.
- Maintenance plans: simple three-tier comparison table (Bronze, Silver, Gold) with checkmarks. Use natural plan names and natural feature copy.
- Service area: chip list.
- Free estimate block.
- Footer.
## Photo strategy
Verified IDs. photo-1605283176567-fc4f7a8c99e1 (modern thermostat), photo-1581094288338-2314dddb7ece (comfortable home interior), photo-1574269909862-7e1d70bb8ca1 (HVAC technician), photo-1565538810643-b5bdb714032a (clean residential exterior).
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`5★ on Google, 29 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/cool-mechanical"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "5★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=cool-mechanical --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://cool-mechanical.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://cool-mechanical.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://cool-mechanical.pages.dev | grep -c "5★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://cool-mechanical.pages.dev | grep -c "(435) 231-5895"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://cool-mechanical.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://cool-mechanical.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://cool-mechanical.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/cool-mechanical/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 231-5895`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`5★`, 29 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://cool-mechanical.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://cool-mechanical.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
17. Los Tapatios Mexican Restaurant
Vertical: Restaurant
Slug: los-tapatios
Phone (CSV): (435) 652-1693
Address (CSV): 987 S Bluff St, St. George, UT 84770
Google rating (CSV): 4.5★ (573 reviews)
Live URL after deploy: https://los-tapatios.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Los Tapatios Mexican Restaurant
- **Vertical:** Restaurant
- **Phone:** (435) 652-1693
- **Address:** 987 S Bluff St, St. George, UT 84770
- **Google rating:** 4.5★ (573 reviews)
- **Slug:** `los-tapatios`
- **Live URL after deploy:** `https://los-tapatios.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Los%20Tapatios%20Mexican%20Restaurant+St+George+UT`
Confirm phone matches CSV ((435) 652-1693). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "restaurant St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Find the restaurant on Yelp and DoorDash. Note hours, menu (if visible), and any photos of dishes.
- Check Google Maps photos to see what their actual interior and food looks like (informs photo direction without claiming the photos are theirs).
- Read 5 to 10 reviews. Note recurring praised dishes (don't quote anyone). The owner can confirm during onboarding.
- Check if they're on Instagram. If yes, link the handle in the footer placeholder.
6. **Save the research** to `apps/los-tapatios/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for restaurant
Full-bleed food photography. A handwritten or hand-drawn accent script for menu category labels and specials. Warm grain texture overlay over hero photos. Dish names large, prices small. Navigation feels like a printed menu, not a SaaS landing page.
This is the most important creative direction. Lean in. The site should look like a restaurant site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Different from Irmita's. Lean darker and bolder. Near-black #0F0F0F background, deep red #B22222 secondary, lime accent #C5DC4D. Use Bebas Neue for the wordmark (neon-sign vibe with a thin underline glow), Inter for body. The food photography is moodier, low-key lit, almost food-noir. Differentiate from Irmita's by leaning urban-cantina rather than family-cantina.
## Typography
See per-business twist for the cuisine-specific pairing. General direction: a strong serif or display sans for dish names + a clean humanist sans for body + a single hand-script accent (Caveat or Permanent Marker) used SPARINGLY on category labels.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
See per-business twist. Mexican leans deep red plus warm cream plus lime accent plus earthy clay. American cafe leans off-white parchment plus forest green plus gold plus bookcloth red. Healthy bowl leans sage plus cream plus white plus a small coral accent. Always warm and food-appropriate.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Generous but never flashy. Hero food photo has a subtle slow ken-burns (3 to 5 percent scale, 8 to 12 second loop). Below-fold sections use Reveal with 18px y-slide, no blur, 600ms. Menu cards lift on hover (TiltCard primitive, 6 degrees max rotation). Marquee scrolls at a calm 38 second loop.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Per cuisine: Mexican leans Hijos de Villa style cantina warmth crossed with editorial food magazine. American cafe leans Penguin Classics covers crossed with Boulder bookstore signage. Healthy bowl leans Sweetgreen-but-better, with full-bleed editorial food shots like Bon Appetit.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/los-tapatios/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"los-tapatios"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: short logo, Menu, About, Hours, click-to-call, Order CTA primary.
- Hero: a single appetizing close-up dish photo as a full-bleed background with a subtle ken-burns. Restaurant name on top in display type. One-line tagline naming the cuisine and city. Two CTAs: Order primary, Reservations or click-to-call outline. A small strip below shows hours and address. Hero must render visible on first paint (static).
- Marquee: scrolling kitchen-language band of dish keywords plus trust signals.
- Featured menu: 6 OR 8 cards in a uniform grid (3x2 or 4x2). Each card has a verified dish photo, a name, a one-line description, and a price. Use cuisine-appropriate generic dishes that the owner can edit.
- About the restaurant: two-column. Left column has the headline plus a short two-or-three-sentence story (family owned, from-scratch cooking, neighborhood feel). Right column has a single interior photo with a natural caption.
- Photo gallery: 6 to 9 verified food and interior shots in a clean masonry or grid layout.
- Hours and location: simple table for the week + a real Google Maps iframe at the real address.
- Order CTA: full-bleed band. Big click-to-call using the real phone, plus DoorDash and UberEats ghost buttons if applicable.
- Footer: hours, address, phone, social handles as placeholders.
## Photo strategy
Verified IDs by cuisine. Mexican: photo-1565299585323-38d6b0865b47 (tacos), photo-1599974579688-8dbdd335c77f (enchiladas), photo-1551504734-5ee1c4a1479b (salsa and chips), photo-1565958011703-44f9829ba187 (charro plate). American cafe: photo-1509440159596-0249088772ff (latte art), photo-1495474472287-4d71bcdd2085 (pastry case), photo-1525351484163-7529414344d8 (brunch plate). Healthy bowl: photo-1546069901-ba9599a7e63c (grain bowl), photo-1540420773420-3366772f4999 (greens). Verify each ID returns HTTP 200 with curl AND open in a browser to confirm the subject. NEVER use source.unsplash.com.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.5★ on Google, 573 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/los-tapatios"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.5★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=los-tapatios --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://los-tapatios.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://los-tapatios.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://los-tapatios.pages.dev | grep -c "4.5★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://los-tapatios.pages.dev | grep -c "(435) 652-1693"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://los-tapatios.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://los-tapatios.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://los-tapatios.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/los-tapatios/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 652-1693`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.5★`, 573 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://los-tapatios.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://los-tapatios.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
18. Summit Pest Control LLC
Vertical: Pest control
Slug: summit-pest
Phone (CSV): (435) 216-3333
Address (CSV): 782 S River Rd #265, St. George, UT 84790
Google rating (CSV): 4.9★ (56 reviews)
Live URL after deploy: https://summit-pest.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Summit Pest Control LLC
- **Vertical:** Pest control
- **Phone:** (435) 216-3333
- **Address:** 782 S River Rd #265, St. George, UT 84790
- **Google rating:** 4.9★ (56 reviews)
- **Slug:** `summit-pest`
- **Live URL after deploy:** `https://summit-pest.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Summit%20Pest%20Control%20LLC+St+George+UT`
Confirm phone matches CSV ((435) 216-3333). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "pest control St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check Utah Department of Agriculture pesticide applicator license (https://ag.utah.gov/) for the company's license.
- Note Utah-specific pests (scorpions are a real St. George concern, mention them).
- Check if they offer monthly contracts or one-time service (informs the CTA).
6. **Save the research** to `apps/summit-pest/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for pest control
Home blueprint plus family-safe motif. A faint house-blueprint background behind the service grid. Pet-safe and family-friendly imagery (yards, kids, dogs) instead of pest close-ups. A small shield icon used as the trust badge motif.
This is the most important creative direction. Lean in. The site should look like a pest control site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Pest control. Mountain-summit motif as a small icon used sparingly on section dividers. Otherwise standard.
## Typography
Display: Familjen Grotesk or Manrope (clean grotesque, weight 600 + 700). Body: Inter (400 + 500). Mono: JetBrains Mono. Friendly humanist personality.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: cream-white #FAF6EE. Foreground: forest green #2D5F3F. Secondary earth #9B7A4E. Accent safety-orange #E66A26 (CTAs and warning chevrons only). Avoid bright greens, they look amateur.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Friendly. Hero static. Below-fold Reveal with 18px y-slide, 500ms. Shield icons gently fade in.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Truly Nolen's premium service site without the cartoon mouse. Orkin's clean information architecture. Modern home service brands like Hippo or Lemonade.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/summit-pest/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"summit-pest"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Service area, Contact, click-to-call, Free inspection CTA primary.
- Hero: family-friendly home exterior photo. Clean grotesque headline with the company name. One-line tagline naming Southern Utah. Two CTAs. Trust strip (pet safe, family friendly, local). Headline visible on first paint.
- Services: 4 OR 6 cards in 2x2 or 2x3 grid. Residential, commercial, ants, spiders, scorpions and roaches, rodents, termites. Standard card pattern.
- Pet-safe block: wide horizontal block with one large image of a yard or dog and three plain bullets explaining pet and family safety.
- Service area: chip list with St. George, Washington, Hurricane, Ivins, Santa Clara, La Verkin, Cedar City.
- Free inspection block: simple form (name, phone, address, brief description) plus click-to-call.
- Why us: 3 plain bullets. Licensed. Insured. Locally owned.
- Footer.
## Photo strategy
Verified IDs. photo-1564540583246-934409427776 (residential exterior), photo-1583912086296-be5b665036d3 (yard with green grass), photo-1493780474520-aff4e8af265c (dog on porch), photo-1542621334-a254cf47733d (Utah desert landscape). Avoid pest close-ups.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 56 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/summit-pest"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=summit-pest --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://summit-pest.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://summit-pest.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://summit-pest.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://summit-pest.pages.dev | grep -c "(435) 216-3333"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://summit-pest.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://summit-pest.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://summit-pest.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/summit-pest/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 216-3333`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 56 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://summit-pest.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://summit-pest.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
19. Somerville Auto & Marine
Vertical: Auto repair shop
Slug: somerville-auto
Phone (CSV): (435) 627-2211
Address (CSV): 2375 E Middleton Dr, St. George, UT 84770
Google rating (CSV): 4.7★ (114 reviews)
Live URL after deploy: https://somerville-auto.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Somerville Auto & Marine
- **Vertical:** Auto repair shop
- **Phone:** (435) 627-2211
- **Address:** 2375 E Middleton Dr, St. George, UT 84770
- **Google rating:** 4.7★ (114 reviews)
- **Slug:** `somerville-auto`
- **Live URL after deploy:** `https://somerville-auto.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Somerville%20Auto%20%26%20Marine+St+George+UT`
Confirm phone matches CSV ((435) 627-2211). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "auto repair shop St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check ASE certification listing if available: https://www.ase.com/find-a-shop. Confirm ASE-certified status if claimed.
- Note brands they specialize in (some are domestic-focused, some import-focused, some are both).
- Read reviews for tone (some shops lean honest-mechanic, some lean technical-expert, some lean family-friendly).
6. **Save the research** to `apps/somerville-auto/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for auto repair shop
Garage chalkboard plus mechanical schematic motif. Service prices written in a chalk-style accent font (used sparingly as labels). A schematic line-drawing of a car as a hero overlay or section divider. Authentic shop photography. The site feels like a working bay, not a corporate dealer site.
This is the most important creative direction. Lean in. The site should look like a auto repair shop site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Auto repair plus marine. Add a Marine services row under the standard auto grid (boats, watercraft).
## Typography
Display: Bebas Neue (condensed bold). Body: Inter (weights 400 + 500). Accent: Permanent Marker or Special Elite (chalk-style, sparingly on price labels only). Mono: JetBrains Mono.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: near-black #0F0F0F. Foreground: cream #F4ECD8. Steel gray secondary: #3A3A3A. Bold red accent: #D9302E (CTAs). Amber secondary accent: #F4A623 (price labels). Concrete gray for textures: #9B9B9B.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Bold but not gimmicky. Hero static. Below-fold Reveal with 20px y-slide, 600ms. Cards have a subtle wrench-icon hover state.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Singer Vehicle Design's website (premium automotive heritage). Iron and Resin's branding. The vintage shop signage of Highway 89.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/somerville-auto/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"somerville-auto"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Hours, Contact, click-to-call, Free estimate CTA.
- Hero: shop interior or under-the-hood photo. Bold display headline with the shop name. One-line tagline naming the city. Two CTAs (Free estimate primary, click-to-call outline). Trust strip with three pills (ASE-certified if real, family owned, warranty on all work). Headline visible on first paint.
- Services: 6 OR 8 cards. Oil change, brakes, transmission, A/C, diagnostics, tires, suspension, engine. Prime Tire variant: lead with tire services. Each card has a chalk-style price label in amber.
- Why us: 4 short bullets. ASE certified, family owned, X years in business, warranty on all work.
- Brands serviced: chip list. Toyota, Honda, Ford, Chevy, Subaru, Nissan, Dodge, Jeep, Ram, GMC.
- Hours and location: simple table plus map iframe.
- Free estimate block: click-to-call plus optional simple form.
- Footer.
## Photo strategy
Verified IDs. photo-1487754180451-c456f719a1fc (mechanic at work), photo-1632823469850-1b7b1e8b7f0c (engine bay), photo-1632823471565-1ec3a1e89a6f (shop interior wide), photo-1486006920555-c77dcf18193c (tools rack).
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.7★ on Google, 114 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/somerville-auto"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.7★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=somerville-auto --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://somerville-auto.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://somerville-auto.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://somerville-auto.pages.dev | grep -c "4.7★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://somerville-auto.pages.dev | grep -c "(435) 627-2211"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://somerville-auto.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://somerville-auto.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://somerville-auto.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/somerville-auto/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 627-2211`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.7★`, 114 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://somerville-auto.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://somerville-auto.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
20. High Vibrations Healing
Vertical: Spa and wellness
Slug: high-vibrations
Phone (CSV): (435) 879-9180
Address (CSV): 640 E 700 S #101, St. George, UT 84770
Google rating (CSV): 4.9★ (74 reviews)
Live URL after deploy: https://high-vibrations.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** High Vibrations Healing
- **Vertical:** Spa and wellness
- **Phone:** (435) 879-9180
- **Address:** 640 E 700 S #101, St. George, UT 84770
- **Google rating:** 4.9★ (74 reviews)
- **Slug:** `high-vibrations`
- **Live URL after deploy:** `https://high-vibrations.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=High%20Vibrations%20Healing+St+George+UT`
Confirm phone matches CSV ((435) 879-9180). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "spa and wellness St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Note the practitioner's modalities (sound healing? reiki? massage? craniosacral?).
- Check if they're licensed massage therapist (LMT) or operate under a different credential.
- Read reviews for tone (calm, professional, intuitive vs. high-energy retreat-style).
6. **Save the research** to `apps/high-vibrations/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for spa and wellness
Soft watercolor wash backgrounds. Generous whitespace. A cursive accent script used only on a single phrase per section. Parallax-light scrolling. Imagery is dreamy and ethereal, candles and stones, never a face close-up.
This is the most important creative direction. Lean in. The site should look like a spa and wellness site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Spa and wellness vertical. Lean into sound healing and energy work as the headline services. The aesthetic is ethereal but grounded, not gimmicky-crystal-shop. Avoid rainbow chakra graphics. Lean monochrome with a single muted accent.
## Typography
Display: Cormorant Garamond or Italiana (weight 400, large). Body: Inter (400). Cursive accent: Allura or Italianno (weight 400, used SPARINGLY on one phrase per section). Mono: JetBrains Mono.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: warm cream #F4ECDF. Foreground: muted ink #2D2A26. Soft sage primary #A8B89C. Lavender secondary #C4B5D4. Rose-gold accent #D4A574 (CTAs only). Lots of negative space.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Dreamy. Hero static but with subtle background blob morphing. Below-fold Reveal with 12px y-slide, no blur, 600ms.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Aesop's website. Le Labo's brand identity. Goop without the wellness-grift energy. Spruce Hill's serene minimalism.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/high-vibrations/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"high-vibrations"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, About, Book CTA primary, click-to-call.
- Hero: a single calm ethereal photo. Serif display name. One-line tagline naming the city. Book CTA, click-to-call. Headline visible on first paint.
- Services: 4 OR 6 cards. Massage, energy work, reiki, sound healing, couples session.
- About the practitioner: bio in three plain paragraphs, single soft photo on the side.
- What to expect: ordered list of three steps for a first visit.
- Book block: click-to-call plus a Book online ghost link to Vagaro or Square placeholder.
- Footer.
## Photo strategy
Verified IDs. photo-1544161515-4ab6ce6db874 (candles soft), photo-1540555700478-4be289fbecef (massage stones), photo-1515377905703-c4788e51af15 (calm spa interior), photo-1580618672591-eb180b1a973f (incense smoke).
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 74 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/high-vibrations"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=high-vibrations --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://high-vibrations.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://high-vibrations.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://high-vibrations.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://high-vibrations.pages.dev | grep -c "(435) 879-9180"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://high-vibrations.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://high-vibrations.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://high-vibrations.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/high-vibrations/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 879-9180`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 74 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://high-vibrations.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://high-vibrations.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
21. Alcoa Construction
Vertical: Custom home builder
Slug: alcoa-construction
Phone (CSV): (435) 879-9866
Address (CSV): 1060 Province Way UNIT 121, St. George, UT 84770
Google rating (CSV): 4.9★ (30 reviews)
Live URL after deploy: https://alcoa-construction.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Alcoa Construction
- **Vertical:** Custom home builder
- **Phone:** (435) 879-9866
- **Address:** 1060 Province Way UNIT 121, St. George, UT 84770
- **Google rating:** 4.9★ (30 reviews)
- **Slug:** `alcoa-construction`
- **Live URL after deploy:** `https://alcoa-construction.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Alcoa%20Construction+St+George+UT`
Confirm phone matches CSV ((435) 879-9866). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "custom home builder St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Look for an existing portfolio, Houzz profile, Facebook page, or builder listings before choosing project categories.
- Check Utah DOPL for contractor license status and only display license details if verified.
- Review Google photos and reviews for whether the business is custom homes, remodels, additions, or general construction.
6. **Save the research** to `apps/alcoa-construction/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for custom home builder
Portfolio-grade desert-modern builder motif. Full-bleed architecture photography, site-plan lines, material samples, and large project captions. It should feel more like a custom home portfolio than a trades landing page.
This is the most important creative direction. Lean in. The site should look like a custom home builder site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Custom home builder lead. Build around new homes, remodels, additions, and construction project management. Lean into a portfolio look with big project photos, material details, and location-style captions.
## Typography
Display: Cormorant Garamond or Canela-style serif (weight 500). Body: Inter (weights 400 + 500). Mono: JetBrains Mono for project specs and build-phase labels.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: warm plaster #F5EFE6. Foreground: charcoal #1E2528. Desert stone #B58A63. Sage #5F725D. Bone #FFFDF7. Dividers: rgba(30, 37, 40, 0.12).
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Editorial and restrained. Hero static. Below-fold sections use Reveal with 14px y-slide, no blur, 600ms. Project images can have a slow scale on hover.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Studio McGee project pages, Olson Kundig portfolio restraint, and Southern Utah desert architecture.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/alcoa-construction/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"alcoa-construction"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Portfolio, Process, Services, About, Contact, consultation CTA primary.
- Hero: desert-modern home or construction-detail photo. Business name as the headline. One-line custom-home position statement for Southern Utah. CTAs: Start a consultation and call.
- Project portfolio: 4 OR 6 large image tiles with location-style captions and scope labels. Do not claim real projects unless verified.
- Services: custom homes, remodels, additions, design-build coordination, project management, site planning.
- Process: discovery, plans, budget, build, walkthrough as a refined timeline.
- Trust details: licensed if verified, local subcontractor network, transparent scheduling, owner communication.
- Consultation block: name, phone, project type, lot status, timeline plus click-to-call alternate.
- Footer: phone, address, license placeholder only if verified.
## Photo strategy
Verified IDs. photo-1600607687939-ce8a6c25118c (finished interior), photo-1600566753190-17f0baa2a6c3 (modern exterior), photo-1600585154340-be6161a56a0c (home exterior), photo-1605276374104-dee2a0ed3cd6 (construction crew), photo-1494526585095-c41746248156 (house exterior). Verify subject match in browser before use.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 30 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/alcoa-construction"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=alcoa-construction --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://alcoa-construction.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://alcoa-construction.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://alcoa-construction.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://alcoa-construction.pages.dev | grep -c "(435) 879-9866"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://alcoa-construction.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://alcoa-construction.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://alcoa-construction.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/alcoa-construction/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 879-9866`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 30 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://alcoa-construction.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://alcoa-construction.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
22. Book Club Bistro
Vertical: Restaurant
Slug: book-club-bistro
Phone (CSV): (435) 288-3323
Address (CSV): Next to Skechers, 26A, 250 Red Cliffs Dr, St. George, UT 84790
Google rating (CSV): 4.9★ (164 reviews)
Live URL after deploy: https://book-club-bistro.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Book Club Bistro
- **Vertical:** Restaurant
- **Phone:** (435) 288-3323
- **Address:** Next to Skechers, 26A, 250 Red Cliffs Dr, St. George, UT 84790
- **Google rating:** 4.9★ (164 reviews)
- **Slug:** `book-club-bistro`
- **Live URL after deploy:** `https://book-club-bistro.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Book%20Club%20Bistro+St+George+UT`
Confirm phone matches CSV ((435) 288-3323). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "restaurant St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Find the restaurant on Yelp and DoorDash. Note hours, menu (if visible), and any photos of dishes.
- Check Google Maps photos to see what their actual interior and food looks like (informs photo direction without claiming the photos are theirs).
- Read 5 to 10 reviews. Note recurring praised dishes (don't quote anyone). The owner can confirm during onboarding.
- Check if they're on Instagram. If yes, link the handle in the footer placeholder.
6. **Save the research** to `apps/book-club-bistro/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for restaurant
Full-bleed food photography. A handwritten or hand-drawn accent script for menu category labels and specials. Warm grain texture overlay over hero photos. Dish names large, prices small. Navigation feels like a printed menu, not a SaaS landing page.
This is the most important creative direction. Lean in. The site should look like a restaurant site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Literary cafe. Off-white parchment #F4ECD8 background, deep forest green #2D4A2B accent, gold #C8A754 secondary. Cormorant Garamond display, Inter body. Sections divided by stylized chapter labels (Chapter I, Chapter II) instead of generic 01, 02. Photography of pastries, coffee, and a book on the table. The site should feel like a Penguin Classics paperback.
## Typography
See per-business twist for the cuisine-specific pairing. General direction: a strong serif or display sans for dish names + a clean humanist sans for body + a single hand-script accent (Caveat or Permanent Marker) used SPARINGLY on category labels.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
See per-business twist. Mexican leans deep red plus warm cream plus lime accent plus earthy clay. American cafe leans off-white parchment plus forest green plus gold plus bookcloth red. Healthy bowl leans sage plus cream plus white plus a small coral accent. Always warm and food-appropriate.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Generous but never flashy. Hero food photo has a subtle slow ken-burns (3 to 5 percent scale, 8 to 12 second loop). Below-fold sections use Reveal with 18px y-slide, no blur, 600ms. Menu cards lift on hover (TiltCard primitive, 6 degrees max rotation). Marquee scrolls at a calm 38 second loop.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Per cuisine: Mexican leans Hijos de Villa style cantina warmth crossed with editorial food magazine. American cafe leans Penguin Classics covers crossed with Boulder bookstore signage. Healthy bowl leans Sweetgreen-but-better, with full-bleed editorial food shots like Bon Appetit.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/book-club-bistro/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"book-club-bistro"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: short logo, Menu, About, Hours, click-to-call, Order CTA primary.
- Hero: a single appetizing close-up dish photo as a full-bleed background with a subtle ken-burns. Restaurant name on top in display type. One-line tagline naming the cuisine and city. Two CTAs: Order primary, Reservations or click-to-call outline. A small strip below shows hours and address. Hero must render visible on first paint (static).
- Marquee: scrolling kitchen-language band of dish keywords plus trust signals.
- Featured menu: 6 OR 8 cards in a uniform grid (3x2 or 4x2). Each card has a verified dish photo, a name, a one-line description, and a price. Use cuisine-appropriate generic dishes that the owner can edit.
- About the restaurant: two-column. Left column has the headline plus a short two-or-three-sentence story (family owned, from-scratch cooking, neighborhood feel). Right column has a single interior photo with a natural caption.
- Photo gallery: 6 to 9 verified food and interior shots in a clean masonry or grid layout.
- Hours and location: simple table for the week + a real Google Maps iframe at the real address.
- Order CTA: full-bleed band. Big click-to-call using the real phone, plus DoorDash and UberEats ghost buttons if applicable.
- Footer: hours, address, phone, social handles as placeholders.
## Photo strategy
Verified IDs by cuisine. Mexican: photo-1565299585323-38d6b0865b47 (tacos), photo-1599974579688-8dbdd335c77f (enchiladas), photo-1551504734-5ee1c4a1479b (salsa and chips), photo-1565958011703-44f9829ba187 (charro plate). American cafe: photo-1509440159596-0249088772ff (latte art), photo-1495474472287-4d71bcdd2085 (pastry case), photo-1525351484163-7529414344d8 (brunch plate). Healthy bowl: photo-1546069901-ba9599a7e63c (grain bowl), photo-1540420773420-3366772f4999 (greens). Verify each ID returns HTTP 200 with curl AND open in a browser to confirm the subject. NEVER use source.unsplash.com.
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 164 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/book-club-bistro"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=book-club-bistro --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://book-club-bistro.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://book-club-bistro.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://book-club-bistro.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://book-club-bistro.pages.dev | grep -c "(435) 288-3323"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://book-club-bistro.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://book-club-bistro.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://book-club-bistro.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/book-club-bistro/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 288-3323`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 164 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://book-club-bistro.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://book-club-bistro.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
23. C&S Plumbing
Vertical: Plumber
Slug: cs-plumbing
Phone (CSV): (435) 650-8439
Address (CSV): St. George, UT
Google rating (CSV): 4.9★ (29 reviews)
Live URL after deploy: https://cs-plumbing.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** C&S Plumbing
- **Vertical:** Plumber
- **Phone:** (435) 650-8439
- **Address:** St. George, UT
- **Google rating:** 4.9★ (29 reviews)
- **Slug:** `cs-plumbing`
- **Live URL after deploy:** `https://cs-plumbing.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=C%26S%20Plumbing+St+George+UT`
Confirm phone matches CSV ((435) 650-8439). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "plumber St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check Utah DOPL for the plumber license number.
- Note if 24/7 service is real.
- Check if they specialize in residential or commercial.
6. **Save the research** to `apps/cs-plumbing/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for plumber
Schematic pipe-diagram motif. A faint blueprint of pipework as a section background. Tradesperson photography, hands-on, real shop. A small wrench icon used as a list bullet.
This is the most important creative direction. Lean in. The site should look like a plumber site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Family-owned plumber. Add a one-line family-owned note under the hero trust strip.
## Typography
Display: Manrope (weight 700). Body: Inter (400 + 500). Accent: bold condensed sans on service names. Mono: JetBrains Mono.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: white #FAFAFA. Foreground: steel blue #3A5A7A. Secondary warm wood #A47551 (small accents). Accent red #C92E2E (emergency CTA only).
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Direct and reliable. Hero static. Below-fold Reveal with 18px y-slide, 500ms. Wrench-icon list bullets fade in with a 80ms stagger.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Tradeworks-style branding. The honest practicality of Klein Tools. Real shop signage from local plumbers in larger Utah cities.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/cs-plumbing/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"cs-plumbing"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Emergency, Contact, click-to-call, Free estimate CTA.
- Hero: tradesperson or pipework photo. Bold sans headline with the company name. One-line tagline naming Southern Utah. Emergency and click-to-call CTAs. Trust strip (licensed, 24/7 if true, family owned). Headline visible on first paint.
- Services: 6 OR 8 cards. Water heaters, drain cleaning, leak repair, repipe, fixtures, sewer line, garbage disposal.
- Emergency block: only if real.
- Service area chip list.
- Why us: 3 plain bullets. Licensed. Insured. Upfront pricing.
- Free estimate block.
- Footer with license number from Phase 1 research.
## Photo strategy
Verified IDs. photo-1585704032915-c3400ca199e7 (plumber hands), photo-1584622650111-993a426fbf0a (water heater), photo-1558618666-fcd25c85cd64 (modern faucet), photo-1581092334516-cc75c7a16c40 (pipe close-up).
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 29 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/cs-plumbing"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=cs-plumbing --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://cs-plumbing.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://cs-plumbing.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://cs-plumbing.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://cs-plumbing.pages.dev | grep -c "(435) 650-8439"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://cs-plumbing.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://cs-plumbing.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://cs-plumbing.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/cs-plumbing/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 650-8439`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 29 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://cs-plumbing.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://cs-plumbing.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
24. Prime Tire & Auto Repair LLC
Vertical: Auto repair shop
Slug: prime-tire
Phone (CSV): (435) 414-3883
Address (CSV): 297 W St George Blvd, St. George, UT 84770
Google rating (CSV): 4.9★ (66 reviews)
Live URL after deploy: https://prime-tire.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Prime Tire & Auto Repair LLC
- **Vertical:** Auto repair shop
- **Phone:** (435) 414-3883
- **Address:** 297 W St George Blvd, St. George, UT 84770
- **Google rating:** 4.9★ (66 reviews)
- **Slug:** `prime-tire`
- **Live URL after deploy:** `https://prime-tire.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Prime%20Tire%20%26%20Auto%20Repair%20LLC+St+George+UT`
Confirm phone matches CSV ((435) 414-3883). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "auto repair shop St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check ASE certification listing if available: https://www.ase.com/find-a-shop. Confirm ASE-certified status if claimed.
- Note brands they specialize in (some are domestic-focused, some import-focused, some are both).
- Read reviews for tone (some shops lean honest-mechanic, some lean technical-expert, some lean family-friendly).
6. **Save the research** to `apps/prime-tire/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for auto repair shop
Garage chalkboard plus mechanical schematic motif. Service prices written in a chalk-style accent font (used sparingly as labels). A schematic line-drawing of a car as a hero overlay or section divider. Authentic shop photography. The site feels like a working bay, not a corporate dealer site.
This is the most important creative direction. Lean in. The site should look like a auto repair shop site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Lead with tires. Tire services are the headline service, repair is secondary. Big tire photography in the hero. Add a tire-brand chip list (Michelin, Goodyear, BFGoodrich, Cooper, Toyo, Falken) below the brands-serviced row.
## Typography
Display: Bebas Neue (condensed bold). Body: Inter (weights 400 + 500). Accent: Permanent Marker or Special Elite (chalk-style, sparingly on price labels only). Mono: JetBrains Mono.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: near-black #0F0F0F. Foreground: cream #F4ECD8. Steel gray secondary: #3A3A3A. Bold red accent: #D9302E (CTAs). Amber secondary accent: #F4A623 (price labels). Concrete gray for textures: #9B9B9B.
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Bold but not gimmicky. Hero static. Below-fold Reveal with 20px y-slide, 600ms. Cards have a subtle wrench-icon hover state.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Singer Vehicle Design's website (premium automotive heritage). Iron and Resin's branding. The vintage shop signage of Highway 89.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/prime-tire/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"prime-tire"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Hours, Contact, click-to-call, Free estimate CTA.
- Hero: shop interior or under-the-hood photo. Bold display headline with the shop name. One-line tagline naming the city. Two CTAs (Free estimate primary, click-to-call outline). Trust strip with three pills (ASE-certified if real, family owned, warranty on all work). Headline visible on first paint.
- Services: 6 OR 8 cards. Oil change, brakes, transmission, A/C, diagnostics, tires, suspension, engine. Prime Tire variant: lead with tire services. Each card has a chalk-style price label in amber.
- Why us: 4 short bullets. ASE certified, family owned, X years in business, warranty on all work.
- Brands serviced: chip list. Toyota, Honda, Ford, Chevy, Subaru, Nissan, Dodge, Jeep, Ram, GMC.
- Hours and location: simple table plus map iframe.
- Free estimate block: click-to-call plus optional simple form.
- Footer.
## Photo strategy
Verified IDs. photo-1487754180451-c456f719a1fc (mechanic at work), photo-1632823469850-1b7b1e8b7f0c (engine bay), photo-1632823471565-1ec3a1e89a6f (shop interior wide), photo-1486006920555-c77dcf18193c (tools rack).
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.9★ on Google, 66 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/prime-tire"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.9★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=prime-tire --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://prime-tire.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://prime-tire.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://prime-tire.pages.dev | grep -c "4.9★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://prime-tire.pages.dev | grep -c "(435) 414-3883"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://prime-tire.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://prime-tire.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://prime-tire.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/prime-tire/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 414-3883`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.9★`, 66 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://prime-tire.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://prime-tire.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
25. Angel Nails & Spa
Vertical: Nail salon
Slug: angel-nails
Phone (CSV): (435) 674-5388
Address (CSV): 2628 Pioneer Rd, St. George, UT 84790
Google rating (CSV): 4.7★ (864 reviews)
Live URL after deploy: https://angel-nails.pages.dev
[BEGIN COPY-PASTE PROMPT]
# Mission
Build and deploy a high-quality cold-outreach demo website for the local business below. The pitch we'll use after the site is live: "I built you a draft site to show what we'd put together. Not finished, your own pictures and content would replace what I have, but it gives you the idea."
The business hasn't agreed to anything. This is a cold-outreach asset. It has to be:
1. **Honest.** No fabricated testimonials, fake reviews, made-up awards, or AI-tell language.
2. **Beautiful.** Visually distinctive for the vertical with a locked-in design system. Not a generic agency template with the colors swapped.
3. **Verified.** Every claim, every photo, every link tested before declaring done.
4. **Deployable.** Build clean, deploy clean, live URL responding HTTP 200, all sections render.
This is a 7-phase build. Work the phases in order. Don't skip verification gates.
# Business data (from CSV, treat as a starting point)
- **Name:** Angel Nails & Spa
- **Vertical:** Nail salon
- **Phone:** (435) 674-5388
- **Address:** 2628 Pioneer Rd, St. George, UT 84790
- **Google rating:** 4.7★ (864 reviews)
- **Slug:** `angel-nails`
- **Live URL after deploy:** `https://angel-nails.pages.dev`
- **Repo root:** `C:\Users\vulnix0x4\protondrive\My files\Projects\website-local-business`
# Phase 1: Research the business (do this BEFORE touching code)
The CSV is a scrape and might be stale. Verify against live public sources before you commit any data to the demo. Use WebFetch to load each source.
1. **Cross-check on Google.** Fetch:
`https://www.google.com/search?q=Angel%20Nails%20%26%20Spa+St+George+UT`
Confirm phone matches CSV ((435) 674-5388). Confirm address matches CSV. Note hours (the CSV does not have them).
2. **Look for an existing website.** Some "no website" leads in the CSV actually have a small Wix or Squarespace site. WebFetch any candidate URL you find. If they have a site, briefly note what it looks like (the demo we're building has to look obviously better, that's the pitch).
3. **Look at competitors.** Search "nail salon St George UT". Pick 2 or 3 competitors and WebFetch each. Note:
- What does the competition look like in this market?
- What's the visual quality bar?
- Where can our demo be obviously better?
4. **Read 5 to 10 Google reviews** for this business. Do NOT quote anyone. Note:
- What do customers actually like (informs which "Why us" reasons to lead with)?
- Is there a recurring complaint (avoid leaning into it on the demo)?
- What's the local tone (casual, formal, family-focused)?
5. **Vertical-specific research:**
- Check Instagram for actual nail-art photos (informs the gallery direction).
- Note the salon's price tier (look for prices in reviews or on Yelp).
- Note if they use Vagaro, Booksy, or Square for booking. Add the right ghost button.
6. **Save the research** to `apps/angel-nails/RESEARCH.md` with:
- Verified phone, address, hours
- Cross-check status: matches CSV / differs from CSV (note differences explicitly)
- Tone notes from reviews (no direct quotes, no review IDs)
- 2 or 3 competitor URLs with one-line takeaways
- Photo direction notes (what does their actual space look like?)
- Any vertical-specific notes (license number, certifications, brokerage, etc.)
If a source doesn't load, write "Couldn't reach [source], used CSV data only" in RESEARCH.md. That is honest. Do NOT invent data.
# Phase 2: Design lock (do this BEFORE writing components)
Lock in the design system before composing sections. Treat this as an art director's brief, not as suggestions.
## Visual signature for nail salon
Editorial fashion spread. Big magazine-style photography of nail art. A serif display headline above each section in the style of Vogue or T Magazine. Clean grid for the gallery. Nail studio aesthetic, not strip-mall.
This is the most important creative direction. Lean in. The site should look like a nail salon site at first glance, not a generic agency template with the colors swapped.
## Specific to this business
Nail salon vertical with a small spa-services overlay. Add a short pedicure-spa block under services. Differentiate from typical strip-mall nail salons with editorial photography.
## Typography
Display: Italiana or Bodoni Moda (weight 400, large). Body: Inter (400 + 500). Mono: JetBrains Mono. Display tracked tight (-0.04em) on hero name.
Update `app/globals.css` to load these fonts via Google Fonts and assign them to the `--font-display` / `--font-sans` / `--font-mono` CSS variables. Update `app/layout.tsx` to add the Google Fonts `<link>` in the `<head>`.
## Color palette
Background: cream #FAF1E6. Foreground: deep ink #1F1A18. Primary rose-gold #D4A0A0. Secondary forest green #2D4A2E or burgundy #722F37 (pick one based on the salon's existing brand colors from Google).
Update `app/globals.css` color tokens. Keep the design discipline tight. Two or three colors do most of the work. The accent is reserved for primary CTAs and highlights only.
## Motion
Editorial calm. Hero static. Below-fold Reveal with 14px y-slide, 500ms. Gallery has a hover lift on each tile.
Don't overdo it. Motion should feel premium, not flashy. The first rule of motion on a marketing site: nothing on the hero animates in from opacity-0. Render hero content static.
## Inspirations
Vacation's nail salon branding. Paintbox's website. Modern nail-studio Instagram aesthetic.
These are reference points for the design quality bar. The site should sit in this neighborhood.
# Phase 3: Build the site
## Setup
1. Duplicate `apps/mixed-greens/` to `apps/angel-nails/`. Skip `node_modules/`, `.next/`, and `out/` (regenerated on build).
2. Update `package.json` `name` field to `"angel-nails"`.
3. Update `app/layout.tsx` metadata: title (no em dashes), description, OG image alt. Add the Google Fonts link from Phase 2.
4. Replace `lib/menu.ts` (or rename to `lib/business.ts`) with this business's data, sourced from your Phase 1 research. Use the verified phone, address, hours, and rating.
5. Update `app/globals.css` with the typography and color tokens from Phase 2.
6. Reference `apps/agency/components/primitives/` for the design system primitives:
- `Reveal.tsx`, `RevealGroup.tsx`, `WordsReveal.tsx` (scroll reveals, never on the hero)
- `ChapterHeader.tsx` (numbered section labels)
- `Bars.tsx` (3-stacked-bars motif)
- `Datasheet.tsx` (spec-sheet style data grid)
- `MagneticButton.tsx` (cursor-attraction on primary CTA only)
- `TiltCard.tsx` (3D tilt on hover for cards)
- `ScrollProgress.tsx` (top-of-page progress bar)
- `CursorHalo.tsx` (soft glow that follows cursor)
- `Marquee.tsx` (kinetic ticker)
Bring them in if they fit the vertical. A law firm probably doesn't want CursorHalo. A salon probably does. Use judgment.
## Sections
- Nav: logo, Services, Gallery, Book CTA, click-to-call.
- Hero: tasteful nail-art close-up or salon interior. Italiana display name. One-line tagline naming the city. Book CTA, click-to-call. Headline visible on first paint.
- Services and pricing: 4 OR 6 cards with service name and price. Manicure, pedicure, gel, acrylic, nail art, combos.
- Gallery: clean 3x3 grid of 9 nail art photos. Verified Unsplash IDs only.
- Book block: click-to-call plus Vagaro or Square or Booksy placeholder ghost button.
- Hours and location.
- Footer.
## Photo strategy
Verified IDs. photo-1604654894610-df63bc536371 (manicure close-up), photo-1607779097040-26e80aa78e66 (nail art), photo-1610992015734-2c4cdfad79d9 (salon interior modern), photo-1632345031435-8727f6897d53 (polish bottles).
**Photo verification gate**: before committing any Unsplash URL, run this loop for each ID:
```bash
curl -I "https://images.unsplash.com/photo-XXXXX?auto=format&fit=crop&w=1600&q=80"
```
Should return `HTTP/2 200`. Then open the URL in a browser tab and confirm the photo's actual subject matches the section. A 200 response from Unsplash does NOT mean the image is the right subject. We have had cards labeled "Real estate" return a guy in a t-shirt because the random query format hit an unrelated photo.
Reject any photo that doesn't match the section. Try the next ID in the curated list, or pick a different one and verify it the same way. Document every swap in your final report.
## Style mandates (these prevent the AI-tell pattern)
- **No em dashes anywhere on the rendered site.** Not in headlines, not in body, not in captions, not in pull quotes. Use periods, commas, or "and". The em dash is the #1 giveaway that copy was AI-generated.
- **No template-meta phrases visible to the reader.** Don't write "(Sample, replace with real focus areas)" or "Stock photo, your real photo goes here once we shoot the space" or "Hours placeholder, confirm before launch" anywhere on the rendered page. If something is generic, write it like the owner wrote it themselves. The only place to mark a placeholder is a small JSX comment for yourself: `{/* TODO: real bio from owner */}`.
- **No mention of photo shoots or scheduling photographer.** If a photo is generic, don't call attention to it. Caption it as if it were already theirs ("Inside the office", "On the road in Southern Utah").
- **No AI-text tells.** Banned phrases: "we pride ourselves", "delivering excellence", "leveraging", "ensuring", "navigate the complexities of", "your trusted partner", "elevate your experience", "seamless", "crafted with care", "your one-stop shop", "best-in-class", "industry-leading", "passionate about". Write like the local business owner. Short sentences. Specific nouns. No marketing inflation.
Bad: "We pride ourselves on delivering excellence in roofing solutions for discerning Southern Utah homeowners."
Good: "We replace roofs in St. George. Same crew on every job."
- **No tilde-prefix numbers.** Write "30 years" or "since 1995", not "~30 years".
- **No vague time hedges.** "For decades" is fine if true. "Nearly three decades" is hedging. "30 years" is direct.
## Layout safety (these prevent recurring bugs)
- **The col-span trap.** This template uses 12-column grids in many sections. If you wrap a right-column block in `<Reveal>`, the Reveal MUST carry the col-span class. `<Reveal className="md:col-span-7">`, not just `<Reveal>`. Forgetting this collapses the column to a 1-word-per-line vertical strip on desktop. Check every section.
- **Hero must paint readable on first render.** Do NOT wrap hero content in `whileInView` scroll-triggered Reveals. The hero is already in the viewport on page load, and framer-motion's intersection observer can race with hydration, leaving the hero blank at opacity 0. Render the hero badge, headline, paragraph, buttons, and any side card as static JSX. Save the Reveal animations for sections below the fold.
- **Card grids must fill rows.** 4 cards = 2x2 or 1x4. 6 cards = 2x3 or 3x2. 8 cards = 2x4 or 4x2. Never leave one orphan card alone on a last row with empty space next to it. If you have 7 services, drop to 6 or expand to 8. If you have 5, drop to 4 or expand to 6.
- **No huge whitespace gaps between sections.** Aim for `py-24 md:py-32` as the default rhythm.
## Honesty constraints (these matter for the cold pitch to work)
Do NOT fabricate:
- Fake testimonials. Fake review quotes attributed to named people.
- Specific Lighthouse scores or load-time numbers in marketing copy.
- Awards, certifications, business-history facts you couldn't verify.
- Specific menu items, service prices, hours, or insurance accepted as if they were the business's actual data.
DO use:
- The business's real name, real phone, real address (verified in Phase 1).
- Stock photos that match the section subject. Don't call them stock photos on the page.
- Generic-but-realistic copy that sounds like the owner wrote it.
- The Google rating badge (`4.7★ on Google, 864 reviews`). This is verifiable public data.
- Real public hours if you found them in Phase 1. Otherwise, use natural-sounding generic hours and leave a JSX comment.
# Phase 4: Local verify (before deploying)
Run a clean static export and confirm the build is healthy.
```bash
cd "C:/Users/vulnix0x4/protondrive/My files/Projects/website-local-business/apps/angel-nails"
rm -rf .next out
npm run build
```
Required outcomes:
- Exit code 0
- Zero TypeScript errors
- Zero "missing alt" or "broken image" warnings
- First Load JS under 200kB on the homepage
- 5 static pages generated (or whatever the homepage count is)
Then start a local preview to spot-check:
```bash
npx serve out -p 4500 &
```
Curl the homepage and grep for the rating badge to confirm hero rendered:
```bash
curl -s http://localhost:4500/ | grep -c "4.7★"
```
Expected: 1 or more. If 0, the hero didn't render and you have a layout issue to fix before going further.
Stop the preview when done.
# Phase 5: Deploy
```bash
wrangler pages deploy out --project-name=angel-nails --branch=main --commit-dirty=true
```
The Cloudflare Pages project gets created on first deploy. Note the deployment-specific URL Cloudflare returns AND the canonical URL `https://angel-nails.pages.dev`.
# Phase 6: Live verify (do not skip)
Don't trust the deploy logs alone. Verify the live site responds.
1. **HTTP check:**
```bash
curl -sI https://angel-nails.pages.dev | head -3
```
Expected: `HTTP/2 200`. If 404 or 5xx, redeploy and investigate.
2. **Content check:**
```bash
curl -s https://angel-nails.pages.dev | grep -c "4.7★"
```
Expected: 1 or more (the rating badge renders in HTML).
3. **Phone presence check:**
```bash
curl -s https://angel-nails.pages.dev | grep -c "(435) 674-5388"
```
Expected: 2 or more (phone shows in nav, hero, and footer at minimum).
4. **No-AI-tell scan:**
```bash
curl -s https://angel-nails.pages.dev | grep -iE "we pride ourselves|delivering excellence|leveraging|seamless|navigate the complexities|crafted with care|elevate your"
```
Expected: empty output. If anything matches, rewrite the offending copy and redeploy.
5. **Em-dash scan:**
```bash
curl -s https://angel-nails.pages.dev | grep -c "—"
```
Expected: 0. If non-zero, find and replace.
6. **Visual walkthrough.** Open `https://angel-nails.pages.dev` in a browser. Walk every section top to bottom. Confirm:
- Hero paints visible on first frame (no opacity-0 stuck headline)
- All photos load (no broken-image icons in devtools network tab)
- Mobile layout works at 375px viewport (use devtools responsive mode)
- All click-to-call links use `tel:` and the real phone (right-click each one to inspect href)
- All anchor links scroll to the right section
- Copy reads natural, no AI-tell phrases slipped through
7. **Image-load check.** In devtools network tab, reload and filter to "img". Confirm zero 404s on Unsplash photos. If any 404, swap the ID and redeploy.
8. **Lighthouse spot-check** (optional but recommended). Open Chrome devtools, run Lighthouse on Performance, Accessibility, Best Practices, SEO. Note the scores in your report. Aim for 85+ on all four. The site shouldn't ship at less than 70 on Accessibility.
# Phase 7: Pre-flight checklist
Answer YES to every item before declaring done. If any answer is NO, fix it before reporting back.
- [ ] Phase 1 RESEARCH.md exists at `apps/angel-nails/RESEARCH.md` with verified data
- [ ] Phase 1 cross-check: phone, address, rating all match Google (or note differences)
- [ ] Phase 2 typography fonts loaded in layout.tsx and globals.css
- [ ] Phase 2 color palette applied to globals.css color tokens
- [ ] Hero paints visible on first paint (no opacity-0 stuck content, no Reveal wrappers on hero)
- [ ] Zero em dashes on the rendered site (verified via grep on the live URL)
- [ ] Zero "Sample, replace with..." or template-meta copy
- [ ] Zero photo-shoot language
- [ ] Zero banned AI phrases (verified via grep on the live URL)
- [ ] Zero tilde-prefix numbers
- [ ] All Unsplash photos return HTTP 200 AND match the section subject
- [ ] No orphan cards on grid rows
- [ ] All <Reveal> in 12-col grids carry md:col-span-X
- [ ] Mobile layout works at 375px
- [ ] All click-to-call links use the real phone (`(435) 674-5388`)
- [ ] All addresses use the real address from Phase 1
- [ ] Google rating badge uses the real rating + review count (`4.7★`, 864 reviews)
- [ ] Footer disclaimers correct for the vertical
- [ ] Build size under 200kB First Load JS
- [ ] HTTP 200 from `curl -sI https://angel-nails.pages.dev`
- [ ] Visually walked every section in a desktop browser
- [ ] Visually walked every section in a 375px mobile viewport
- [ ] Lighthouse Accessibility 70+ (90+ ideal)
# Report back
When done, post a final report with:
1. **Live URL.** `https://angel-nails.pages.dev` plus the deployment-specific URL Cloudflare returned.
2. **Build stats.** Exit code, First Load JS size, page count.
3. **Phase 1 research summary.** 3 to 5 bullets from RESEARCH.md (verified data, competitor takeaways, tone notes).
4. **Photo swaps.** Any Unsplash IDs you replaced because they returned the wrong subject. Include the rejected ID and the replacement ID.
5. **Layout fixes.** Any col-span / orphan-card / hero-paint issues you caught and fixed during build.
6. **AI-tell catches.** Any banned phrases you noticed in your first draft and rewrote (good signal that the discipline is working).
7. **Decisions for the owner.** Anything you faked (hours, insurance, services, brand list) that the owner needs to confirm or replace before launch. Be specific.
8. **Lighthouse scores** if you ran them.
9. **Pre-flight checklist.** Confirm every item passed.
Don't declare done until the checklist passes. If any item is NO, fix it and re-verify.
[END COPY-PASTE PROMPT]
Generator script
These prompts are generated by scripts/build-cold-outreach-prompts.cjs from the same source CSV as the outreach list. To regenerate after a fresh scrape:
node scripts/build-cold-outreach-prompts.cjs
That writes to business-kit/24-cold-outreach-prompts.md and apps/playbook/content/25-cold-outreach-prompts.md (this file).