What this is: an internal profitability dashboard for a mid-size accounting firm that joins Xero invoiced revenue to Karbon logged time, so partners can see effective hourly rate (EHR) per client in one place instead of rebuilding it in Excel every month-end.
Stack: Karbon + Xero APIs, PostgreSQL, Express, React Replaces: a manual month-end export-and-VLOOKUP cycle
What was broken?
A mid-size firm was flying blind on client profitability:
- Xero held invoiced revenue by contact name
- Karbon held logged hours and job costs under different client names
- Budgets lived in a spreadsheet with no reliable link to Karbon work items
- No shared view of effective hourly rate (EHR), utilisation, or budget variance
Month-end meant exporting, VLOOKUP-ing, and hoping the Excel model didn’t break.
What I built
A practice-management analytics dashboard — the same class of tool firms pay SaaS vendors for, tailored to how this firm actually works:
| Module | What it shows |
|---|---|
| Profitability | Revenue vs hours per client, EHR, onshore/offshore split, client-group rollups |
| EHR Rate | Chart + table vs a target rate slider |
| Team Utilisation | Actual hours vs contracted capacity per team member |
| Budget Analysis | Uploaded budget vs Karbon actual cost, grouped by client or job |
| Client Mapping | Xero ↔ Karbon name matching with auto-match and manual override |
| Client drill-down | Invoices, jobs, time entries, and monthly trend per entity |
How it’s architected
- Production system: Karbon + Xero APIs → PostgreSQL → Express API → React dashboard
- Portfolio demo: Static React app with synthetic JSON fixtures — same UI, no backend, no real client data
The demo uses fictional names (Acme Tax Partners, Harbor Retail, etc.) and a visible Demo data badge.
Try the demo
Use the FY25/26 date preset on the Profitability page to see the full dataset. Switch to Grouped view to see the Summit Family client group rollup.