Skip to content
ComputingAmerica

Higher Education & Research

One codebase for the public site and the platform behind it

A public-facing site and an internal student-tracking platform, built years apart on stacks nobody still owned. We consolidated them into one application with one design system and one authorization model, and shipped it without a production regression.

Verified engagement. Every claim on this page traces to a document, a publication or a system somebody can open, and we can arrange a direct reference call for a shortlisted engagement. The work was done by the engineers who founded this firm, in most cases before the firm existed, which is why the dates below predate it. Client names and identifying details are withheld under NDA unless the client has agreed to be named.

Client
A university cybersecurity center and its program stafftxcr.tamu.edu
Duration
20 months, four phases
Team
5 engineers, embedded customer
Year
2023–2025

The situation

What we walked into.

Two systems, built years apart, neither owned by anyone still on the team. They had drifted apart in the way that always happens when the same facts are maintained in two places, and routine content edits were arriving as interrupts to engineers rather than as work the program staff could do themselves.

The public site was failing at its actual job, which was explaining what the center did to the people it wanted to reach. The internal platform tracked students, projects and credentials, and a meaningful subset of that was personally identifiable student information.

The deployment target was university infrastructure with restricted egress, so every dependency had to be self-hostable and reproducible from CI rather than reachable as a managed service.

The team was five engineers working part-time around full course loads, with the center’s director and program staff reviewing weekly. That combination punishes any plan that needs a heroic month.

Approach

How it was sequenced.

Each step had to be independently valuable. That constraint is what let the client stop at any point without being stranded.

  1. Step 01

    Fix the scope before writing code

    Two requirements sessions produced a one-page scope document that fixed three things: the user roles, the data domains, and the in-scope use cases for each. Anything that did not map to one of those cells was explicitly out of scope and tracked in a parking lot. That document is what kept 'just one more thing' from eating the schedule.

  2. Step 02

    Foundations before features

    The first phase shipped no user-visible functionality at all: repository, CI, design system, authentication skeleton and role primitives. Every later change landed on rails that already worked, which is the cheapest time to get them right and the only time anyone will agree to spend on it.

  3. Step 03

    Authorization at the server boundary, not the interface

    Three roles with explicit permissions on every mutation, enforced at the route handler rather than in the components. The interface hides what a user cannot do; the server refuses it regardless of what the interface shows. Anything touching authentication or personal data shipped integration tests against a real database in CI.

  4. Step 04

    Harden, then hand over

    A penetration test, a performance pass, audit logging and handover documentation, with each phase closing on an exit criterion the customer signed off. The rotation of who shipped the riskiest change each week meant no single engineer became the only person who understood a subsystem.

What was built

The parts that mattered.

  • One application serving a static public surface and a gated platform, sharing a design system and a data layer
  • Role-based access enforced at the route handler on every mutation, independent of interface state
  • Test-driven development as the default workflow, reaching 600+ unit and integration tests
  • Required-checks pipeline: typecheck, unit, integration and a preview deployment on every change
  • A data-exposure incident on a legacy route found, closed, credential-rotated and written up within 24 hours
  • Follow-on penetration test led in-house, with a remediation plan the center adopted

Results

Measured, with the method stated.

Every figure below has a defined measurement window and a comparable baseline. Numbers without those are just adjectives.

Production regressions
0Production regressionsAcross the release window, with aggressive refactoring throughout
Tests at handover
600+Tests at handoverThe count is not the point; being able to refactor under deadline is
Incident to written post-mortem
24 hrsIncident to written post-mortemRoute pulled, credentials rotated, access logs audited, report delivered
Under staff who did not build it
Still runningUnder staff who did not build itThe handover held, which is the only real test of one
Closed by default at the route layer is the only design that survives a moment of inattention.
Engineering lead on the project, university cybersecurity center and its program staff

Built with

  • Next.js
  • TypeScript
  • PostgreSQL
  • Prisma
  • Tailwind
  • GitHub Actions

Services involved

Next step

Tell us what’s breaking.

Forty-five minutes, no charge, no deck. We’ll tell you what we’d do, what it would likely cost, and whether you should be building this at all.