The problem
A New York liquor license moves through eight stages, from application sent to final license. Along the way it picks up community board notices, fingerprinting, documents, payments, agency follow-ups and deadlines. One client can mean three approvals running at the same time.
The team could find any detail if they went looking, but it was spread across spreadsheets, email, Dropbox and memory. Nobody had one view of what needed attention today, who owned it, or what should happen next.
“Clients need to feel that everything is organized and under control.”
The office’s founder
The goal was to make that true inside the office first.
What I built
Staff sign in and land on a Today view: overdue work, upcoming work and work with no owner. Opening a task shows its owner, deadline and priority, and links to its application. The application page keeps the stage, tasks, documents, payments, mailings and history together.
- Data: Postgres through Supabase for clients, applications, stages, tasks, deadlines, documents, payments and activity history. I cleaned and imported the office’s existing client data before launch.
- Access: only approved staff can sign in, access is role-based, and client documents sit in private storage.
- Quality: Playwright end-to-end tests on the main flows run in GitHub Actions, and deploys go through Vercel.
Where the AI is
One follow-up email, from start to finish:
Decisions and why
- Model the office’s real process. Staff think in stages like “fingerprinting” and “conditional approval.” If the software used other words, they’d keep a spreadsheet on the side, and the spreadsheet would win.
- Put ownership on each task. This came out of talking to the team and changed the data model. On one application, different people handle the community board, the fingerprints and the payment. Owning the whole application hid that.
- Keep the workflow deterministic. Stages drive deadlines, and deadlines drive the day. That part has to behave the same way every time and be easy to explain, so it’s ordinary code.
- Give AI one small job. A clear, polite agency follow-up takes real time to write, and a bad draft costs nothing because a person reads it first.
- One backend for data, auth and files. As the only engineer, fewer moving parts meant more time on the product. Postgres underneath means the data isn’t trapped.
Tradeoffs I accepted
- AI could read incoming agency emails and move applications forward on its own. I didn’t do that, because a wrong stage quietly shifts every deadline after it. Staff still update stages by hand.
- Supabase for auth and storage ties the app to one vendor more than separate services would. I took that for speed.
- The app fits this office closely. I didn’t make it configurable for other offices that don’t exist yet.
Outcome
The office now has one place to see what needs attention, understand an application and take the next step.
Presented at Google HQ; staff training and product iteration are underway.
The client’s expected benefit once the team has fully adopted the new workflow; not yet a measured result.
Client data is private, so there’s no public demo. I’m happy to walk through it live.