/projects/Feb 1, 2026

Patrik Warranty Form

Production warranty registration portal for Patrik windsurfing products — multi-step form, direct-to-S3 photo uploads, dual persistence to MongoDB and Google Sheets, transactional email, and IP rate limiting.

next.jstypescriptmongodbs3

The shape of the problem

Patrik International needed a way for customers to submit warranty claims — with proof photos — and for staff to receive structured notifications without manually chasing attachments. File bytes going through a Next.js server would be slow and expensive; a plain form with email attachments wouldn't scale.

What I built

A Next.js App Router portal where each claim flows through a multi-step form: customer details, product info, address autocomplete via Mapbox, and four photo slots (invoice, serial number, full product, close-up).

Photos upload directly to Hetzner S3 via presigned PUT URLs — the server never touches the file bytes. On submit, the server writes to MongoDB and appends a row to a Google Sheet simultaneously, then fires a customer confirmation email and a staff notification in parallel. A MongoDB-backed sliding-window rate limiter blocks abuse per endpoint and surfaces a live countdown in the UI on 429.

The health endpoint (GET /api/health) pings MongoDB, verifies SMTP, and asserts Sheets config — returns 200 or 503 so the load balancer knows what's actually alive.

Lessons

  • Presigned S3 uploads cut server memory and latency to near zero for file-heavy forms.
  • Dual persistence (MongoDB + Sheets) sounds redundant until the operations team opens Sheets and never asks for a dashboard.
  • Boot-time env validation that crashes the server early beats silent runtime failures by a wide margin.