Building a cross-platform desktop app isn’t just about writing code — it’s about leading a team through the chaos of shifting requirements, evolving technologies, and technical roadblocks. Here’s how we navigated that journey and what we learned along the way.
In this article, I’ll share our story of how we overcame technical and leadership challenges, the pivotal decisions we made, and how we continuously pushed ourselves to improve both the app’s performance and the team’s workflow.
The Challenge: Creating a Robust Cross-Platform App
With growing demand for a desktop solution that works seamlessly on both Windows and macOS, we faced a critical decision: How could we deliver a high-quality app without duplicating effort for each platform? After deliberation, we chose .NET Core for cross-platform support. Paired with Electron for the user interface and Vue.js for the frontend, we created a product that ran on both platforms without sacrificing performance or user experience. Communication between the app’s components was handled via gRPC, ensuring seamless interaction between the core and UI layers. For the core app, we implemented the actor model using Akka.NET, which provided the reliability and fault tolerance we needed.
Midway through development, we received a crucial requirement change: decoupling the UI from the core app. This shift would allow us to release UI updates independently of the full app — an essential flexibility for enterprise settings, where app upgrades may be infrequent. We aligned this change with our planned migration from Vue 2 to Vue 3, in response to Vue 2’s upcoming end-of-life in December 2023. Implementing these adjustments in parallel modernized our app architecture, improved stability, and kept us on track.
Our Approach: Innovating While Managing Risks
As development progressed, we realized that success wasn’t just about technology — it was also about how we managed the project. With multiple teams working on different aspects of the app — core app development, UI, build systems, and testing — alignment and transparency were essential.
One of our key innovations was optimizing the build system. Initially, our build times were long, causing frustration among developers. By reusing unchanged binaries, we achieved up to 70% faster builds, drastically improving our developer experience. This saved time and energy, allowing us to stay focused on solving key problems rather than waiting for builds to complete.
Overcoming Roadblocks: Technical Challenges and Quick Pivoting
Midway through development, we encountered a significant issue with offset-based pagination. As the app scaled, we started noticing data inconsistencies, with some users experiencing missing or skipped data. This created confusion and undermined the user experience, especially as we approached our beta release. The team quickly regrouped, and after brainstorming, we decided to pivot to cursor-based pagination. This solution resolved the data skip issue, ensuring a more reliable and consistent experience for users, and allowed us to stay on schedule.
We also closely monitored our progress using internal metrics to track app stability and performance. Our initial target was to ensure the app met a high standard of reliability, and despite facing challenges, we exceeded our expectations at launch. Since then, the team has been dedicated to continuous improvement, working towards even higher performance benchmarks.
Leadership in Action: Stakeholder Communication
A crucial part of our success was maintaining constant alignment with stakeholders. One example that stands out is the Go/No-Go meeting we scheduled before the release. This was the first time I had participated in such a meeting, and it quickly became clear that we were under prepared. While the meeting didn’t go as smoothly as we had hoped, we took it as an opportunity to reflect and improve our approach for the next one.
For the second Go/No-Go meeting, we came fully prepared. We ensured all the necessary data points were ready — performance metrics, risk assessments, and a clear timeline for any remaining issues. This preparation allowed us to align all stakeholders, gain their confidence, and secure approval for the final release. With that, we were able to successfully push the app to production with full support.
Post-Release: Continuous Improvement and Monitoring
After the release, we knew the real work began — ensuring the app continued to perform well in production. The first few days were critical. We released the app to 20% of users in the first 5 days to catch any platform-specific issues. Once those were resolved, we rolled it out to the remaining 80% over the next week, addressing edge cases in real time.
Post-launch, we tracked key performance indicators that served as a measure of the app’s success. While our initial target was set at a high standard, the app exceeded expectations at launch. We’re now focused on continuously enhancing these metrics, striving for even higher levels of performance. This proactive approach ensures that we stay ahead of potential issues, consistently improving stability and delivering a better user experience.
Looking Ahead: Building a Legacy of Resilience
The journey of building this cross-platform app has shaped not only our product but also us as professionals. As a leader, I’ve learned that success is never a straight line. It’s about pivoting quickly, making tough decisions, and keeping the team motivated, even when the road ahead seems unclear. The innovations we implemented — whether in build optimizations, pagination improvements, UI decoupling, or the Vue migration — were critical to our success. They saved us time and reduced frustration, enabling us to deliver a high-quality product on time.
As we continue to innovate and push boundaries, we’re more committed than ever to building products that not only meet user needs but also help us grow as engineers and leaders.
