Overview
WeSwim is the back office for a swimming academy: one app that replaces the pile of spreadsheets, WhatsApp chats and notebooks a small academy uses to run itself. It keeps track of the pools, the coaches, the kids, the class schedule, who showed up, who paid, who still owes, and whether the business is actually making money. It's fully bilingual (English + Arabic) and lays itself out correctly in both directions, built with a Middle-East audience in mind: Beirut time, Levantine Arabic month names, and proper right-to-left throughout.
The Challenge
A swimming academy runs on a dozen little loops that never quite line up: classes get scheduled, kids show up (or don't), parents pay in cash whenever they hand it over, coaches are owed on different terms, and at month-end the owner has no clear answer to the one question that matters: are we making money, and at which pool? Doing that across paper and chat is slow, error-prone, and easy to lose money on.
- Everything has to connect: enter something once (a class, an attendance tick, a payment) and it should ripple through billing, payroll and reports automatically.
- Money has to be exact: all of it is stored and computed in integer cents, because rounding errors in payroll and P&L are unacceptable.
- Two payroll models (salaried vs. paid-per-session coaches), shared family balances for siblings, and per-pool cost accounting all have to coexist cleanly.
- It has to be genuinely bilingual and usable one-handed on a phone, at the poolside.
How I Solved It
WeSwim is a TypeScript app in two halves: a Next.js / React front-end and a NestJS + PostgreSQL (Prisma) back-end, where the entire business is modelled explicitly so data flows instead of being re-entered. Attendance is wired directly to money: marking a swimmer present at a per-entry pool auto-creates the matching cost, and un-marking them cleans it up, all inside a single transaction. Siblings link into one family account so parents get a single combined balance. Two separate payroll calculators handle salaried and per-session coaches, and a profit engine tallies income against costs to produce a P&L overall and per pool.
The trickier engineering lives in pure, unit-tested calculators kept away from the database (money, balances, coach pay, location cost and profit) so the numbers are provably correct. Notifications run on Beirut-timezone cron jobs (overdue balances, trial-lesson reminders, session milestones), delivered in-app and as real Web Push (VAPID, no Firebase). PDFs are generated server-side, and the whole thing ships automatically to a VPS through a GitHub Actions pipeline on every update.
Key Features
- Scheduling: one-off or repeating classes with four calendar views (today timeline, week grid, month, filterable list), including per-weekday times and per-student schedules.
- Poolside attendance: tap present/absent or "mark all present"; a present mark can auto-log the pool's per-swimmer cost.
- Billing & families: every attended class counts against what's owed; siblings share one family balance; one-tap WhatsApp payment reminders.
- Coach payroll: salaried and per-session coaches, bonuses/deductions, and what each coach is owed.
- Profit & loss: income vs. costs (pool rent, coach pay, expenses), overall and per pool, so the owner sees which locations are worth keeping.
- Notifications: nightly overdue-balance scan, day-before trial reminders, and milestone nudges, in-app + push.
- Trials, printable coach-schedule PDFs, an in-app help guide, and an installable PWA with offline basics, all in both languages.
Results & Impact
WeSwim turns the scattered reality of running an academy into one connected system where the owner enters something once and it flows through to billing, payroll and profit. It answers the two questions that actually keep a small business alive (who owes us money and are we profitable, and where) instantly, instead of at the end of a painful month of spreadsheet reconciliation. Under the hood it's a genuinely production-grade build: a fully modelled relational schema and API, a bilingual UI across two fully-translated languages, a substantial hand-written TypeScript codebase, automated tests over the money math, and a demo-data generator that reproducibly builds three years of realistic history (students, coaches, pools, sibling families, thousands of sessions and payments).
