/projects/ulbra-admin

← All projects

Ulbra Admin

The numbers the board runs the university on.

Head of Technology — design & implementation · Aug 2026 – Current

.NET 10React 19PostgreSQLMongoDBTanStack RouterDocker Swarm
Private

Overview

The dashboards the presidency and the board use to check the university’s numbers. A .NET 10 API and a React 19 front end that read two systems neither of them owns: prospect data from the CRM, and confirmed enrollment from the legacy Oracle platform through a typed HTTP client rather than a database connection.

What I did

I built it end to end — the API, the integrations, the front end and the deployment.

  • The read-only integration with the CRM’s datastore.
  • The typed client that fronts the legacy enrollment system.
  • The dashboards themselves and the React front end.
  • Authentication and the Swarm deployment.

The problem

The people accountable for the university’s numbers could not see them without asking. Enrollment lived in a legacy platform, prospects lived in the CRM, and reconciling the two meant a request to IT and a spreadsheet that was stale by the time it arrived. The question being asked was not complicated; the answer was just never at hand.

Architecture

Two sources, neither of them owned by this system, behind one API.

  1. CRM storeProspect and pipeline data, read-only.
  2. Enrollment APIA typed HTTP client over the legacy platform — never the database directly.
  3. Admin APIJoins the two and serves the dashboards.
  4. DashboardsWhat the board actually looks at.

What it does

  • Prospect and enrollment figures side by side, from the two systems that own them.
  • Reads the CRM’s datastore strictly read-only — the dashboards can never corrupt the system of record.
  • Single sign-on, so access follows the accounts the university already manages.
  • The same design tokens as the service desk, so six systems read as one platform.

Engineering decisions

  • Deliberately the simplest architecture in the group

    Single project, no modules, no DDD — written into the codebase as a rule, in a house whose service desk is a modular monolith. This system owns almost no domain: it reads two other systems and draws charts. Giving it aggregates and bounded contexts would be ceremony around a query. The architecture is chosen per problem, and the honest answer here was "less".

  • Never query the legacy database directly

    Enrollment could have been read straight from the legacy platform’s database, and it would have been faster to write. It goes through a typed API instead, so the definition of "an enrolled student" lives in one place rather than being reimplemented in a SQL query — and so the day the legacy platform is replaced, one client changes rather than every consumer of it.

  • Read-only by construction

    The connection to the CRM’s datastore is read-only, not by convention but by the credentials it holds. A reporting system that can write to the system of record is one bug away from corrupting the numbers it exists to report.