![]()
Who
I get hired when a contractor's site still works for referrals and dies for everyone else: plugins rotting, forms flaky, hosting bill arguing with the phone.
Kings Roofing already had a personality: orange #FF7620, leaping lion, metal-roof hero, color pickers, carport kits, Waynesville-to-Highlands location pages. Redesigning that into a generic "modern roofing" template would have trained half of Haywood County that the company changed crews.
This write-up is for operators who will keep the weird brand orange on purpose, and for WNC folks who just need the site to load when they search the truck wrap.
What
Public repo Hustle-Launch/kingsroofingnc.com. Package 0.1.0, Bun, Next.js 16.1.6, React 19, Tailwind 4.
Stack on HEAD: Resend for quote mail, PostHog, Sentry (withSentryConfig + CSP/HSTS/frame DENY), Phosphor via react-icons, Biome/Oxlint/tsgo local gates. No Stripe on main. A local branch has quote-fee experiments that never reached HEAD, so I am not narrating them as shipped.
![]()
What actually shipped:
- Pixel-faithful homepage: Residential & Commercial hero, Free Quote / Call box, New Roof Installation with YouTube embed, Re-Roofing orange band, Roof Repair checklist, four location photo cards, "Roofers in Asheville NC" closer.
- App Router pages matching the old WordPress menu: About, Residential, Commercial, Contact, Roofing Color Pickers (metal + shingles), Metal Structures (carport kits + pole truss kits + style detail pages).
- Location SEO under
/residential/[location]for Asheville, Cashiers, Highlands, Waynesville. Constants consolidated so phone numbers do not drift. - Contact + feedback flows: Resend from
notify@uncap.ustokingshaywood@gmail.com, HTML escaped in templates, interactive star rating + loading skeleton from launch week. - Ops: Vercel prebuilt / Blacksmith path, git auto-deploy off on main, Aug 8
X-Robots-Tag: index, follow.
Honesty: sitemap still lists legacy /waynesville style URLs while the app moved under /residential/.... Custom domain kingsroofingnc.com returns Cloudflare 526 from pack hosts. The working surface is the Vercel alias.
![]()
Where
Working product: kingsroofingnccom.vercel.app. Intended apex kingsroofingnc.com is DNS/SSL-incomplete at draft time.
Code: Hustle-Launch (public; michaelmonetized mirror shares HEAD 984746b). Host Vercel. Business phones in constants: 828-246-2193 / 828-279-6896. Service area string spans Asheville through Weaverville.
![]()
When
2026-02-12. One long day. Create Next App to WP migration scaffold to Layout/Providers to exact copy to full sitemap pages to move locations under /residential/[location] to dropdowns for locations / metal structures / color pickers to white/orange restyle to lion + dark footer to lock Roboto/Poppins/#FF7620 to YouTube to "match WordPress exactly" commits. That afternoon is the product.
2026-02-15. Escape user input in Resend HTML so quote mail is not an XSS souvenir.
2026-02-21. Launch-week hygiene: README that is not boilerplate, LOCATIONS single source, star rating + skeleton, Phosphor icons, ContactCTA extract, carport/pole-truss content fleshed out, phone consolidation + rel=noopener.
2026-02-27–28. Build gate, drop GitHub Actions (Vercel is CI), P1 fixes, security headers folded into next.config.ts.
2026-05. shipprep / Blacksmith observability dance: install, revert, re-apply.
2026-08-08. HEAD 984746b. Robots index/follow on Vercel. Thirty-two commits on the clock.
Why
Referral businesses do not buy your taste. They buy continuity.
I kept the orange, the lion, the color pickers, and the metal-structure tree because those were already the marketing system. Next.js, Resend, Sentry, and CSP are the parts that were rotting under WordPress, not the brand.
When you migrate a referral-driven local business off WordPress, do you keep the weird brand orange, or do you "modernize" it until nobody recognizes the truck wrap?