A website for a cleaning and junk removal company

Home page of ajcleaningandremoval.com: the headline beside the full logo with the truck, and the start of the services list

A&J Commercial & Residential Cleaning is the other business run by the people behind A&J Gates & Fences: cleaning for homes and businesses, and junk removal, around Central Florida. They had a logo and two phone numbers and needed a site that says what they do and takes a quote request.

What it is

One page plus privacy and terms. The hero has the logo with the truck and a call button. Services is a plain list: vacuum, mopping, trash removal, yard services. Junk removal is the second service line, with its own option on the form. Then the quote form, contact details and footer.

The copy went through the same cut as the gates site. An early draft had a 5.0 rating badge and a satisfaction line; they came out, and what is left is the confirmed facts: what they do, where, the phone numbers, and that they have been licensed since 2016.

The palette comes from the logo: blue, teal, a green accent, navy, white. The supplied logo was one PNG. I cut it into a full version with the truck for the hero and a wordmark for the header and footer, made the backgrounds transparent, and saved both as WebP. Inter and Plus Jakarta Sans are self-hosted. There are no cookies, no analytics and no third-party fonts, so the privacy page is short and there is no cookie banner.

Same stack, shared Worker

Vite, React, TypeScript and Tailwind v4, with the same 21st.dev header and shadcn-style primitives as the gates site. Production is a Cloudflare Worker with static assets; wrangler deploy builds, uploads and owns the custom domains. The old Pages project stays up only to redirect its pages.dev address to the domain, because the QR codes point there.

The quote endpoint is the same Worker code on both sites. The two forms name the message field differently, description on gates and message here, so the handler accepts either. Otherwise it does the same work: honeypot, server-side Turnstile verification pinned to the quote action and the site’s hostnames, limits on fields, and an email through Cloudflare Email Service with the visitor as reply-to.

The form fallback

The first version posted to Formspree with fetch, and Formspree’s own bot check blocked background submissions. The fix was to keep a real action on the form: if the JavaScript path fails, the browser posts the form the ordinary way, and a hidden _next field brings the visitor back to /?sent=1#quote so the page can show its own thank-you instead of Formspree’s. When the site’s own endpoint replaced Formspree as the main path, the fallback stayed. Both sites now try their own Worker first and fall back to a plain Formspree post on any server error. A hidden business field and a _subject line tell the two businesses’ requests apart when they land in the shared Formspree inbox.

Tagged cloudflare, workers, react, vite, tailwind, client work.