CONTROLE
DE TREINO
THE "COPY-PASTE" CEILING
"Personal Trainers have a hard cap on their income: time. To manage more than 50 students, they usually sacrifice quality, resorting to generic 'copy-paste' spreadsheets sent via WhatsApp."
The friction here isn't just administrative; it's a quality bottleneck. The status quo forces trainers to choose between Scale and Personalization. We needed a system where the AI acts as the "Junior Coach"—handling the heavy lifting of periodization and volume calculation—while the human trainer focuses on strategy and relationship. It’s not about replacing the trainer; it’s about giving them superpowers (and their weekends back).
NEXT.JS 15 & SUPABASE RLS
[ Athlete/Trainer ]
|
v
[ Next.js 15 Edge Middleware ]
|
v
[ React 19 Server Components ] ----> [ Supabase Auth ]
|
+-- (Data Fetching) --> [ Supabase Postgres ] <--(RLS Policies)-- [ User ]
|
+-- (Prompt Context) -> [ Vercel AI SDK ]
|
v
[ Gemini 2.0 Flash ]We skipped the traditional backend API boilerplate and went straight for Supabase. Why? Row Level Security (RLS). In a multi-tenant SaaS where one trainer manages 100 students, data isolation is critical. RLS ensures that the database engine itself enforces permission rules, not the application logic.
We are also leveraging Next.js 15 (App Router) to keep the dashboard snappy. Hydration is expensive; we keep as much logic as possible on the server.
CONTEXT-AWARE WORKOUT GENERATION
The problem with most "AI Workout Apps" is that they hallucinate exercises that don't exist or ignore the gym's equipment. We are building a pipeline that moves from simple "Prompting" to a structured RAG (Retrieval-Augmented Generation) system.
System analyzes metadata (Injuries, Experience, Equipment).
Injects specific constraints of the trainer's periodization style.
Learns from "Daily Check-ins" (RPE, Sleep, Pain) to adjust intensity.
// Leveraging Vercel AI SDK with Gemini 2.0 for structured output
import { google } from '@ai-sdk/google';
import { generateObject } from 'ai';
export async function generateWorkout(userProfile: Profile, constraints: any) {
// We force Gemini to return JSON, not chatty text.
// This allows us to map the result directly to our UI components.
const { object } = await generateObject({
model: google('gemini-2.0-flash-exp'),
schema: workoutSchema,
prompt: `Create a Hypertrophy workflow for a ${userProfile.level} athlete.
MUST respect these injuries: ${userProfile.injuries}.
Available equipment: ${userProfile.equipmentList}.`,
});
return object;
}"SWEATY FINGERS" UX
I've used too many apps that require surgical precision to log a rep. That doesn't work when your hands are shaking from a deadlift.
We adopted a "Low Friction Input" philosophy using shadcn/ui and TailwindCSS: Big Hit Areas, Dark Mode Native, and strict Information Hierarchy.
Generation Time - Reduced the time to create a personalized weekly plan from ~45 minutes (manual) to under 4 minutes.
Latency Reduction - Switching to the Flash model reduced token generation latency significantly.
The Supabase backend seamlessly handles complex many-to-many relationships (Trainer <-> Teams <-> Athletes).