Case / 01 of 07
Glamease
Booking is the easy part. Making everything around it agree is harder.
Context
A salon marketplace and partner platform where customers discover salons, book appointments and pay, while partners manage bookings, staff, billing, earnings and settlements.
Built as a Turborepo with customer and partner applications, a NestJS API, shared packages and Android applications generated from the same React codebase.
System
What I built
- Customer booking experience
- Partner operations console
- Customer Android app
- Partner Android app
- Booking lifecycle
- Payments and wallet
- Staff management
- Coupons
- Notifications
- Search
- Admin functionality
- Scheduled reconciliation jobs
The hard part
Money, time and people have to agree.
The interesting problems weren’t the screens.
Money could move between Glamease and another product. Booking transitions had to reject invalid states. Dates had to belong to the store’s timezone rather than wherever the API happened to be running.
Those rules live in the system instead of being left to the frontend.
Engineering decisions
- 01
Business rules live in the API.
Booking transitions are validated server-side, so an invalid state can’t be reached from any client.
- 02
Dates belong to the store.
Booking logic uses the store’s timezone, not the server’s.
- 03
Money movement is idempotent and reconcilable.
Payment and wallet state is checked by scheduled reconciliation jobs.
- 04
One codebase, web and Android.
Customer and partner Android apps are generated from the same React code with Capacitor.
Shipped
- Web + Android
- Customer + partner apps
- Docker
Stack
- React 19
- Vite
- TypeScript
- Tailwind
- TanStack Query
- NestJS 11
- PostgreSQL
- TypeORM
- Redis
- Capacitor
- Docker
Integrations
- Cashfree
- MSG91
- AWS S3
- Firebase
- Google OAuth
- GA4
- Microsoft Clarity