← All Projects
Homepage hero of the Kempt Laundry Services website

Kempt Laundry Services

A website for a pickup-and-delivery laundry business in Benin City — built to be found in local search and to turn visitors into WhatsApp bookings, with no backend to maintain.

Role: Sole developer for a paid client — design direction, build, deployment, and SEO. Built using an AI-assisted workflow (Claude Code).

Next.js 14 (App Router)React 18TypeScriptCSS (no framework)WhatsApp click-to-chatGoogle Maps embedPython + Pillow (share images)Vercel

Problem

Kempt Laundry Services is a pickup-and-delivery laundry in Uselu, Benin City, and a business I'd been a customer of for years before the owner hired me. It needed a website that people searching for laundry in Benin City could actually find, that explained its services and per-item pricing clearly, and that made booking a pickup as easy as sending a message.

Goals

Rank for local searches like "laundry in Benin City," present services and prices clearly, give schools and churches a way to request bulk quotes, and lead every visitor toward one of two actions — schedule a pickup or message on WhatsApp — on every screen size from a 390px phone to a 1440px desktop.

Solution

A three-page Next.js site (Home, Services, Pricing) with booking, opening hours and map, and contact sections shared across every page. "Schedule pickup" and the bulk-quote form both open WhatsApp with a prefilled message, so requests land in the channel the business already runs on — with no server, inbox, or database to maintain. A design system drawn only from the logo's colors keeps every page consistent.

Architecture

Statically rendered App Router pages built from Server Components, with client components only where interaction needs them: the mobile menu, reviews slider, price tabs, FAQ accordion, and quote form. All business data — phone, address, opening hours, services, prices, FAQs, reviews — lives in one content file (lib/site.ts) that the pages, the structured data, and the sitemap all read from, so changing a price or phone number is a one-file edit. Pushes to main deploy automatically on Vercel.

Frontend

Hand-written CSS in a single stylesheet: design tokens taken from the logo (navy, blue, sky), BEM-style class names, and fluid grids (auto-fit/minmax with clamp()) that reflow from phone to desktop with almost no media queries. Shapes borrowed from the logo — wave dividers, a teardrop-framed hero photo, circular price badges — give it personality without a component library. Fonts are self-hosted at build time via next/font, loading only the weights the CSS actually uses.

Backend

None, by design. The bulk-quote form originally posted to a placeholder API route that only logged requests — so a real customer's request would have been silently lost while the page told them "we'll be in touch." I replaced it with a client-side flow that validates all six fields (including whitespace-only answers, which HTML's required lets through) and opens WhatsApp with the request prefilled, plus a fallback link in case the browser blocks the popup.

Database

None. The business data changes rarely, so a single content file replaces a CMS or database entirely — nothing to host, secure, or pay for, and every edit goes through version control.

Challenges

The quote form's silent data loss was the most important fix: a form that looks like it works but delivers nothing is worse than no form at all. Smaller issues came up too — price-badge photos stretching inside their circular frames (fixed by positioning each image inside a fixed-ratio ring), and a section heading pushed to the wrong side by two conflicting flexbox utility classes. Link previews needed care as well: WhatsApp only shows a large preview for images under about 300 KB, so each page's share image is generated to fit that limit.

Technical Decisions

Plain CSS and only three runtime dependencies (next, react, react-dom), all pinned to exact versions, so builds are reproducible and there's very little for a small business to maintain. WhatsApp instead of a backend for bookings, matching how customers already contact the business. Kept on Next.js 14 for launch, with the framework's image-optimization endpoint switched off since the site doesn't use it — less surface area — and an upgrade to Next.js 16 planned. Left review star ratings out of the structured data on purpose: Google treats reviews a business publishes about itself as self-serving.

Results

Live and showing in Google search results, with Google Search Console and Bing Webmaster Tools set up, the sitemap submitted, and the site linked from Kempt's Google Business profile. Every page has its own branded link preview for WhatsApp, Facebook, and X, plus local-business structured data carrying the address, opening hours, and services. The site is drawing visitors, and the owner is happy with it.

Lessons Learned

Test the whole path a user's data takes, not just whether the form submits — the original quote form passed every visual check while delivering nothing. And the simplest architecture that fits the business is usually the right one: routing requests into WhatsApp, which the business already runs on, delivered the feature without a server to maintain.