
Capabilities
- Back office
- Users and roles
- API sync
- Transactional email
Frontend
Backend
Sport Moto Team
CompletedSport Moto Team is the Yamaha Official Riding School in Girona, fifteen years running track days. I built their corporate site as a standalone Next.js 14 app that consumes TrackLap's public API to publish track days automatically, plus a back office where the club edits copy, banners, sponsors, galleries and reviews without touching code.
The challenge
The club had two problems at once: an old site that needed rebuilding, and a track-day calendar updated by hand every time a new date opened. The idea was for the site to feed itself from TrackLap — the platform where they already handle sign-ups — and for everything else to be editable by them, from a phone, trackside.
Implementation
A calendar that feeds itself
Upcoming track days are read from TrackLap's public API inside a Server Component revalidated hourly: publishing a date on the platform makes it show up on the site with no manual step, complete with spots left, price and sign-up link.
Content lives in the database
Copy, banners, sponsors and images are stored in a content-blocks table in PostgreSQL; the literal in the component is only the fallback for when the row is missing. That way the client changes any text on the site without needing a deploy.
Panel with users and roles
A bespoke back office with two roles: the owner manages users, the editor only touches content. Passwords are hashed with scrypt and the session is an HttpOnly cookie signed with HMAC-SHA256.
Sessions validated in two layers
The middleware runs on Edge, where there is no database, so it only checks signature and expiry; the authoritative check — user active, token version current — happens in every API route on Node. Changing a password or deactivating someone expires their open sessions instantly.
A panel built for phones
It gets used trackside: nothing essential hidden behind hover, 44 px touch targets, a pinned save bar showing how many changes are unsaved, and two-step confirmations instead of the browser's native dialogs, which some phones block.
Guest book with its history
An idempotent import of the 660 reviews from the previous site, spanning 2011 to 2026, plus moderation from the panel: publish, hide, pin a position, edit the text and search without depending on accents.
SEO generated from the environment
Robots and sitemap are resolved per request. Prerendered, they froze with the deployment domain baked in and ended up telling Google the wrong canonical; regression tests now keep that from happening again.
The backend contract under test
Vitest covers the API client, the components with logic and the whole back office against a fake in-memory Postgres. A contract test also verifies the real production response when run in live mode.