CMC Lawns
A speculative rebuild for a Perth lawn-care business where every word traces back to the owner and every unknown stays visibly blank.
Overview
An unaffiliated rebuild of cmclawns.com.au, built as a pitch after auditing the live Wix site on 10 August 2026. The owner did not commission it and has not paid for it. Six pages cover the program, the services, the before-and-after work, the operator and the quote form. The rule the whole build runs on is that nothing is invented: every line of copy sits in one data file tagged as the owner’s own words, a placeholder the owner still has to supply, or a claim carried across from the old site but never independently checked. Placeholders render visibly on the page instead of quietly reading as fact, so no price, date, ABN or review count appears that nobody has verified, and there are no testimonials because none could be sourced. Four measures stop it being mistaken for the real site or competing with it in search: a permanent banner above the masthead, a robots meta tag, a blocking robots.txt and an X-Robots-Tag on every response, with canonical URLs still pointing at cmclawns.com.au. They only work as a set, so the handover checklist removes them together in one commit. Available to license or commission.
Screenshots
What I Delivered
- Six-page React site: home, the program, services, before-and-after work, the operator profile and a quote form.
- A browser-measured audit of the existing Wix site, published as AUDIT.md alongside the build.
- A written design direction, produced before any code, covering voice, reference and palette.
- An owner-facing pitch document in plain language, deliberately unpriced.
- A handover checklist that sequences every step needed to take the concept live.
Key Features
- Draggable before-and-after comparison slider over the owner’s own job photography.
- Quote form that mirrors every keystroke to localStorage, so a reload cannot cost a customer their typing.
- Send-failure fallback: with no endpoint, or on a failed request, the form offers a pre-filled mailto and the phone number rather than dropping the enquiry.
- Content tagging system marking each string as owner-supplied, placeholder or unverified, with placeholders visible on the page.
- Four-part concept marking: banner, robots meta, robots.txt and X-Robots-Tag, with canonical URLs pointing at the real site.
Stack & Tooling
- React 18 with Vite 6 and react-router-dom.
- Tailwind CSS 3 with an OKLCH token palette.
- lucide-react for iconography.
- sharp for the image build step, re-encoding source photography to sized WebP.
- playwright-core driving the verification and interaction test scripts.
- Vercel hosting.
Integrations & Backend
- Configurable form endpoint via VITE_FORM_ENDPOINT, with a mailto fallback when it is absent or fails.
- No analytics, no third-party embeds and no tracking in the concept build.
Performance / SEO / Accessibility
- Contrast gate runs before every production build and fails the build on a WCAG 2.2 AA violation.
- Verification re-measures every piece of live text against its real composited background, rasterising a pixel to resolve colour because getComputedStyle returns oklch() verbatim and string-parsing it produces nonsense.
- Photography re-encoded to sized WebP through a scripted build step.
- The C4 footer badge and its animation library load only as the footer approaches the viewport, so they stay out of the initial payload.
Challenges & Constraints
- Rebuilding a business site with no access to the business. Everything had to come from the public site or be marked as missing, which shaped the content model more than the design did.
- Resolving OKLCH colours for contrast checking. getComputedStyle hands back the oklch() string unchanged, so the checker rasterises a pixel and reads it back rather than parsing text.
- Keeping the four concept markings coherent. Any one of them removed on its own leaves the build worse off than having none, so they are documented and removed as a set.
What I'd Improve Next
- Fill every value currently rendering as a placeholder: pricing, service area, opening hours, ABN, insurer and the Google Business Profile link.
- Point the quote form at a live handler and test both the success and the failure path end to end.
- Replace the type-set wordmark with the owner’s real logo artwork.
- Re-read the competitor and service-area claims and refresh their read dates before anything goes live.