Tallyroom
B2B dashboard & client portal





Metrics with a clear rule. Monthly contract value only counts confirmed, running contracts at their latest price before the reference date. Tests check the number itself, not just the shape of the response.
Everything about a client in one place. Contact details, projects, contracts, requests and documents together. Internal notes are visible to the team only.
Requests with status and owner. Service requests from all clients in one list: priority, status, who is responsible and when something last happened.
Sharing is a deliberate step. Documents stay internal until someone shares them. Files sit in private storage and can only be reached through the protected API.
Clients only see what concerns them. The client portal has its own data layer without internal fields. 16 integration tests guard the separation, and other clients’ records answer with 404 instead of 403.
- InterfaceReact and TypeScript, four languages, light and dark
- Client portalits own data layer without internal fields, 16 integration tests
- APIExpress with role permissions, other clients’ records answer with 404
- DatabasePostgreSQL, every client only with their own data
- OperationsDocker on my own server, nightly backups, rehearsed restore
Dashboard with a client portal for small digital agencies, in four languages. Live, with a private demo for every visitor; the data is invented and deleted after 60 minutes.
- Stack
- React, TypeScript, Express, PostgreSQL, Docker
- Tests
- 276 unit and integration tests; the integration tests make sure roles hold and no client sees another client’s data
- Checks
- Playwright checks accessibility (axe, light and dark), four languages and keyboard use at six screen widths; VoiceOver and NVDA run for real in CI
- Operations
- Runs with Docker on my own server, with nightly backups and a rehearsed restore
- Performance
- Lighthouse live: mobile 99, desktop 100
Figures from the case study, as of 22 September 2026
























