Liubov
← All work

Licensing dashboard

One shared place for a four-person office that gets restaurants their liquor licenses, food permits and sidewalk cafe approvals.

Client
NY Business Licensing
Role
Sole engineer
Program
Google-funded Hispanic Federation program, 2026
Stack
Next.js, TypeScript, Supabase, Playwright, Vercel

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.

Before → afterOne operating picture replaces four places to look.
ScatteredFour sourcesSpreadsheets, email, Dropbox and memory
System of recordOne applicationStages, tasks, owners, files, payments and history
TodayOne next stepOverdue, upcoming and unowned work

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:

CodeConfirmed stageEight stages with fixed rules for what can come next.
CodeDraft from the stageThe app writes a focused draft for that exact stage.
AIOptional polishAI can improve the wording. It can’t change records or send.
PersonReview and sendStaff check the recipient and details, then send it.

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.

DeliveredBuilt, deployed and in rollout

Presented at Google HQ; staff training and product iteration are underway.

Projected5–10 hours saved each week

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.