The problem
An agency reporting to a roster of clients every month does the same work repeatedly: chase each account for their numbers, assemble them into a document, write a paragraph explaining what the numbers mean, export it, and email it. Multiply by the client list and it consumes several days of senior time every cycle — time that produces no new value, only the same value again.
Worse, the chasing is invisible work. Nobody sees the effort spent finding out that three accounts have not submitted yet.
What I built
Two applications that operate as one system.
- An intake portal where each account submits their weekly and monthly figures through structured forms — separate flows for different service lines, plus financials and strategy inputs.
- A reporting dashboard that reads what came in, tracks it against per-client goals, surfaces which accounts are healthy and which are drifting, generates the written summary, renders the report as a PDF, and sends it.
Both sit behind one-time-passcode authentication with signed sessions, because the data is commercially sensitive and the users are not technical.
How it works
Submissions land in a structured store the team can still inspect directly — deliberately, so nobody is locked out of their own numbers by the tool meant to help them. The dashboard reads against that, compares to goals, and derives the health signals.
The narrative summary is generated through the Claude API from the actual figures, then reviewed before delivery. The report renders server-side to PDF and goes out through a transactional email service. Reports can also be shared as tokenised links, so a client can open one without needing an account.
Scheduled checks watch for the things that quietly go wrong — a missed submission, an invoice past due, a month with no monthly report — and raise them rather than waiting for someone to notice.
Decisions worth defending
The generated summary is reviewed, never auto-sent. The model is good at turning numbers into readable prose and unreliable at knowing which omission matters. Keeping a human approval step is what makes it usable for client-facing work.
Authentication is one-time passcode rather than passwords. For a small set of infrequent, non-technical users, passwords generate support burden and get reused; a passcode to a known address removes both problems.
What changed
The reporting cycle stopped being a manual assembly job. Chasing became visible — the system knows who has not submitted, so the follow-up is a glance rather than an investigation. And the monthly narrative starts from a draft rather than a blank page.
The interface above is an illustration built for this portfolio, with invented clients and figures. No client data appears anywhere on this site.