A personal workout tracker. Laravel REST API with a Vue 3 frontend on top of it.
I built this to practise designing an API properly instead of growing one controller at a time,
which is how most of my earlier side projects went. Everything here started as a written spec
before any code existed. Those specs are in specs/ if you want to see how it was planned.
Log your workouts and see whether you're actually progressing.
- Profile and body metrics over time
- An exercise library, with shared exercises plus your own private ones
- Routines, either built by hand or generated for a muscle group and difficulty
- Workout sessions, where you log sets and reps against the routine
- Analytics for training volume and personal records
Backend is Laravel with a versioned /v1 API. Auth is Sanctum. The interesting part there
is that token abilities are synced from the user's role permissions at login, so authorisation
is on the token rather than being re-derived on every request.
Data access goes through repository interfaces in app/Repositories/Contracts, with Eloquent
implementations behind them. Authorisation is in policies, validation is in form requests
grouped by domain, and responses go through API resources. Controllers stay thin.
Frontend is Vue 3 with Inertia, in frontend/. Pages for routines, workouts, exercises,
analytics and profile.
Tests are Pest feature tests covering registration, login, logout, the exercise library, workout plans and workout logs.
There's a Postman collection in backend/ covering every endpoint.
Putting repository interfaces in front of Eloquent is arguable on a project this size. Laravel already gives you a decent data layer and the indirection costs you something.
I did it because I wanted the controllers and services to depend on something I define rather than on Eloquent's whole surface area, and because it makes the query logic a single place to look when it gets complicated. On a project this small it's more structure than strictly needed. On the systems I work on day to day it isn't.
cd backend
composer install
cp .env.example .env
php artisan key:generate
php artisan migrate --seed
php artisan serve
cd ../frontend
npm install
npm run devTests:
cd backend && ./vendor/bin/pest- Move the routine generator out of its controller and into a service. It's the one place in here doing real logic in the wrong layer.
- Docker Compose for the whole thing, and a CI workflow that runs the test suite on push.
- Analytics currently recalculates on every request. It should be cached.