Employee Self Service Portal
One surface over HR systems, building services, approvals and a SharePoint CMS — with consistency and accessibility enforced at a boundary rather than requested.
- Duration:
- 2021–2025
- Role:
- Lead Engineer
- At:
- Macquarie
Problem
The problem
Everything an employee needed lived somewhere else. SAP for one thing, PeopleSoft for another, building services somewhere else again, approvals arriving from several upstream systems, and content in SharePoint. Each had its own login, its own interface conventions, its own design system, its own vocabulary for the same ideas.
The cost was not any single system being bad. It was that using the company required knowing the company’s org chart of software.
Challenge
What made it hard
You cannot fix this by fixing the backends. Nobody was going to redesign SAP, and the systems underneath would keep multiplying. The only available surface was the front.
Which creates the real constraint: a portal built by many teams over many backends will quietly become as inconsistent as the systems it was meant to hide, unless consistency is enforced by construction rather than by agreement. The problem was never building the portal. It was making the portal stay one thing while many people built it.
Architecture
How it is put together
A Single-spa shell hosting React and Angular micro-frontends against a shared Stencil component library, with Envoy and OPA enforcing policy at the edge, over Node.js services on AWS serverless, fronting SAP, PeopleSoft and the rest.
Policy at the edge is the load-bearing decision. Authorisation stops being something each micro-frontend implements and becomes something the gateway guarantees, which is what lets teams ship independently without each shipping its own security model.

Tradeoffs
What we chose, and what it cost
We chose
Independent deployability with enforced consistency. Teams owned their own micro-frontend and released on their own cadence, but inherited the shell’s identity, the shared component library and the gateway’s policy whether they thought about it or not.
We gave up
Simplicity, permanently. A micro-frontend shell is harder to run than a monolith: version skew between independently released apps, a debugging story that crosses boundaries, and a shared component library that becomes a coordination point exactly when everyone is busiest. The architecture buys team autonomy and charges rent in operational complexity.
Outcome
What changed
Halved
the clicks needed to complete an everyday task
WCAG 2.1 AA
accessibility built into the shared component library, not retrofitted per app
One place
HR systems, building services, approvals and a SharePoint CMS behind a single identity
Design intent, not a measured result.
Four years
in production, and the template for its successor
Lessons learned
What this changed
Anything left to convention drifts and anything enforced at a boundary holds. Accessibility is the clearest case: WCAG 2.1 AA held across the portal because it lived in the shared component library, not because each team was asked to remember it.
The sharper lesson only showed up on the second attempt. This shell had a lot of moving pieces, and they cost more in delivery and maintenance than they returned. Building the same pattern again for different users forced a separation this build never made: the shell should own composition, routing, identity and policy, and stay agnostic about appearance.
Read alongside