Thai Cross — Gestão de Academia
Two modules, one system — built around the gym's real routine, with attendance taken standing up, on a phone.
- Role
- Design & Development
- Duration
- 2 meses
- Tech stack
- Next.js · Prisma · MySQL

The challenge
A data model supporting one student across two modalities
Idempotent monthly fee generation and WhatsApp billing
Access control always derived from role, never from the person
The solution
A Muay Thai gym that also runs a Cross Training team managed students and payments in spreadsheets. I built a tailored system with a dashboard (monthly revenue, overdue, today's attendance, who stopped showing up), students, attendance, monthly fees and settings.
The model separates Student from Enrollment: someone training both modalities has one record and two enrollments, each with its own price and due date. Overdue isn't a stored status but computed (pending and past due), so it never goes stale overnight. Each fee stores its own amount, so price changes don't rewrite history.
Role-based access (admin, Muay Thai coach, Cross coach), each with its own branding. Tested with Vitest across four layers and continuously deployed via GitHub Actions to a VPS running PM2.
Key takeaways
Derived state beats stored state when it depends on time.
CI/CD with tests from the start makes weekly delivery safe.
Tailored beats generic when it starts from how the client actually works.
Inside the project



- Next.js
- TypeScript
- Prisma
- MySQL
- NextAuth
- Tailwind CSS
- Vitest
- GitHub Actions
- PM2
- Zod
Like what you see?
Turn.io — Webflow → Next.js
