Making the portal usable, not just full
Alex, 16 Sep 2026: "right now it just feels like a dump, a load of features that nobody really knows where to click, what to do, how it ties together. Even on the BI side, it doesn't really tell me much. It's just a dump of all the information, which means that our database is probably good. But looking at the entire thing, it doesn't feel very usable."
The database is sound. Three years of bank statements reconcile to the cent, every payment is attributed, and the invoice record matches Stripe. The problem is that the portal presents what it holds rather than what anybody wants to know.
The test for every page: a person who did not build it should be able to say what decision it helps them make. A page that fails that is a filing cabinet drawer.
Done
- Finance pages now carry the question they answer. The front door lists ten pages as questions in the order somebody would ask them. The section bar follows the same order.
- Four pages that answered a question worse than another page were retired to redirects: P&L, Expenses, Personnel, Revenue and acquisition. Two pages counting the same thing two ways is how two people reach two numbers.
- "So what?" explains the year as five lines of arithmetic that reconcile, rather than a dashboard.
- "Did we make money?" leads with the answer in a sentence and folds the detail away.
- The Money page's warnings are computed, so each disappears when it stops being true.
- The team page dates every arrival from the way salaries are tagged in the bank.
- Client cards show what the account is worth. Money kept, payments taken, when they last paid, and a "gone quiet" flag after two months without one. Read from the same function the finance pages use, so a card and a finance page cannot show different money for one client.
- Assignments were in two places and one of them was empty. Cards read two profile keys while the team page read
client_assignments, so cards showed names and the team page said nobody was assigned. Moved into the table, both now read it. Eight clients of 96 have an assignment; that is the real number. - The team page names the accounts with no owner. Eight of 55 active clients have somebody against their name. The 27 that are still paying and have nobody are listed biggest first, worth 415,789 between them, with Design4Space at 94,175 at the top. A statistic became a morning's work.
- Pages say how stale they are. The bank ledger runs to 2 September and is thirteen days behind, because statements arrive monthly and are loaded by hand. Nothing said so, and September was being read as a month with six payments in it. The Money page, So what and Month by month now carry one sentence naming the date and warning that September is a part month.
- The client page carries what the client pays. Eleven tabs about an account and no figure about its money, which lived on a finance page keyed by a different identifier. Four tiles now sit above the campaign KPIs and link through. Gated on the same check the middleware makes, so an account manager still sees no money.
- Plain view or full report, chosen in the URL. One control on Month by month, So what and Costs. A link to the full report arrives expanded, so it can be sent to Junkai. Costs gained most: eleven stacked tables of cost lines became one labelled fold per group.
- Today tells an account manager which alerts are theirs. Rayne read "Nothing is assigned to you" directly above five alerts for clients she does not carry. Hers lead in red; the rest are counted as elsewhere and marked "Not yours".
- The finance view of a client says what was done for them and who carries it, so money is never read on its own.
- Atlas Brain has a link. The page that answers "what is the biggest bottleneck in the business" existed and appeared in no menu, so nobody could reach it. It now sits under Today, and the finance front door points at it. The app's own running cost had the same problem.
Next, in order
- Work and Pipeline did not need the treatment. Checked on 16 Sep: both already lead with a sentence and name their own problem ("13 deals open, and not one has a next step"; "798 facts across 21 clients"). They were built after the lesson finance had to learn. Leave them alone. What they lack is not framing but connection, which is the next item.
- Keep connecting sections. The client page now carries its money. The same is missing the other way: a finance client page shows payments and invoices and says nothing about whether campaigns are running, what was delivered, or who carries the account.
- The rate card is empty. Until Alex sets what a video and a shoot cost, every per-client cost is the house average and a heavy client looks like a light one. This blocks the question he most wants answered: which small accounts are worth keeping.
- Only 8 of 55 active clients have an account manager recorded. The 27 still paying with nobody against them are listed on the team page, biggest first. This needs Alex or Jil, not code.
- Lead to client cannot be measured, and probably never will be for the back years. Leads start 4 Dec 2025 and most clients predate that. Of the four clients carrying both a lead date and a first payment, three show the lead captured *after* they were already paying, so the record is a re-capture rather than the acquisition. Only Alumlus is a real measurement, at 26 days. One data point is not a metric. Worth revisiting only for clients won from now on.
- Shoots, statics, landing pages and media-buying months have no record. Clients who buy those and no video look free to serve.
- A weekly "what changed" view is not buildable from the bank yet. The ledger runs to 2 September, so a seven-day money view would honestly show nothing. It becomes worth building once statements are loaded more than once a month, or from Stripe alone if invoices raised are enough.
- Loading statements is manual and the lag shows. Thirteen days is enough for a month to be misread. Worth automating, or worth a reminder on the first of the month.
Use cases, and who the portal is actually for
Checked on 16 Sep by opening the portal as each person rather than reasoning about it.
- Owner (Alex, Junkai). Well served now. So what, Month by month, Clients and Team answer the questions they ask. The gap is judgement they have not entered: the rate card and who carries what.
- Accounts director (Jil). Same surfaces, and she carries four accounts. Finance is deliberately closed to her, so the money tiles on a client page do not render for her. Worth confirming that is still what Alex wants now that the client page carries money.
- Account manager (Rayne). The daily user, and the least served. Two accounts against an agency of fifty-five, and until today every surface showed her all of it. Alerts are fixed. Her Today still shows agency-wide spend and recommendations that are mostly not hers.
- Editors and setter (Chris, Giles, Irsyad, Vanessa, Wai, Celart). Six people with no assignments at all, so every personalised surface is empty for them. Either they work somewhere else entirely, or the portal has nothing for them yet. Worth asking before building.
Features that exist and never fire
Worth knowing before building more. Each is real code that produces nothing because nobody has entered the input it needs.
- Lead and ROAS targets. Zero of 55 active clients have either set, so the two rules that judge a client against its target have never produced a single item, and the KPI tile on a client page has nothing to show. All 55 do have a KPI cycle start, so somebody began this and stopped.
- The deliverable rate card. Seven kinds, no rates set.
- Client assignments. Eight of 55 carry an owner.
The pattern: the portal is good at computing and poor at collecting. Every remaining gap is an input somebody has to type once, not a feature to build. Worth asking whether these are wanted at all before adding a third place to enter them.
Rules learned the hard way, that apply to every page
- A number on a page must be traceable to a page that shows the rows behind it.
- If two views can disagree, they must read from one function. They disagreed by 5,580 once.
- A warning that is no longer true is worse than no warning.
- Never infer a fact that only a person can know. An inferred assignment reads as knowledge.
- Check identities in code and say on the page whether they held. Do not ask to be trusted.