Even with OpenRewrite’s catalog of over 2,500 code transformation and analysis recipes, there’s always a need to tweak and customize recipes for specific organizations, like adding pre-conditions, deleting whole sections, or combining discrete recipes. Now this is going to be easier than ever with the new Recipe Builder in the Moderne Platform.
The inspiration for the new builder and editor came directly from the pain our users faced when trying to navigate and customize deeply nested recipes. These vital elements were scattered across multiple pages in the Moderne Platform, making editing and exploring recipes cumbersome. We knew our users needed a unified interface to streamline this process for better accuracy and ease of recipe composition and execution.
Our ultimate goal is to help you, our users, understand the dependencies and relationships within complex recipes more clearly. This new interface is designed to make navigating, analyzing, and editing recipes easier and more efficient by consolidating views and tasks within the UI.
In this article, we’ll walk through our design and development process and share the final results.
Sketching and prototyping recipe visualizations
To transform the current recipe builder into a more intuitive graphical view, we embarked on a journey that began with extensive sketching and paper prototyping. Before diving into the engineering proof of concept, we held collaborative workshops to rethink how existing
components could be creatively restructured to form a cohesive new display.
After experimenting with numerous flat graphical representations, we ultimately chose a force-directed diagram model. Using the largest composite recipe comprising 1,701 recipes, we tested various graph models that turned out to be overly complex and misaligned with our vision of creating a user-friendly and aesthetically pleasing topology.
After further sketching, experimentation, and iteration on the topology proof of concept, we settled on a design that integrates a unified interface for topology visualization with a hierarchical tree structure of the full recipe in the right panel. This design simplifies navigation and editing by displaying the entire recipe in a single view.
This new view not only reveals the full breadth and depth of a recipe but also empowers users to edit and compose custom recipes easily. Additionally, we incorporated search and filtering capabilities to streamline the process of finding and customizing recipes according to users’ specific needs.
While there are a lot of cool engineering things peppered throughout the implementation, the question we get asked the most about is the 3D rendering. So how did we build it?
Developing the 3D rendering of an OpenRewrite recipe
Once we have the design direction established for the recipe visualization, our next challenge was to figure out the rendering. We were able to apply a combination of tools and techniques that resulted in a robust 3D tree viewer that empowers users to understand and author complex recipes.
Gathering and structuring data
The development of the new Builder began with our GraphQL API and making the necessary changes to ensure that we could get all the recipe list tree data back. The nested tree data is then transformed into a more usable structure, consisting of a list of nodes or vertices, which contains a node ID and an individual recipe’s information (without the recipeList data), and a list of links or edges, that represent the connection of node IDs. This graph/network structure is very common and helps us integrate with other libraries as well as write our own helpers and libraries for manipulating the graph.
Calculating positional data
To effectively visualize this data our foremost goal was to make complex data comprehensible. We anticipated that users would use this data to understand connections and patterns as well as facilitate better decision making when crafting their own recipes. For these reasons, it was critical for the data to be rendered in a way which makes groupings and relationships easy to identify and understand.
We began by creating an ngraph from our graph data. This formed the foundation for our positional data and allowed us to use the various graph related algorithms associated with ngraph and its modules. Next, we set up a force directed graph layout using ngraph.forcelayout. This step set up a physics simulation where all nodes start at one point and at the start of the simulation are pushed away from each other (think big bang). This naturally allowed the attractive forces, which are predefined based on the links/edges, to keep groupings near each other in space. The result of the simulation is an arrangement that minimizes overlap and maximizes clarity.
To further enhance the visualization, we employed a high dimensional embedding method. This allowed us to set the initial position of the nodes prior to running our force layout simulation, such that the graph’s overall structure would be more accurately represented from the start. One way to think about this is the starting positions of race cars where the order does not guarantee the race ends in the same order, but it biases the final result. Regarding our graph, this approach ensured that the graph layout is not only aesthetically pleasing but also retained the meaningful relationships and patterns inherent in the data.
Lasty, we run our simulation and at the end have the positional data for each node.
Rendering the scene
With the positional data defined and ready, we used Three.js as our 3D renderer. Three.js provides a versatile and powerful platform for creating intricate 3D scenes. The basic components we built were:
- Scene—responsible for setting up the canvas, lighting, and initialization of the camera controls.
- Orb—responsible for the mesh, sphere geometry, and material properties
- Link—responsible for connecting vertices with a colored line
We made many iterations here with some notable things being foregoing default orbital controls in favor of customizing our own camera controls, which included dolly to cursor movement, creating our own material shaders using WebGPU Shading Language (WGSL), and creating a debug tool for designers to manipulate any of the colors live.
The Moderne Recipe Builder in action
The development of the new Recipe Builder has been a journey of invention, design and engineering at Moderne. By addressing the challenges of our users we have created a powerful tool that brings clarity and efficiency to authoring recipes with ease and accuracy.
The new Recipe Builder is designed to offer an intuitive interface that simplifies the process of navigating back and forth from the Recipe Marketplace, editing, and composing deeply nested recipes across pages.
Users start by accessing an entire recipe in a single view. The center canvas features a topology visualization, utilizing a force-directed model, to represent the relationships and dependencies within a recipe. The 3D rendering provides a dynamic and engaging way to comprehend complex recipes making the build process both visually stunning and highly functional.
The right panel contains a hierarchical tree view of the same recipe that allows users to explore, change arguments, delete, and edit. Search and filtering in this panel enables users to quickly locate and customize a recipe based on their needs. Our goal was to ensure that users could intuitively understand that the left visual representation of the recipe tree and the right hierarchical representation are the same recipe. This alignment of understanding was crucial to provide a seamless and coherent user experience.
We are currently working with our customers to gather feedback and iterate as we learn. As we continue to gather insights and refine the functionality, users like you will have the opportunity to explore and test this innovative feature now.
Explore the Builder today and experience the next generation of OpenRewrite recipe development at Moderne.