LaxTrainer
I coach youth lacrosse, and the thing that actually moves a player is reps on the wall. So I built the whole product around that. A phone app that runs your wall-ball workout, counts the reps, and gives you a reason to come back tomorrow. Mobile app, backend API, admin panel, and a database. I built all of it.
Why I built it
Wall ball is the most underrated thing in lacrosse. It is just you, a ball, and a wall, and it is where stick skills actually get built. The problem is it is boring and easy to skip. Kids do not know what to do, they lose count, and they quit after a week. I wanted something that hands a player a real workout, talks them through it, tracks what they did, and makes the streak worth keeping. So I built it.
I am non-technical by training. I shipped this the way I ship everything now, by building the real thing with AI in the loop and being stubborn about getting it right. This was me proving to myself I could take a product from an empty folder to a working mobile app with a backend behind it.
What it does
The mobile app is the player's side. You set up a profile (position, skill level, age group), pick a workout, and the app runs it for you drill by drill.
- Guided wall-ball workouts. Each workout is a sequence of drills with timers and rest periods between them. The workout player walks through a clean set of states: get ready, playing, log your reps, rest, next drill, done.
- Audio coaching and voice. The app can count cadence, give form reminders, and drop encouragement while you go, so you can keep your eyes on the wall instead of the screen. It also listens for a voice command so you can say "done" to finish a drill early. Built on Expo's speech and audio tools.
- A real drill library. Drills are organized by category (wall ball, stick skills, footwork, position-specific, flexibility, conditioning), by difficulty, and by which hand they train, including weak-hand work.
- XP and levels. Finishing drills and workouts earns XP. The level curve runs from Rookie up to Legend across ten tiers, and it is shared logic so the app and the backend agree on what your level is.
- Streaks. The app tracks your current streak and your longest streak, which is the whole point. Wall ball only works if you keep showing up.
- Badges and challenges. There is an achievement system (streak, skill, challenge, and milestone badges) and a challenges feature you can join by code, with leaderboards per challenge.
- Leaderboards. The backend ranks players by XP, so there is a reason to put in the extra set.
How it is built
It is one monorepo (pnpm workspaces, Turbo) with three real pieces that share types.
- Mobile app. React Native on Expo, with Expo Router for file-based navigation. State runs through Zustand, server data through React Query. Reanimated and Gesture Handler for the feel, Haptics for feedback, plus Expo speech and audio for the coaching layer.
- Backend API. A Hono server in TypeScript, with the full set of routes the product needs: drills, workouts, users, sessions, badges, and challenges. Completing a session is where it all comes together. The server awards XP, updates your profile stats, and recalculates your level.
- Admin panel. A Next.js app where I manage the content: drills, workouts, challenges, and badges. So the catalog the players see is something I can actually curate, not hardcoded.
- Database. Postgres (Neon) modeled with Drizzle ORM. Seventeen tables covering users and profiles, drills and categories, workouts and the drills inside them, sessions and completions, badges, challenges and participants, teams, equipment, and the audio cues.
- Shared package. The position, skill, and category types plus the XP and level math live in one shared package, so the mobile app, the API, and the admin panel never disagree about the rules.
Why it matters
This is the end-to-end proof. Not a screen mockup and not a single-file demo. A mobile app, a backend that does real work on session completion, an admin tool to run the content, and a database schema that holds it all together, designed and built as one product. It is also just a thing I genuinely wanted to exist for the kids I coach, which is the kind of build I do my best work on.