From Excel Macros to a Mobile App: How We Built Kalendarz Lekarza Stażysty
Somewhere in Poland right now, a young doctor is planning the next 13 months of their post-graduate internship from their phone. A year ago, that same doctor would have been wrestling with a spreadsheet, color-coding cells day by day and hoping the macros calculated everything correctly.
This is the story of Kalendarz Lekarza Stażysty — a mobile app we built at Otocolobus to replace an outdated Excel-based system used by Polish intern doctors to plan their mandatory post-graduate training. The app is live on both the App Store and Google Play, and roughly 1,000 doctors use it every month.
Here's how we got there.
The Problem: A Spreadsheet That Nobody Liked
In Poland, every medical graduate must complete a structured post-graduate internship (staż podyplomowy) before they can practice independently. The internship spans 13 months and includes rotations across multiple specialties — internal medicine, surgery, pediatrics, gynecology, emergency medicine, and others — each with specific time requirements set by the regional medical chamber (Izba Lekarska).
For years, the tool doctors used to plan these rotations was an Excel spreadsheet packed with macros. The workflow went like this: you'd open a grid of days and manually color-code each cell to represent a rotation — one color for internal medicine, another for surgery, another for pediatrics, and so on. Once you'd painted your schedule, the macros would read the cell colors and calculate whether the durations met the requirements.
On paper, it worked. In practice, it was a mess.
The interface was deeply non-intuitive. New doctors — most of whom had never seen the file before — had to figure out which colors mapped to which rotations, how to apply them correctly, and how to read the macro output. There was no onboarding, no legend that made immediate sense, just a rainbow-colored spreadsheet and a prayer.
Manual coloring was the norm, and errors were constant. A wrong color on a single cell, an accidental drag that painted over a week, or a missed day in a rotation could throw off the entire calculation. The macros would dutifully sum up whatever colors they found — garbage in, garbage out. Doctors would discover that their schedule didn't add up weeks later, sometimes after they'd already started a rotation that was shorter or longer than required. Fixing these errors meant going back to the spreadsheet, hunting cell by cell for the wrong color, and repainting — often from scratch.
The file only worked on desktop. Doctors who wanted to check their schedule on the go had to email themselves the file or take a screenshot. Sharing plans with colleagues or supervisors meant sending Excel files back and forth over email.
It was a system built by engineers for engineers — not for busy doctors who needed a quick, reliable answer to "Where am I supposed to be next Monday?"
The Decision: Why Flutter?
When we took on the project, we needed to ship on both iOS and Android with a small team and a tight timeline. That immediately narrowed the field.
We chose Flutter for several reasons.
First, a single codebase for both platforms. With a team our size, maintaining separate Swift and Kotlin codebases was out of the question. Flutter gave us one codebase that compiled to native performance on both platforms — no compromises on speed or feel.
Second, the app is fundamentally data-local. Doctors' schedules are personal and don't require a shared backend. All data lives on the device, which simplified our architecture dramatically. No user accounts, no server-side database, no API to maintain. This also addressed privacy concerns — doctors' rotation plans never leave their phone.
Third, Flutter's widget system made it straightforward to build a calendar-centric UI that felt native on both platforms. The scheduling interface — which is the core of the entire app — needed to be intuitive enough that a doctor could pick it up without instructions. That was the whole point: replace something confusing with something obvious.
We use Firebase Analytics to understand usage patterns and identify friction points, but the app itself runs entirely offline after installation.
The Architecture: Deliberately Simple
One of the best decisions we made was what we chose not to build.
There's no backend server. No API layer. No user authentication. No cloud database. The app is self-contained.
Here's what the architecture looks like:
┌─────────────────────────────────┐
│ Flutter App │
│ │
│ ┌───────────┐ ┌────────────┐ │
│ │ Calendar │ │ Rotation │ │
│ │ UI │ │ Engine │ │
│ └─────┬─────┘ └─────┬──────┘ │
│ │ │ │
│ ┌─────▼──────────────▼──────┐ │
│ │ Local Data Storage │ │
│ └───────────────────────────┘ │
│ │
│ ┌───────────────────────────┐ │
│ │ Firebase Analytics │ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘
The rotation engine handles all the scheduling logic that used to live in Excel macros — specialty durations, legal requirements, date calculations, conflict detection. But instead of relying on the user to enter everything correctly, the app guides them through each step and validates as they go. You can't accidentally create an impossible schedule because the app won't let you.
Local storage means instant performance. There's no loading spinner waiting for a server response. Open the app, see your schedule. Done.
Firebase Analytics is the only external service. It tells us which features doctors actually use, where they drop off, and what causes confusion. This feedback loop has been essential for iterating on the UX.
What We Learned
Start with the pain, not the technology. We didn't set out to build a Flutter app. We set out to fix a broken workflow. The technology choices followed from the constraints — two platforms, small team, no backend needed, offline-first. Every architectural decision was driven by the problem, not by what looked impressive on a résumé.
Simple architecture is a feature, not a compromise. It would have been easy to over-engineer this. User accounts! Cloud sync! Shared calendars! Social features! But none of that was needed. Doctors wanted one thing: a reliable way to plan their internship rotations without fighting a spreadsheet. The simpler the architecture, the fewer things that can break — and for an app used by doctors planning their medical training, reliability matters more than features.
Validation beats documentation. The old Excel system had documentation (somewhere). Nobody read it. Our app doesn't need documentation because it prevents errors in real time. Every input is validated, every conflict is flagged immediately, and the interface makes the correct path the obvious path. This single change — from "paint cells and hope the macros get it right" to "the app guides you through it" — is what made the biggest difference.
Analytics are not optional. Firebase Analytics costs us nothing but gives us everything we need to make informed decisions about the product. We know that doctors primarily use the app during certain periods of the year (when new internship cycles begin), and we know exactly which screens cause the most confusion. Without this data, we'd be guessing.
The Results
The app has roughly 1,000 monthly active users across iOS and Android. For context, that's a significant share of the Polish intern doctor population in any given year.
More importantly, we've replaced a workflow that doctors actively dreaded with one they actually use by choice. The reviews on both app stores reflect this — doctors consistently mention that the app is intuitive and saves them time they used to spend color-coding spreadsheets.
The infrastructure cost is essentially zero. No servers, no database, no ongoing AWS bill. The only recurring cost is the Apple Developer Program fee and Firebase's free tier.
When to Build Simple
Not every project should be this minimal. Our real-time analytics platform for a logistics client uses ECS, DynamoDB Streams, CloudFront, and a full AWS stack — because that problem demanded it.
But Kalendarz Lekarza Stażysty is a reminder that the best architecture is the one that solves the problem with the least complexity. A spreadsheet full of macros was replaced by a mobile app with local storage and zero backend. The doctors are happier, the error rate dropped, and nothing wakes us up at 3 AM.
Sometimes the smartest engineering is knowing what not to build.
At Otocolobus, we build software that fits the problem — whether that's a serverless mobile app or a full-scale AWS platform. If you have a workflow stuck in spreadsheets and want to explore what a modern solution looks like, let's talk.