A three-sided reporting platform where an organisation submits its metrics once and every funder that requested them receives their own permitted view.
Where it started
Investees and grantees were reporting the same numbers repeatedly, once per funder, in whatever format each funder asked for. Funders, meanwhile, could not benchmark a portfolio because nothing arrived comparably. The hard constraint is separation: funders share a platform but must never see each other's requests, comments or cohort positions, and a composite score is published without exposing the weights behind it.
Report once
An organisation submits a metric once and every funder that requested it receives their own permitted view.
Additive requests
Requests from multiple funders combine, with reporting frequency resolving to the shortest interval any of them asked for.
Per-funder separation
Funders share a platform but never see each other's requests, comments or cohort positions.
Composite scoring
A reproducible score published without exposing the factor weights behind it.
Portfolio benchmarking
Funders compare across their portfolio because submissions arrive in a comparable shape.
Subscriptions
Billing handled through a payment provider, with webhook handling as a first-class endpoint.
- Every separation rule — permission matrix, cohort suppression, comment filtering — is enforced in the API; the client holds no authorisation logic and renders only what it is given.
- Express and Prisma over PostgreSQL, with Zod validating request payloads at the boundary.
- Public marketing routes are prerendered for crawlability while the authenticated application stays a single-page app.
- The client's existing design tokens were ported verbatim and the components rebuilt natively rather than inheriting prototype code.
- Security headers and request logging applied at the service level.
- 01
Modelled metric requests as additive across funders, so one submission satisfies every funder that asked, with reporting frequency resolving to the shortest interval requested.
- 02
Enforced every separation rule server-side — per-funder isolation, the permission matrix, cohort suppression and comment filtering — with the client holding no authorisation logic and rendering only what the API already filtered.
- 03
Implemented a composite score that is reproducible and auditable while its factor weights stay server-side and unexposed.
- 04
Integrated subscription billing through a payment provider rather than hand-building it, with webhook handling as a first-class endpoint.
- 05
Prerendered the public marketing routes for crawlability while leaving the authenticated application a single-page app, which needs no SEO.
- 06
Ported the client's existing design tokens verbatim and rebuilt the components natively, so the platform matches their identity without inheriting prototype code.
- React
- TypeScript
- Vite
- Express
- Prisma
- PostgreSQL
- Zod
- Stripe
Where it landed
Reporting organisations submit once instead of once per funder. Funders benchmark their portfolio on comparable data, and the separation guarantees that make a shared platform acceptable are enforced by the server rather than trusted to the interface.
A short conversation with an engineer, not a sales qualification call. If we're the wrong people for it, we'll say so and point you somewhere better.



