Featured project
G.R.I.T.
Training software that keeps prescriptions in code, not in a prompt. GRIT is a Next.js PWA for planning, logging, and progressing resistance training, with AI constrained to exercise selection.
Product type
Installable training PWA
Core stack
Next.js · TypeScript · Supabase
Engineering theme
Deterministic core + validated AI
Product reel
GRIT in motion
A 21-second look at the native-feeling flow: build a program, constrain AI to useful choices, log the work, and watch progress compound.
The problem
Useful guidance without an opaque prescription.
A workout log records what happened; a training plan also needs to explain what happens next. I wanted a product where the rules behind sets, reps, and progression remain explicit and reviewable, while exercise choices can use the lifter’s context.
Success criteria — goals, not results
- Make numeric prescriptions reproducible from typed program settings.
- Reject incomplete or mismatched AI exercise selections before saving.
- Keep program persistence all-or-nothing and failures visible to the lifter.
Deterministic core, bounded AI
The rules engine is pure TypeScript. The AI adapter calls it to build the base program before asking the model to fill exercise slots. Prompt data is explicitly marked as untrusted context, rather than allowed to override the slot instructions.
Validate the choice, not the confidence
validateAiSelection checks catalog membership, muscle-slot matches, missing or duplicate selections, and rationale length. A fluent explanation does not make an invalid selection acceptable.
Save the whole program
The save adapter calls save_ai_program and rejects database errors or a mismatched returned program ID. The server builds saved prescriptions from the rules engine, not model-provided training numbers.
Architecture — design view
Authenticated request
A Next.js route checks the session and builds the prompt server-side. The model key stays on the server.
Deterministic prescription
Pure TypeScript rules build the program and fix the slots, sets, rep ranges, and target effort.
Constrained selection
Gemini receives locked slots and an exercise catalog, and proposes exercise choices with short rationales.
Review and validate
At save time, the server rebuilds prescriptions and validates choices against the current catalog before writing.
Atomic persistence
One database RPC saves the program, days, template exercises, and targets as a transaction.
Tradeoffs
Rules over free-form prescriptions
An explicit rules engine takes more work to maintain than a single prompt. In return, its prescriptions can be inspected and tested independently of a model response.
A smaller job for the model
Exercise selection benefits from context; numeric training prescriptions need stable boundaries. The model proposes choices, while application code owns validation and saving.
A transaction over cleanup code
Related program rows belong together. A database transaction avoids depending on a series of best-effort deletes after a partial save, at the cost of maintaining the RPC alongside the application.
Current scope and limits
The implemented boundaries and their tests are engineering evidence, not evidence of improved training outcomes. This case study is based on the implementation, not live deployment verification. No adoption, model-quality, latency, or cost benchmark is claimed here.
Next iteration
I would make the boundary easier to evaluate: publish a repeatable selection-evaluation set, capture cost and latency under a defined workload, and document failure and fallback behavior with a recorded walkthrough.
Ownership and collaboration
I own the product direction, engineering decisions, and acceptance criteria. AI assists with implementation and review; it does not replace my responsibility to understand the changes and verify them.
How I build with AI