Website voor Michiel Detailing — mobiele auto detailing in de regio Breda en de regio Goes.
Next.js 16 (App Router, Turbopack) · React 19 · Tailwind 4 · TypeScript · zod · Resend. Nederlandstalig, één taal, light-only ontwerp.
Voor niet-technisch onderhoud — prijzen wijzigen, foto’s toevoegen, live gaan — zie HANDLEIDING.md.
npm install
npm run dev
De site draait op http://localhost:3000 en werkt zonder environment-variabelen. Alleen het versturen van offertemails vraagt een Resend-key; zonder die key geeft het formulier netjes de melding dat het niet verstuurd kan worden.
| Script | Doet |
|---|---|
npm run dev |
Ontwikkelserver |
npm run build |
Productiebuild |
npm run start |
Productiebuild serveren |
npm run typecheck |
tsc --noEmit |
npm run lint |
ESLint (next/core-web-vitals + typescript) |
Kopieer .env.example naar .env.local en vul in wat je nodig hebt.
app/ Routes (App Router)
layout.tsx Metadata, fonts, nav, footer, LocalBusiness-schema
page.tsx Homepage
diensten/ Overzicht + [slug] detailpagina's
prijzen/ Volledige prijslijst (incl. btw)
werkgebied/ Overzicht + [slug] per plaats (lokale SEO)
zakelijk/ B2B-pagina (excl. btw)
offerte/ Offerteformulier
over-mij/, privacy/ Statisch
api/offerte/route.ts POST-endpoint voor het formulier
sitemap.ts robots.ts manifest.ts opengraph-image.tsx
lib/ Alle inhoud en logica — hier pas je dingen aan
site.ts NAW, KvK, btw, telefoon, merken, straal
packages.ts De 15 pakketten + uurtarief + btw-berekening
services.ts De 4 dienstcategorieën met paginateksten
areas.ts De 12 plaatsen, met eigen tekst per plaats
faq.ts Vragen en antwoorden (gedeeld met FAQ-schema)
nav-links.ts Menu-items
structured-data.tsx Alle schema.org-markup
offerte/ zod-schema, rate limit, mailer, templates, submit
components/
nav/ Header met gecentreerd logo, mobiel menu, actiebalk
sections/ Homepage- en paginasecties
ui/ Container, Reveal, Photo, PackageCard, icons, Logo
De inhoud zit in lib/, niet in de pagina’s. Eén prijs wijzigen doe je in
lib/packages.ts; die verandering slaat automatisch door naar de homepage, de
prijzenpagina, de dienstpagina’s, de plaatspagina’s, het offerteformulier en de
structured data. Hetzelfde geldt voor site.ts, services.ts en areas.ts.
app/globals.css definieert semantische tokens (--surface, --ink,
--accent…). Componenten gebruiken alleen die tokens, nooit een letterlijke
kleur. Het logoblauw #c7d5e9 is te licht voor tekst (1,4:1 op wit) en dient
daarom als vlak — --accent (#1b3a63, 11,5:1) en --accent-light (#2f5c94,
6,8:1) dragen de tekst en knoppen.
components/sections/quote-form.tsx → POST /api/offerte →
lib/offerte/submit.ts. Die pijplijn valideert met zod, controleert een
honeypot en een minimale invultijd, throttelt op IP (5 per 10 minuten,
in-memory) en verstuurt via Resend twee mails: de aanvraag naar Michiel en een
bevestiging naar de klant.
Er zit bewust geen foto-upload in het formulier. Foto’s uploaden vanaf een telefoon is traag en foutgevoelig, en mailbijlagen lopen tegen groottelimieten aan. In plaats daarvan vraagt de bevestigingsmail om foto’s via WhatsApp, met een klaarstaande link.
Gemaakt voor Vercel: repo koppelen, environment-variabelen uit .env.example
invullen, deployen. Zet NEXT_PUBLIC_SITE_URL op het echte domein zodra dat
live is — anders wijzen de canonicals naar de *.vercel.app-hostname.
De securityheaders (CSP, HSTS, X-Frame-Options) staan in next.config.ts. De
CSP staat geen enkele externe host toe; voeg je later analytics of een
kaartdienst toe, dan moet die daar expliciet bij.