In this post, I'm going to outline the process of building my new app, SourceNote, using Lona.
SourceNote is a very small app written for a single platform by a single developer, so it's far from the intended use case for Lona. In other words, I'm going to keep this post short. But I plan to go into more detail about Lona in the hopefully-not-too-distant future — there are a few much more interesting apps and websites (i.e. with millions of users) that are pretty close to shipping some Lona-generated components to production.
Lona is a tool for building and maintaining cross-platform design systems at scale. It comes in 2 parts:
The goal is to design a component once, fully specifying how it behaves in every condition (responsive screen sizes, error states, different languages, etc) and generate an identical UI on every platform you support.
I started the project while at Airbnb, in order to address issues that arose when scaling the design system to hundreds of designers and engineers. It's open source and MIT licensed.
The whole premise of Lona was to make design systems scalable at large organizations. But... it turns out that the size of the app doesn't really matter.
Building UI components visually is simply better than coding them manually:
Also, while Lona is intended for building components used in many places throughout an app, it works just as well for building components or screens used only once. Landing screens and onboarding screens often need a lot of iteration to get just right, and building them in Lona really speeds up that iteration cycle.
Here are a couple examples of components built in Lona.
If you've downloaded SourceNote, this component should look familiar. This is the very first screen when you launch the app:
And here's how it looked in Lona Studio when I was designing it:
Lona made it super easy to lay out the different text and image elements. It was easy to iterate on this screen as I watched beta testers launch the app and run into issues.
The built-in Mac buttons are a little boring, so I decided to make something in a similar style but with a bit more color:
You can see the button has two possible colors. Setting the
highlight parameter will cause it to use the green color. I also made sure it looked acceptable if the text ever wrapped around.
This modal overlay is part of the license activation flow:
You can see it uses the
ColoredButton component in two places. The text input field is an existing macOS system component (
NSTextField), so the one you see in Lona Studio is actually a placeholder:
In Lona, if you want to use an existing component, you can specify its name and parameters, and provide a placeholder UI for Lona Studio to show. Think of this as a contract between Lona and the target app. As long as both sides adhere to the contract, they can integrate seamlessly. If one side doesn't, you'll get a compile-time error. There are other ways to integrate existing components, but so far I've found that this is the most common way.
In this example, you can also see this component has 2 states: default and error. Lona makes it convenient to see both at the same time.
It's important to think through which components should and shouldn't be built with Lona. It's relatively easy to mix-and-match Lona-generated components and hand-written components, so if Lona doesn't have the right features for a specific component, or even if you just don't think it'll be a time-saver, it's totally fine to build a component by hand.
Good candidates for Lona are components that may be complex visually, but have relatively simple interactions.
The welcome screen and license activation screen are both great examples, since they contain several different components within them that need to be arranged correctly.
Click and hover states are also generally pretty easy to do, so custom buttons are another great example. If I were trying to use the exact native button style, then I probably would just use the native button directly instead though.
Components that are very platform-specific should be used directly. It's probably a bad idea to recreate a text input field from scratch, since it's never going to be as polished/fully-featured/accessible as the native system one,
NSTextField. Platform-specific components like these should instead be used within larger Lona components, which can then arrange and configure them as needed. The is how the
ActivateLicense.component works — I use the system's text input fields, but I arrange and configure them in a larger Lona component.
Additionally in SourceNote, the text editor and note list didn't make sense to create in Lona. Text editors are extraordinarily complicated, so I used an open source component called Scintilla. The note list needed a variety of custom interactions, so it wouldn't have saved me any time to make it in Lona. However, I did make the individual rows in the note list using Lona:
Most of the rest of the components were built using Lona.
I usually start a new project with a pencil and a stack of post-its. After that I'll pop open Sketch and come up with a couple more detailed designs for how it might look. From there, I build the designs using Lona, but this time with much more rigor. I have to figure out exactly how the app should be broken down into components, and define how each component should behave with different input parameters and on different screen sizes. After this, I generate the UI code using the Lona compiler and start integrating it into my app.
If I want to make a major design change, I'll head back to Sketch for a bit. Sketch is really fast and I enjoy playing around with different ideas before honing in on my favorite. I focus on getting the main UI flow down, without spending too much time tweaking things to look just right. The UI always looks a little different in the real app, so I prefer to tweak font sizes and paddings when I can see them live. For this reason, I use Lona for adjusting the visuals by a few pixels here and there, testing in the real app as I go.
If you don't mind using bleeding edge software, Lona works fairly well. Today Lona supports iOS, macOS, React DOM, and React Native, so if you're working on one or more of these platforms, I think you can build a good portion of your app's components in Lona. However, it requires a decent amount of effort upfront to learn the tool, and you'll also likely run into bugs and missing features.