With the rapidly-approaching release of Supernova V9, we are introducing a bleeding-edge-of-innovation code definition technology that will put the power of quality code generation into the hands of developers everywhere, for any platform, with the freedom and flexibility to tailor the code output to their preference in order to maximize performance.
We’re calling the new technology Blueprints, and it’s the next step on our journey to create the future of synced product design, where designers and developers seamlessly collaborate, innovate, and accomplish their shared mission at scale.
For too long, strained designer-developer relationships have caused redundancy, confusion, and misalignment. Developers often have to guess at a designer’s intentions from prototypes. Designers get frustrated when their work is lost and the finished product doesn’t solve user needs as intended.
There are numerous tools on the market that attempt to fill this designer-developer gap, but none ultimately succeed because, eventually, they are forced to pick sides. Whether they prioritize a designer’s vision or a developer’s control, choosing one side over the other means the gap remains.
The solution is not for everyone to conform; nor is it to prioritize one at the expense of the other. It is to allow designers and developers to co-create and collaborate as equals, and on their own terms.
Supernova V9 is our next step toward catering to both sides equally in the first fully code-enabled design system manager. But before diving into the specifics of Blueprints, we’d like to take you behind the scenes of how we arrived at this one-of-a-kind solution in the first place.
Our first approach to code gen
When we first decided to take on code generation, we sat down and learned as much as possible about current approaches, tools on the market, what users do, how they do it, and how methods differs from developer to developer, platform to platform, and configuration to configuration.
We found that code generation is judged on the following criteria:
- Code Quality (bugs, trustworthiness)
- Performance (how efficient/performant the code is when executed)
- Maintainability (how well-organized, readable, etc. the code is over the long term)
- Extensibility (how easy it is to extend functionality yourself and add or integrate other code and business logic)
- Flexibility (how well it can conform to required coding standards and workflows, different architectures, platforms and tech stacks, etc.)
Historically, code generation tools haven’t been able to meet these standards, largely because of the way they approach design data.
Design tools use artboards, groups, and layers to visually represent design data. This is perfect for understanding how something looks but lacks information regarding how the product should actually function.
Old school code generation tools take these layers and perform a 1:1 design-to-code conversion, resulting in a heap of raw, structured data representing a design exactly as-is; every layer has its own definition and so does every single piece of styling a designer might have applied.
This is the method most of our competitors use — using raw data without modification — for things like code snippets, design previews, etc., but without behavior data, responsiveness, and the ability to iterate on the resulting code, no developer could ever actually use code from a 1:1 conversion.
We knew we needed to enrich this method with the designer’s intention in order to make code generation worthwhile for developers.
Sure, we could ask for users to help define design intention, but where does the madness end? Asking a person for every intended use is not only technically impossible but also irritating for both us and the user. If a designer or a developer spends half their time explaining what is going on, it defeats the purpose of using the tool in the first place. We had to figure out a way to gather this information without driving ourselves or our users insane.
When a human looks at a design, they immediately understand the purpose behind it because a lot of internal inferring takes place. While AI cannot fully match a human’s intuition, with some clever engineering there’s quite a lot that can be technologically inferred. Positions of elements, relations of elements to each other, texts used, colors used, data present, or even missing can all be used to bridge the information gap.
This was the approach we took — allowing Supernova to fill the gaps users would otherwise have to provide. In order to make this approach work, we had to flip the traditional thought process — rather than thinking in layers, we thought of everything as a component.
A developer’s job used to be identifying components from layers; since it was up to the developer to map layers to components, there was a lot of room for error and redundancy.
With Supernova’s more structured data model, whole components are converted to native SDKs, so that the generated code is linked to actual components, removing the margin of error present in designer > developer handoffs — because there is no longer a need for handoff at all.
This brings us to V8. While we were incredibly proud of Supernova as it was, it still wasn’t the all-powerful code generation tool we had originally set out to build.
Taking a second look at our exporters
Our code exporters for Flutter, iOS, Android, and React Native had extensive functionality, were fully automated, customizable, and adhered to the highest possible standards — but they were also so interconnected that adding any additional features impacted literally every part of an exporter. If something broke, the exporter broke completely. It was a brittle system that required very careful planning and implementation — AKA, a total pain.
To put into context how big of a pain it was, when we added styles in V8, it took three times longer to build the feature into the exporters than to build the feature itself. This was due to the fact that every single use case required its own layer in an exporter — not a sustainable process (especially for a small company), and it was too controlled by the internal team, going against the community-centered approach we strive for.
All of that aside, the biggest issue was flexibility. Without fully customizable exporters, people would avoid using Supernova for the same reasons they avoided previous code generation tools:
- Code structures come ‘canned,’ meaning developers must commit to someone else’s architecture and acquaint themselves with the output
- Locking into proprietary code libraries used as a crutch to shortcut generating complete code
- A lack of configurability at all levels — from code style to code structure, and even project file structure
- It’s often hard or impossible to blend generated code with human-authored code in a normal iterative development workflow
Although we allowed minor style or formatting customization (such as tabs vs spaces or braces vs new lines), most of what we provided was representative of the most common use cases, such as the code architecture structure, types of components, etc. By making a number of decisions on behalf of our users, we were limiting Supernova’s ability to generate useful code for everyone outside of those typical use cases.
Even if we were able to cater up to 80% of developers, we weren’t satisfied with ignoring the remaining 20%. We wanted to reach everyone, and that meant redesigning the exporters in a way that allowed users to modify them to their liking.
With all of the above in mind, we set out to make new exporters that met the following criteria:
- Be extensible by users and hand over the development to the community (or communities) for specific platform/language/architecture
- Work with existing code, allowing to merge code that was written by a developer with a code generated by Supernova
- Support custom components
- Support user-defined architectures
- Be customizable to a point of complete control over the resulting code
- Maintain the robustness and automation level we support nowadays
- Allow users to contribute new ideas that we didn’t think of
- Make it possible to create reusable templates handling specific parts of code generation and make it easy to build those templates
- And lastly, and maybe most outrageously, make it possible to create completely custom exporters from scratch
And guess what, readers — we have! We’ve rebuilt the way we think about exporters from the ground up. We’ll officially introduce V9’s Blueprints in our next article and walk you through how to finally make code generation a part of your toolkit.