GC LAL — gamified cohousing platform
Multi-tenant property, booking, tasks-for-points and payments backend, with a React admin and Flutter tenant app.
Background
A cohousing operator needed one system for properties, floors and spaces, booking requests, inventory, resident tasks, invoices and support. Residents earn points for tasks they complete with photo evidence, which feeds into gamified standings.
I designed the whole platform from an empty repo: the NestJS API, the admin web app and the Flutter tenant app, plus the delivery pipeline.
The problem
Several properties share one system, and a resident of one must never see another's data. On a Phase 1 MVP timeline, the usual approach of a tenant filter on every query is the first thing to be forgotten.
Push notifications for bookings and invoices had to be reliable: a notification about a payment that later rolled back is worse than none.
Approach
- Enforce tenancy in one place. A Prisma client extension scopes every query by property, so a missing filter is impossible rather than a code-review item.
- Auth built for a long-lived mobile session: JWT access tokens with rotating refresh tokens hashed with argon2id, refresh reuse detection, login throttling, invite and access codes.
- Transactional outbox for Firebase Cloud Messaging. A push row is written in the same transaction as the change and delivered by a scheduler, so a rollback never sends a notification.
- eSewa payment gateway, UAT and production, behind a PaymentIntent model. Audit events and an activity log on every mutation.
- Both clients generate their API layer from the backend's OpenAPI spec: openapi-fetch on the web, Retrofit via swagger_parser in Flutter. A breaking API change fails the client build.
- Ship with docs: ARCHITECTURE.md, ADRs, SECURITY.md, a delivery plan, and Docker Compose for dev, staging and production with GitHub Actions deploys.
Architecture
Outcome
- Phase 1 MVP delivered as three deployable clients with staging and production pipelines in under a month.
- API at api.gclal.np with an OpenAPI spec that both clients build against.
Lessons
- Tenancy at the data-access layer costs a day and removes a category of security bugs for the life of the project.
- Generated clients are the cheapest contract test a small team can have.