Product · Gym management SaaS
Multi-Tenant Gym Management Platform
A complete gym-management SaaS — members, billing, inventory, payroll, and analytics — built as three apps over one FastAPI service, multi-tenant and trilingual, shipped to production through CI/CD.
The analytics dashboard — inflows vs outflows, revenue mix, and top plans, per year.
Three apps, one API, isolated per gym.
A member-and-reception app and a separate superuser console both talk to one async REST API over a single PostgreSQL database. Everything ships as Docker images built in CI and pulled in production — so prod stays light and a rollback is one tag away.




Caddy · TLS
Docker Compose
GitHub Actions → Container Registry APScheduler cron Daily backups gym_id in the JWT scopes every query — so one deployment serves many gyms and
a cross-tenant read returns 404, not 403.
Eight modules, and what each one owns.
From the front desk to month-end — members and billing, the operations the floor runs on, the analytics that close the loop, and the platform that holds it all together.
- 01
A members module: a searchable directory with live KPIs and advanced filters, and a POS-style signup that creates the member, their subscription, and the first payment in one atomic transaction — so a half-finished checkout never leaves an orphan record.
- 02
A billing engine: subscriptions driven by an automatic state machine (pending → active → expired), bundled and recurring fees, payments by cash, transfer, or cheque, and refunds that create linked records instead of deleting history — every figure traceable.
- 03
Operations modules for the rest of the floor: inventory with stock, sales, purchases and low-stock alerts; staff payroll; and categorised expenses — each with its own KPIs and history.
- 04
An analytics dashboard plus reporting: revenue inflows vs outflows, member cohorts, top plans, and expense breakdowns, with server-rendered PDF journals for accounting.
- 05
The platform underneath: multi-tenant from the JWT so each gym's data is isolated, a separate superuser console for provisioning gyms, a UI in French, English, and Arabic with true RTL, and nightly jobs that expire subscriptions, clear stale payments, and reconcile state on their own.
- 06
The delivery path: a React + Redux Toolkit front end and FastAPI + PostgreSQL back end, packaged as Docker images and shipped through GitHub Actions to a droplet behind Caddy, with daily backups and health-checked, near-zero-downtime deploys.
Built to be lived in all day.
Every screen leads with the numbers that matter, then the records — searchable, filterable, and fast enough for a busy front desk.
The hard part is the invariants, not the screens.
Anyone can draw a form. The work that earns trust is underneath: signup and its first payment commit as one transaction, refunds add linked records instead of erasing them, archived rows are refused if anything still points at them, and tokens refresh before they expire. What can't be verified by hand, a nightly job reconciles on its own.
- Atomic member + first payment
- Refunds keep an audit trail
- Nightly state reconciliation
- Soft deletes, never orphaned
- Silent JWT refresh — no surprise logouts
One product replaces the pile of spreadsheets.
What ships is a real, deployed product, not a demo: three services behind CI/CD, multi-tenant so one deployment runs many gyms, trilingual down to Arabic RTL. The work I'm proudest of is invisible — the invariants that keep it honest. Money is never lost in a partial transaction, archived records are never orphaned because the system refuses to break its own references, and subscription state reconciles itself every night instead of drifting. It's the difference between software that demos well and software a front desk can lean on all day.
Built for the person at the front desk — not the one who wrote it.
Running a business on spreadsheets?
Tell me how your operation works today, and I'll come back with what a product like this would consolidate — and what it would take to stand up.