Slavko Babić
All projects

Healthcare / SaaS

Healthcare workforce SaaS platform

Architecture and CI/CD for a growing workforce product — moving a change-resistant legacy codebase to a microservices architecture with a shared component library, without stopping delivery.

Overview

A workforce-management product for healthcare had found real traction, and was now being held back by the thing that got it there: the code that shipped the first version. This was less a greenfield build and more a careful transplant — keeping the patient working while replacing the architecture underneath.

Problem

The symptoms were the classic ones of a product that outgrew its origins. Releases were slow and nerve-wracking. UI work was duplicated across projects because there was no shared foundation to build on. And the architecture itself resisted change — every new feature touched more than it should, so estimates crept up and confidence crept down. None of this is a crisis on any single day; it’s a tax that compounds until the team stops being able to move.

Solution

I designed and implemented the software architecture and the CI/CD processes to get delivery back under control:

  • Laravel backend APIs as the service boundary, with Vue and React frontends consuming them.
  • A shared component repository so UI built once could be reused across projects instead of re-implemented — killing the duplication at its root.
  • A led transition from the legacy codebase to a microservices architecture, done incrementally rather than as a big-bang rewrite.

The outcome was faster, safer releases and a codebase multiple teams could build on in parallel without stepping on each other.

Architecture

The move to microservices was driven by team topology as much as by technology: the goal was to let separate teams own separate services and ship on their own cadence. Backend capabilities were carved out behind Laravel APIs with clear contracts; the frontends became consumers of those contracts rather than reaching into a shared monolithic core.

The shared component library deserves special mention because it’s the least glamorous and highest-leverage part. A common design-system foundation meant a button, a form, a table looked and behaved the same everywhere, was accessible by default, and got fixed in one place. It’s the difference between three teams each maintaining their own slightly-broken date picker and one good one.

Technical challenges

The genuinely hard part of any legacy modernization is that you can’t stop the business to do it. The migration had to be incremental: strangle the legacy paths one capability at a time, keep both the old and new running side by side during the handover, and never present the team with a flag day. That requires discipline about seams — knowing exactly where the new architecture meets the old one, and making those boundaries explicit and reversible.

CI/CD was the enabling work that made the rest safe. You can’t migrate confidently if every deploy is a manual, scary event; automating the path from commit to production is what turned “big risky release” into “many small boring ones”.

Lessons learned

Modernization is a people problem wearing a technology costume. The architecture choices mattered, but the shared component library and the CI/CD pipeline mattered more, because they changed how the teams worked day to day. Give people fast feedback and reusable foundations and a lot of the “the code resists change” problem dissolves on its own. Incremental beats heroic — every time.

Technologies

  • Laravel
  • Vue.js
  • React
  • Microservices
  • CI/CD