Detailing-Website

Michiel Detailing

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.

Draaien

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.

Structuur

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

Waar zit wat

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.

Kleuren

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.

Formulier

components/sections/quote-form.tsxPOST /api/offertelib/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.

Deploy

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.