
Therapy that fits a career, not the other way around.
TRS targets a specific wedge — executives, athletes, entertainers, service members, healthcare and shift workers. People whose schedule, mobility or visibility makes traditional therapy logistics fail. The product side is a clinic. The engineering side is a SaaS that has to behave correctly under retries, late webhooks, missed sessions and rescheduled bookings.
We shipped both: a Next.js 16 marketing surface that explains the wedge, and an operational backbone — Nest + Prisma API, encrypted message + notes layer, Stripe-signed webhook ledger, and a single tick-loop worker that does the boring renewal math correctly.


Bookable, billable, encryptable, deployable.
Clients sign in, book the £80 / 80-min consultation, get assigned a therapist, then run on a 2- / 4- / 8-sessions-per-month subscription. Every booking action writes a typed entry to a credit ledger so reschedules preserve the original hold and webhook retries can never double-credit.
Messages and therapist notes are encrypted at rest with AES-256-GCM. Video sessions are wired through an adapter with a mock-twin for local dev. The worker runs reminders, renewals, no-show sweep and notification dispatch on a single tick loop with idempotent dedupe keys. Deploy is one shell script: pull signed images, run schema migrations, bring the stack up. The data plane and queue layer never face the internet directly.



- Next.js 16 · React 19
- NestJS 11
- Prisma 6 · PostgreSQL 16
- Redis 7 · BullMQ
- Stripe (adapter pattern)
- Daily.co video adapter
- AES-256-GCM at rest
- Tailwind CSS 4
- Tick-loop worker (tsx)
- Hardened EU-region deploy
- Signed-image CI/CD
- Playwright · TypeScript
- Marketing site
- Role-aware client / therapist app
- Bookable 80-min consultation
- Subscription credit ledger
- Encrypted messaging + therapist notes
- Video session adapter (Daily + mock)
- Therapist availability + blackouts
- Tick-based worker (reminders, renewals, no-show)
What moved.


For the readers.
Each topic below opens its own page with the full story.
- Deep dive · 01
Three-app monorepo
web · api · worker, plus one shared zod-contracts package. Postgres 16 + Redis 7 underneath. npm workspaces, no Turborepo.
- Deep dive · 02
Credit ledger booking model
Every booking action emits a typed ledger entry with a deterministic key. Reschedule preserves the hold; cancel inside the window writes a release; complete writes release + use.
- Deep dive · 03
Encryption at rest
AES-256-GCM via a single EncryptionService, shared across messages, therapist notes, and Daily-room join payloads. Round-trip + tamper-detection unit tests.
- Deep dive · 04
Stripe webhook + payment ledger
Adapter pattern with a Mock twin for local. Signature-verified raw-body Nest route. Payment.eventId unique. Renewal pipeline gates credits on exact-period payment evidence.
- Deep dive · 05
Tick-loop worker
One tsx loop runs four jobs per tick — reminder scan, renewal scan, no-show sweep, notification dispatch. NotificationEvent rows carry unique dedupeKeys for safe retries.
- Deep dive · 06
Hardened, reproducible deploy
CI typechecks + tests every push and builds signed images for the three apps. One shell script on the host pulls + migrates + restarts. Edge proxy isolates everything behind automated TLS.
Got something
this size?
Big ambitions, we match the energy. Drop a brief — reply within one working day.