/library / template-vertical-hvac-site
templateVertical (industry)

HVAC contractor website (lead form, service area, reviews, call tracking)

A vertical-specific marketing site for an HVAC contractor. CallRail-style number, lead form to Resend/Twilio, service-area map with city pages, real-photo gallery, Google reviews embed. Built for the exact audience trades owners need to convert.

use whenYou're building a website for an HVAC, plumbing, roofing, or similar trades client. The CLAUDE.md captures the specific decisions and gotchas of this vertical so Claude doesn't drift toward generic SaaS aesthetics.

May 8, 20262,310 bytestradeshvaccontractorlead-formlocal-seo

[Contractor Name] · HVAC site

A trades marketing site. Built to convert homeowners with a leak, not to win a design award. Phone above the fold, service area visible, real photos, named technicians.

Source of truth

Vercel deploys from main. Content (services, service areas, gallery photos) lives in MDX in the repo for v0. Move to Sanity when the client wants to edit themselves.

Tech stack

Next.js 15 (App Router) + React + Tailwind v4. CallRail for the tracking phone number on the site. Resend API for the apply/quote form (emails + SMS to the owner). Cloudinary for real-photo galleries. Sanity (later) for content. Vercel hosting.

Deploy

git push origin main. Vercel auto-deploys. Phone number from CallRail is environment variable; swap when CallRail changes.

File map

  • app/page.tsx home: hero with phone, services snapshot, service-area map, recent jobs, reviews
  • app/services/[service]/page.tsx per-service pages (/services/ac-repair, /services/heat-pump-install)
  • app/service-area/[city]/page.tsx per-city landing pages for local SEO
  • app/quote/page.tsx lead form
  • app/api/quote/route.ts POST -> Resend email + Twilio SMS to owner
  • content/services.ts services list (price ranges, descriptions, FAQ)
  • content/service-area.ts cities served (zip codes, drive times)
  • content/gallery.ts real job photos (before/after pairs)
  • components/PhoneCTA.tsx sticky phone CTA, mobile-prominent

.env keys

  • NEXT_PUBLIC_PHONE CallRail tracking number (formatted (555) 555-1234)
  • NEXT_PUBLIC_PHONE_TEL raw E.164 (+15555551234) for tel: links
  • RESEND_API_KEY
  • RESEND_NOTIFY_EMAIL owner's inbox
  • TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER, TWILIO_NOTIFY_NUMBER (SMS alerts)
  • CALLRAIL_FORM_TRACKING_ID (binds web leads to CallRail)
  • GOOGLE_REVIEWS_PLACE_ID for the reviews embed

Hard rules

  • Phone number is above the fold on every page. Click-to-call on mobile is the primary CTA.
  • License + insurance numbers visible in the footer. Trade audiences look for these.
  • Photos are REAL (the team, the trucks, actual jobs). No stock photos of "diverse team in hard hats" -- audience instantly distrusts.
  • No em-dashes anywhere (Pangram flags them; owner WILL notice if his copy has them).
  • Service-area pages are real local SEO pages: city name in H1, neighborhoods listed, distinct testimonial per city. Not duplicate content.
  • Lead form notifies via BOTH email AND SMS. Owner is on a roof, not at a desk.
  • Submit must be smoke-tested with real Resend + Twilio before launch. Lost leads = lost revenue.

Recent significant changes

  • 2026-05-08: Scaffolded. Locked: phone-first design (homeowner mid-leak is not browsing), per-city pages for local SEO, real photos only, dual email + SMS alerts.

Next session: start here

  1. Buy CallRail tracking number, set in .env.
  2. Verify Resend domain. Verify Twilio messaging service.
  3. Populate content/services.ts and content/service-area.ts with the client's actual scope.
  4. Get 30-50 real job photos from the client. Compress + upload to Cloudinary.
  5. Submit a real test lead. Confirm email AND SMS arrive within 30 seconds.
  6. Run apex-seo before DNS attach.

Get the next CLAUDE.md in your inbox.

One new template every week, plus occasional case studies.