GenDev®
Fitness coaching · CMS

Himanshu Sharma

himanshusharma.fit is the marketing site and coaching-application funnel for a certified personal trainer in Mumbai, with a hardened admin CMS he runs himself. We built it on Next.js 16 and SQLite, with security wired through the whole stack: every request validated with Zod, every upload checked by its magic bytes, and the coaching funnel rate-limited and forwarded straight into a Google Sheet.

Himanshu Sharma: screen 1 of 8
Role
Design & full-stack build
Domain
Fitness coaching
Surfaces
Marketing · Funnel · CMS
Core stack
Next.js 16 · SQLite
01

The brief

A personal trainer's site has one job: turn a visitor into a coaching enquiry. So the build is shaped around a funnel, a premium marketing page that leads into a pricing section, and a pricing card that drops the visitor into an application already filled in with the plan they picked.

Two things sat underneath that. The trainer wanted to run the whole site himself, so every section is CMS-backed; and because the funnel collects real personal data, security had to be designed in from the first commit rather than bolted on.

02

The marketing site

The homepage is a React Server Component that reads CMS content through cached readers with incremental regeneration, so it stays fast while still being editable. Lenis drives a smooth scroll that respects reduced-motion, and Framer Motion handles the section transitions.

The sections are the usual premium kit done properly: hero, about, training approach, testimonials, and a gallery that links out to Instagram, plus animated glassy pricing cards that each build a prefilled link into the application funnel.

  • RSC homepage, cached CMS + ISR
  • Lenis smooth scroll, reduced-motion aware
  • Pricing cards prefill the apply funnel
  • CMS-controlled floating WhatsApp
03

The application funnel

Picking a plan sends the visitor to the application page with the service, tier, and session count already selected. They complete the form, and the submission is validated against a strict Zod schema, rate limited, and forwarded to a Google Sheet so the trainer gets every lead where he already works.

The whole path is defensive: the outbound call to Google is pinned against SSRF with a timeout, request bodies are capped, and any personal data is hashed before it ever reaches a log line.

  • Pricing card → prefilled /apply
  • Strict Zod validation + rate limiting
  • SSRF-pinned forward to Google Sheets
  • Personal data hashed out of logs
04

A CMS the trainer runs

Every section, plus programs, testimonials, and media, is editable from an admin panel gated by middleware. Uploads are streamed and verified by their magic bytes rather than a trusted extension, served back with range support for video, and swept by a janitor that clears orphaned files.

Even the WhatsApp launcher's number and message are CMS fields, so the trainer can change how visitors reach him without a deploy.

  • Section / program / testimonial CRUD
  • Magic-byte-verified streamed uploads
  • Range-aware media serving + orphan sweep
  • Site settings, incl. WhatsApp, in the CMS
05

Security as the foundation

Security runs through the middleware on every request: a per-request CSP nonce, CSRF protection, JWT verification, and a request id for tracing. Admin sessions are short-lived, jti-stamped JWTs that can be revoked en masse by bumping a session epoch, and passwords are bcrypt-hashed at cost twelve.

Below that, configuration fails fast if it is missing or malformed, a three-tier sliding-window rate limiter only trusts forwarded IPs from configured proxies, and a Vitest suite covers schema validation, URL hygiene, body caps, and PII hashing. The whole thing ships as a non-root Alpine Docker image.

  • Middleware CSP nonce · CSRF · JWT
  • Revocable, jti-stamped 24h sessions
  • Fail-fast env + 3-tier rate limiting
  • 49 Vitest tests, non-root Docker

Deep dive

How a click becomes a verified lead

The point of the whole site is a single conversion: a visitor picking a plan and becoming a coaching application. That path is the most carefully built part of the project, prefilled for the user and locked down for everyone else.

  1. 1

    Prefill from pricing

    An animated pricing card builds a link to /apply with the chosen service, tier, and session count, so the form opens already filled in.

  2. 2

    Validate strictly

    On submit, the payload is checked against a strict Zod schema; anything unexpected is rejected before any work happens.

  3. 3

    Rate limit by client

    A three-tier sliding-window limiter throttles submissions per client, only trusting forwarded IPs from configured proxies.

  4. 4

    Forward, SSRF-pinned

    The lead is shaped into a sheet payload and forwarded to Google Sheets through an SSRF-pinned call with a fifteen-second timeout.

  5. 5

    Log without leaking

    Personal data is hashed before it touches a log line, so traceability never comes at the cost of the applicant's privacy.

What carried the build

Prefilled, defended funnel

Pricing cards open the application prefilled, then strict Zod validation, rate limiting, and an SSRF-pinned forward to Google Sheets keep the lead path clean.

Uploads verified by magic bytes

Streamed uploads are checked by file signature rather than extension, served back with range support, and swept of orphans.

Security in the middleware

Every request passes a CSP nonce, CSRF check, and JWT verification, with revocable, short-lived admin sessions.

Tested and fail-fast

Configuration fails fast on bad env, and a 49-case Vitest suite covers schemas, URL hygiene, body caps, and PII hashing.

Built with

Frontend

  • Next.js 16
  • React 19
  • Framer Motion
  • Lenis
  • Tailwind

Backend

  • Route Handlers
  • SQLite
  • Zod
  • better-sqlite3

Security & infra

  • jose JWT
  • bcrypt
  • CSP / CSRF
  • Docker

Quality

  • Vitest
  • TypeScript strict

Want something built like this?