Skip to content
Back to Work
Local BusinessTrilone Electric

Trilone Electric

A full-stack marketing site for a licensed NJ electrical contractor, with a headless CMS, contact form, and SEO.

View Live Site
trilone-electric-homepage

Trilone Electric: Full-Stack Site and CMS — Planned and Built with AI

A licensed NJ electrical contractor needed a modern, editable marketing site. I used AI to design a detailed plan first, then implemented it end-to-end.

Problem and context

Trilone Electric is a licensed electrical contractor serving industrial, commercial, and residential clients in New Jersey. They needed a professional web presence that could be updated without touching code: homepage, services, about, contact, and legal pages, plus a contact form and strong SEO. The project had to feel reliable and maintainable—something a real client could run long-term. I treated that as a product problem: define the scope and content model up front, then build to the spec.

Research and discovery

Before planning with AI, I locked in the stack and high-level requirements. I evaluated Next.js (App Router) against other frameworks and chose Next.js 16 for its server components, routing, and deployment story. For the CMS I wanted something type-safe and co-located with the app: Payload CMS 3 fit—TypeScript-native, schema-driven, and deployable on Vercel alongside the frontend. I added PostgreSQL for the database, Tailwind for styling, and Vercel Blob for media so the client could upload images without managing a separate asset pipeline. I also looked at how similar contractor sites structured their content (hero, services grid, testimonials, trust bars) so the plan could reflect patterns users expect.

How I used AI to create a detailed plan

I used AI (Cursor) to turn the problem into a structured, step-by-step plan before writing any application code. That plan became the single source of truth for what to build.

Information architecture. The plan spelled out the sitemap: Home, Services (list + detail pages by slug), About, Contact, and Legal (dynamic pages by slug). It also listed every content type: hero (headline, CTAs, trust bar, background), services (with icons, categories, featured flag), testimonials, team members, company stats, and legal pages with rich text.

CMS design. I had the AI break down Payload into globals vs collections. Globals: homepage (tabs for Hero, Services section, About snippet, CTA), about page, site settings (nav, footer, contact info, default SEO), and page copy (hero and section labels for Services, About, Contact). Collections: media, users (with an approval flow so only approved users could log in), services, testimonials, team-members, company-stats, legal-pages (Lexical rich text), and contact-submissions (read-only in admin). That split made it clear what was "site-wide" vs "many items," and the approval flow was in the plan from the start.

Data flow and APIs. The plan specified that the frontend would be server-rendered and pull data via a single query layer (e.g. payload-queries.ts) from Payload. It also spelled out the contact flow: validate with Zod, verify reCAPTCHA, persist to the contact-submissions collection, send a notification email via Resend, and optionally log IP for audit. A revalidation API route for on-demand cache invalidation was included so the site could stay in sync after CMS publishes.

SEO and performance. The plan called out a dynamic sitemap (static routes plus service slugs from the CMS), robots configuration, per-page meta (and Payload's SEO plugin where it made sense), JSON-LD for the homepage (e.g. ElectricalContractor schema), and an edge-generated Open Graph image. Optional analytics (e.g. Vercel) was noted as a one-line add.

I iterated on this with the AI until it read like an implementable checklist: sections for "Frontend pages," "Payload schema," "API routes," and "Environment variables." Having that plan meant fewer surprises mid-build, a clear line between "what to build" and "how to build," and a way to estimate and hand off or revisit the project later.

Build: from plan to implementation

I started with the Payload config and seed data so the CMS and types were real from day one. Then I built the query layer (payload-queries.ts) and the homepage—hero, featured services, about snippet, stats, testimonials carousel, and CTA—all driven by globals and collections. Next came the services listing and detail pages (/services, /services/[slug]), the about page (company story, mission, vision, team, certifications), and the contact page with the form. After that I added legal pages (/legal/[slug]), the contact API (Zod, reCAPTCHA, Payload create, Resend), and the revalidation route. Finally I wired up the sitemap, robots, OG image, and JSON-LD and polished the UI (Framer Motion, responsive layout, mobile nav).

Payload. A single config file defines four globals (homepage, about, site, page-copy) and eight collections, including media (Vercel Blob), users (auth + approval checkbox), and contact-submissions. The Payload SEO plugin handles meta for services and legal pages; Live Preview is configured for the homepage, about, page-copy, and services with breakpoints. A custom "Request access" link in the admin points to a public registration page; new users stay blocked until an admin checks "approved."

Frontend. Marketing pages are server components that call the query layer. Reusable sections (Hero, ServiceGrid, FeaturedServices, TestimonialsCarousel, etc.) receive typed data. The hero and other preview-aware sections use Payload's live-preview hooks so editors see changes without a full refresh. Fallbacks in the query layer return sensible defaults when the CMS is unavailable (e.g. during a static build), so the site still renders.

Contact. The /api/contact route parses the body, verifies reCAPTCHA, validates with Zod, creates a document in contact-submissions, and sends an HTML email via Resend. The form is built with React Hook Form and the same Zod schema, with clear success and error states.

Refinements. Two changes happened during build: hero background moved from a legacy URL field to a proper media upload in the homepage global, and the user approval flow was enforced in a beforeLogin hook so unapproved users see a clear message instead of being able to log in. Both came from implementing the plan and adjusting when the behavior didn't match the goal.

Results and takeaways

The client got a live marketing site with a full CMS: they can edit the hero, services, testimonials, team, company stats, and legal pages without code. Contact form submissions are stored in the admin and emailed; the site has a sitemap, OG image, per-page meta, and JSON-LD for search. The stack is type-safe end-to-end (TypeScript and generated Payload types), and the codebase has seed and create-admin scripts so the project can be spun up or handed off cleanly.

Takeaways:

• Plan first. Using AI to produce a structured, sectioned plan before coding kept the project on track and made the implementation phase predictable and iterative

• Single source of truth. The plan acted as a living spec: when I wasn't sure what to build next, I referred back to it instead of ad-libbing.

• Refine as you build. The plan didn't need to be perfect—moving the hero to media upload and tightening user approval were small, informed tweaks that improved the outcome without throwing away the plan.

Tech stack

Frontend: Next.js 16, React 19, Tailwind CSS 4, Framer Motion

CMS & data: Payload CMS 3, PostgreSQL, Vercel Blob (media)

Integrations: Resend (email), reCAPTCHA, Vercel Analytics (optional)

Tooling: TypeScript, Zod, React Hook Form, Lexical (rich text in Payload)

Process overview

Discovery (Requirements, Stack research) → Planning with AI (Structured plan, Content model, APIs and SEO) → Build (Payload and queries, Pages and forms, SEO and polish) → Outcome (Live site and CMS)