Simplifai Platform in a nutshell The Simplifai Platform is the space where customers create their AI Agents and design automation workflows. From the frontend perspective, it's a complex system that combines multiple AI modules (for chats, emails, documents, and more), workflow builders, dashboards, settings, and other tools.
The UI of the Simplifai Platform At the time, Angular was the obvious choice. Our frontend team already had solid expertise in the framework, and its strongly typed, structured approach paired well with the backend stack in C#/.NET. The architectural similarities meant that frontend and backend teams could easily understand each other's codebases, review changes, and even contribute across the stack.
The frontend app was designed to be highly modular, with a standalone custom design system . Back then, Angular didn't offer robust design systems or component primitives suitable for building complex UIs like ours - so we built one ourselves.
Lessons learned For many years, the heart of Simplifai AI was our NLU . On the frontend side, this meant one thing: training UIs . A big portion of our effort went into building sophisticated training workflows.
For example, in the document AI module, we had to let users mark documents with intents and entities, select and annotate table layouts, categorize pages, and more. There were essentially no libraries available for this, so we had to create a complex document rendering engine from scratch - think of it as a PDF reader, but with a strong focus on text selection and tagging. This was probably the most UI-heavy part of our product, and it's where I first started questioning whether Angular was really the right tool for the job.
The UI of the document module training Our document AI module also had to handle huge documents. To achieve top-notch performance, we needed scrolling virtualization so that only visible pages were processed and rendered instead of hundreds at once. Angular CDK was (and pretty much still is) the only option in the Angular ecosystem for scrolling virtualization. Unfortunately, it was highly opinionated and, most importantly, didn't support variable-height elements - a common case with scanned PDFs. So we ended up building our own custom virtualization… the first time.
Later, when we set out to build a new, better Flow Builder , we ran into the same challenge . Customers' flows could grow extremely large, so virtualization and precise rendering optimizations were again essential. And again, the Angular ecosystem lacked tools that could help us. We had to reinvent the wheel and build our own solution.
In retrospect, libraries like react-window or React Flow could have saved us a lot of time. For the new Flow Builder, we introduced a schema-driven approach : the backend sends a UI definition (what components to render and how), and the frontend renders it dynamically. This gave us a single source of truth for configuring and adding new components. In practice, though, it meant maintaining a lot of Angular templates with APIs like ngComponentOutlet /ngTemplateOutlet . Even with the new template syntax, it was clear that Angular was not designed for this kind of dynamic UI composition.
The implementation would have been much simpler if we could just assemble the UI dynamically using JSX. Then came the big rebrand . With new branding, we had to completely revamp the look of the Platform. Ironically, this coincided with the rise of LLMs. That's when our Angular-based custom design system turned into a liability. Updating it required far more work than it should have. Had we used a more flexible foundation, the transition would have been smoother and faster, leaving us more time to deliver business-critical features.
Now, as an Agentic AI-first company, we need tools that match our pace. Angular simply didn't let us move fast enough.
Enter React Migrating to React was a natural solution to our problem.
But first, we had to select the toolset. The React ecosystem offers a lot of options, so we carefully evaluated which tools to adopt. For each case, I built a POC to test the architecture and validate how solid it was.
React framework The Platform is essentially a SPA, and we plan to keep it this way. Even so, the React team now officially recommends starting with a framework even for single-page applications. For the Platform, we chose React Router v7 (in framework mode ). It's a battle-tested tool that comes with the complete set of features we need.
My favorite feature: type-safe routing. One of the many things we previously had to build from scratch now comes out of the box. Even in framework mode, React Router gives us plenty of flexibility.
We also considered alternatives: Next.js (more opinionated than we wanted) and TanStack Start (promising but still in beta).
Design system For the design system, shadcn/ui + Tailwind was a clear winner. Tailwind provides a well-structured design language, while shadcn/ui (with Radix UI at its core) is by far the most flexible component framework we've worked with. As a major bonus, we no longer have to build our own accessibility layer from scratch since Radix UI takes care of that .
Testing We picked Vitest as our testing framework. It integrates seamlessly with Vite , which we already use, and gives us all the testing tools we need. To test the app in more realistic scenarios, we're currently experimenting with MSW to mock backend APIs.
The new architecture Our Angular app already used a feature-based multi-tier architecture , and the good news was that it translated surprisingly well into React:
Presentation layer → React components Business layer → custom hooks + SWR mutationsData access layer → SWR queries + React context This structure made the migration much more approachable for the team.
For the data layer, we use SWR , which provides caching, revalidation, and an elegant service-like pattern for queries and mutations.
There are still Angular modules that haven't been migrated. To keep them accessible, we introduced a micro-frontend bridge , which lets us load parts of the Angular application inside the host React app during the transition.
Trade-offs Of course, no migration comes without trade-offs. Here are a few we've had to balance:
The new mindset. Along with new tools, React brings a different approach to building UIs. While most of our developers were already familiar with it, moving from Angular's structured layers and predictable reactivity will take time.
Two systems in parallel. Even though the micro-frontend architecture neatly separates React and Angular, it still means more overhead, more cohesion work, and more complex builds.
React quirks. A React component is "just a function." That comes with its own challenges: remembering the Rules of Hooks , handling stale state closures, and other quirks. And I'll admit - I do miss Angular's signal-based reactivity .
React isn't a silver bullet. It has its own downsides, and we need to account for them.
The results The new stack has been working great so far. From the feedback we’ve collected, it’s clear that the overall experience has improved in several important ways.
Pages now load faster. With only frontend work, we’ve been able to significantly improve both the UX and the perceived performance of the UI. A big part of this comes from SWR caching , which gives us a highly optimized data layer almost for free. On top of that, we’ve built our own preloading mechanism, which makes navigation feel instant.
The UI also feels noticeably snappier. Our Angular app was already highly optimized, but what it lacked was a consistent design system. With shadcn/ui, we finally have well-balanced component interactions, which makes the interface feel smoother and more cohesive to our users.
On the development side, the difference is just as dramatic. Re-implementing some Angular modules in React took only a few days, and the team can now deliver new features in parallel with the ongoing migration. The improvement in velocity has been exactly what we hoped for when we planned the switch.
Finally, there’s the nice bonus of faster CI builds . Although it’s hard to measure accurately right now (since we still have Angular microfrontends in the codebase), early estimates suggest at least a 1.5× speed boost once the migration is complete.
Most importantly, users are noticing the difference. The new Platform feels faster, smoother, and more consistent, which is exactly the outcome we wanted.
The bottom line The team and I are excited to be moving to React.
First, it comes with the largest frontend ecosystem out there. Instead of spending months building infrastructure ourselves, we can focus on solving business problems and delivering value faster.
Second, the nature of React suits our requirements much better. Its component-driven architecture and flexibility align perfectly with the way we build UIs. We no longer have to fight the framework.
Third, shadcn/ui and Tailwind give us the design system we've been missing. They speed up development and allow our design team and developers to work with the same building blocks and vocabulary.
In addition, the combination of React, shadcn/ui, and Tailwind is super LLM-friendly . As an AI company, we need a stack that works well with AI-assisted development and rapid prototyping, and React's ecosystem is simply better positioned for that.
Finally, we now have a stack that truly matches both our pace and our ambition.