
The problem
Requests came in through Slack, Gmail and the client portal, and someone had to log and assign each one by hand.
What changed
Every message turns into a ticket with an owner and a deadline on its own, and the team gets the alert in Slack.
What I built
- Inbound parser that turns Slack threads and Gmail messages into structured tickets with the right owner and SLA.
- Role-based access on top of Supabase row-level security for partners, associates, paralegals and clients.
- Operational dashboard with SLA timers, queue health and per-client load.
- Bidirectional sync so updates in the Hub fire back into Slack and email without spamming.
What I learned
- RBAC at the database layer (RLS) saved me months of bug-hunting compared to enforcing it in the app.
- Lawyers don't read dashboards. They want one alert in Slack with the right action button.
- The hardest part of ticketing isn't the UI, it's deduplication across three input channels.
Stack
- Next.js
- TypeScript
- Tailwind
- Supabase
- Postgres
- Slack API
- Gmail API