When Zesty.io was first conceived of some 10 years ago it was to solve the needs of individuals managing websites for their customers. Simplicity was at the heart of Zesty.io’s products for the developers building the websites and for the business users who would eventually manage them once built. This inspired a lot of “magic” that was done on the software side like automating best practices without the need of manual work. As our understanding of our customers and their needs evolved improvements in the product followed and that understanding continues to inform our decisions around user experience. We now opt for a “batteries included” design, i.e. good defaults, while allowing users more in-depth control over the myriad choices that can be made when constructing content or a webpage.
Although Basil served Zesty.io well, it was only a matter of time until we’d need to begin rebuilding towards a more long term solution for a few good reasons:
The new paradigm of virtual doms allowing for v = f(d)
The current point in time has many front-end frameworks that are well established and with large supporting communities.
A custom framework will always make the already tricky task of hiring trickier.
Working towards the vision of the future had two major hurdles.
We have paying customers! This was going to happen in-flight and we could not stop supporting business feature needs and bug fixes to pursue a ground-up rewrite.
Building Towards Our Goal
To accomplish the task of rebuilding Zesty.io away from our proprietary Basil framework we set about it incrementally by rebuilding one “sub-app” at a time. This incremental approach reduced the turnaround time and limited the scope of the work, reduced the impact of bugs that occur with rewrites, and reduced the effect of product changes on our customers. It also facilitated our ability to start and pause work as business needs dictated, as they often did.
A "sub-app" is designated by a URL path part, for example "/media" which is our digital asset management app. Rebuilding these sub-apps entailed recreating and restructuring discrete sections of functionality. This incremental rebuild allowed us to validate architectures before fully committing to them across our complete product surface. Our media app is a good example of this. We built it with Riot.js and while the ergonomics and design decisions around Riot really fit our tastes we ultimately decided against it for two primary reasons:
Performance. Riot allowed us to work really fast but with the quantity of data our customers bring to the table it quickly started to not meet our rendering speed expectations. We could have worked around these issues and built solutions to improve the performance however, it was more important to put that time towards shipping features.
Community. It had a smaller community which equated to fewer ready-made and production tested solutions for common development needs.
Those reasons are what led us to choose React.js as the foundation for our user interface (UI). With React we got acceptable performance out of the box and had clear paths to solve performance issues when we faced them. Since the community is very large it meant lots of pre-rolled solutions for common problems developers experience when building applications.
In addition to that, hiring is arguably easier, too.
While we had a couple missteps at the start of our journey towards rebuilding the underpinnings of Zesty.io we have ultimately settled on a React + Redux tech stack which we have rebuilt all of our Manager UI sub-apps in; they include the following:
Along with the rebuild of our sub-apps we have built an evolving design system which abstracts common interface elements and experiences in our product.
A key element of our rebuild was being very intentional about our architecture. We have split our product by sub-app to allow dynamic app bundle loading as not every user role within a Zesty.io instance has access to every sub-app. Splitting our bundles like this allows us to deliver only the code a specific user needs. Thus improving performance across the board.
Doing this introduced some unique problems. One of the most interesting was the need for dynamic reducer injection into our "app shell" Redux store.
Our guide post has been the PRPL pattern. This is a pattern we are continually working towards.
Now that we have laid a solid foundation to build our products’ UI on we are excited about what the future holds.
A major downside of not being on modern technologies was the learning curve and maintenance cost for our code bases. With these out of the way we look forward to being more responsive to customer needs, taking time to deep dive into issues, and design solutions which truly solve the problems at hand.
Due to the nature of our product customers can create complex relationships between models which introduce performance issues we could not have predicted. Part of our continuing efforts will be reevaluating and reworking portions of our product’s code to ensure we maintain acceptable rendering performance even in these complex cases.
One way we accomplish this is reevaluating technology choices. For example we reevaluated our use of moment.js. We initially used it because it is well known and battle tested. Unfortunately it is quite large and represents a significant portion of our bundle size and the moment.js maintainers now officially recommends using alternatives. With the rebuild we are now well positioned to experiment with alternatives which can provide us the same features but at a smaller size cost.
Progressive Web App
We want our product to become extremely intelligent by taking advantage of PWA features like background sync so we can fetch data as a user begins to indicate their need for it. Similarly PWA offline capabilities allowed for users’ workflows to not get interrupted while on intermittent connectivity, and web notifications allowed users opt into updates on significant events for resources they care about, e.g. publish events... along with many more features we are dreaming of.
One of the things, as developers, we are most excited about is the Instance Manager code base is now source-available. This means that you can publicly find all of the code we author that makes the instance manager experience operate. We hope that by sharing our efforts in building this code base we can give our customers deeper insight into our process, those evaluating Zesty.io a tangible way to understand the power of the product, and provide a resource to the community for what a non-trivial large product-surface code base looks like.