Skip to content
Submit Project Request
All Work
Client Engagement

A real engagement, documented by the team that engineered it. The client is not named, and nothing identifying or confidential appears.

Built to carry proof

A Fraser Valley hardscape contractor wins work on craftsmanship — so the site had to carry photographic proof at local granularity without getting slow. How we engineered roughly three hundred statically generated pages, an 89-frame hero inside a 2.7 MB budget, and a quote pathway that lands in the CRM.

Landscape construction·March – June 2026·6 min read
High-Converting WebsitesAutomated WorkflowsNext.js 16React 19TypeScriptTailwind v4AVIFVercel

01 Context

A hardscape and landscape contractor working across the Fraser Valley and Lower Mainland wins jobs the way every good trades business does: the last project sells the next one. Retaining walls, paver patios, driveways, drainage — the evidence is photographic, and the buying decision is local. A homeowner searches for a specific service in a specific municipality, and compares whoever shows up on the strength of their finished work.

The engagement began in March 2026 with a six-page single-page-application build — a fast way to get a presentable site standing — and finished in June as something structurally different: a statically generated system of just under three hundred pages, every URL derived from typed data files, with the operator's project photography and review history doing the persuading. The interesting part is not that a contractor got a website — it is what a website has to be when photographic proof is the product and the market is won one municipality at a time.

02 The Constraint

Three facts shaped everything.

Proof is heavy. The conversion asset is photography of real, finished builds — and image-heavy pages are exactly the pages that get slow. The visitor most worth converting is standing in their backyard on a phone. A site that makes them wait for the pictures has already argued against the craftsmanship it is trying to demonstrate.

The market is hyper-local, and local content is usually fake. Search demand arrives as service-plus-place queries, which is why contractors end up with per-town pages. The standard way to build them is a template with the town name swapped in — content that readers discount instantly and search engines increasingly treat the same way. The client's actual advantage is genuine local knowledge: how soil behaviour, drainage patterns, and municipal permit thresholds differ across their service area. The pages had to carry that knowledge or not exist.

The quote request is the only conversion, and it cannot land in an inbox. A trades operator is on a site all day — a job site — and a submission that becomes an unread email is a lost job. The pathway had to terminate in the client's CRM, where follow-up automation runs without anyone remembering to check.

The engineering problem underneath all three: serve heavy visual proof fast, at local granularity, honestly — on a system a small trades business never has to hand-maintain.

03 The System Engineered

Content as typed data, routes as a consequence. Twenty services and eleven municipalities live in TypeScript data files with strict interfaces — service copy, process steps, material systems, FAQs on one side; per-municipality soil conditions, climate notes, permit thresholds, and neighbourhood lists on the other. Every App Router route is generated from these files with dynamic params disabled — an unknown slug is a 404 by construction — and adding a service or municipality is a data edit that propagates to routes, sitemap, and AI-crawler index on the next build. Nothing on the site is a page someone has to remember to update in four places.

220 combination pages with no template-swap padding. The service-times-area pages — the long-tail pages that answer service-plus-place queries — are produced by a pure, deterministic generator that composes the service data with the municipality data. No randomness, no LLM calls, no synonym-shuffling to fake variety. The variation across all 220 pages comes entirely from the source data being genuinely different: a retaining wall page for a hillside municipality talks about glacial till and the wall height at which an engineer's stamp becomes mandatory, because that is what its data file records. We rejected AI-generated localization outright — the reason most contractor sites read like nobody local wrote them. If a municipality's entry had nothing real to say, the honest fix was research, not prose-padding.

An 89-frame hero inside a hard byte budget. The desktop homepage opens on a scroll-driven canvas sequence of the client's own project work — 89 frames scrubbed in lockstep with the scrollbar. The reputation of the technique is bloat, so the budget came first: the full set had to fit under 2.7 MB. A sharp-based pipeline re-encodes the frames from WebP to AVIF at quality 50, effort 6 — 36% smaller with no perceptible loss — landing the whole sequence at 2.40 MB with the largest frame at 29.4 KB and the first frame, the LCP image, near 24 KB. The runtime is engineered with equal suspicion of jank: scroll-driven updates are direct DOM writes with zero React re-renders, the scroll handler is pure arithmetic against cached layout measurements so it never forces a synchronous layout, a lerped requestAnimationFrame loop gives fast scrolls a ~150 ms glide instead of a snap, and an IntersectionObserver short-circuits all of it the moment the hero leaves the viewport. Frames ship with immutable cache headers; a repeat visit pays nothing.

Mobile is a different product, not a scaled-down one. Under 768px the canvas machinery does not load at all — the phone gets a static single-frame hero behind a frosted-glass panel, one image in AVIF with a WebP fallback. Visitors with reduced motion enabled get the same static treatment regardless of device. The rule: nobody pays for an animation they will not see or did not ask for.

Proof the site does not author. Ratings and reviews are pulled server-side from Google's Places and Business Profile APIs and cached with incremental revalidation on six- and twenty-four-hour windows — third-party proof, served at static-page cost. The rating badge renders only when the integration is configured; every gated feature degrades this way, and the site runs with zero environment variables — the property that makes it safe for a business without a web team.

A quote pathway that ends in the CRM. The contact form posts to a serverless handler that forwards straight into the client's CRM via an inbound webhook, where contact creation and follow-up workflows fire automatically. Abuse control is sized honestly for an SMB lead form — a CSS-hidden honeypot field and a modest in-memory rate limit — and if the webhook is unconfigured the form returns a graceful failure with a call-us fallback rather than pretending to succeed.

Migration under discipline. Mid-engagement, the site was rebuilt from the initial SPA onto Next.js in twelve phases, each landing as an atomic commit, with the old stack kept in-tree as rollback insurance and a DNS cutover runbook specifying TTL reduction beforehand and a 48-hour fallback window after. Structured data — organization, local business, service, FAQ, and breadcrumb JSON-LD — plus a generated llms.txt pair and a robots policy that explicitly admits the major AI crawlers round out the retrieval surface, fed from the same data files as everything else.

04 What Changed

What shipped is a statically generated site of just under three hundred URLs on Vercel's edge, carrying the client's photographic proof at a payload most sites spend on a JavaScript framework: the entire 89-frame hero weighs 2.40 MB, less than a single unoptimized photo, and the page's first image is about 24 KB. Local pages exist for every service in every municipality served, built from recorded local fact rather than swapped town names, and every quote request lands as a CRM contact with automation already running.

Structurally, the site is built to be grown by editing data, not pages. A new municipality, a new service line, a new article cluster — each is an addition to a typed file that the routes, sitemap, and crawler indexes pick up on the next build. As the business extends its service area, the system that carries its proof is built to extend with it, at the same standard.

Details that would identify the client have been withheld; every technical claim above is observable in the build.

BUILD YOURS

You've seen how we build.Now point it at your business.

Submit a project request. We'll bring the same engineering discipline to your highest-leverage system — and document it the same way.

Submit Project Request