Lukas
Hello everyone, I'm Lukas, co-founder and CEO of Widgetbook. And as Vadim already said, today I'm not mainly talking about the design system. I'm mainly going to talk about how we can simplify app development by building widgets in isolation. And first of all, I'd like to start with a question. Who in this audience already heard about Widgetbook before? Okay, great. That's basically everyone. Who already used Widgetbook before? Okay, great. Also about half. And who is using Widgetbook right now? Okay, amazing. That's quite a lot of people. Great to see. For all of you who have not yet heard or used Widgetbook before, we are building primarily an open source package. And with that, we've been featured by Google's team as experts for both component-driven development and also UI reviews. But today, what we're going to learn today is we're going to learn how we can build our widgets in isolation, how we can quickly test widgets in different states, device sizes, language, etc. So basically in all the different configurations that we could have, how we can then catalog our widgets in our own component library or design system, as Anton just talked about for 1.5, for example, and how we can then also review our UI changes in our pull request. And first of all, why is that even important? I mean, it's the last session of today and I would of course like to have you energized for the last talk today. So why is it even important? Why should you bother listening to me? I think, and most experienced developers agree with that, is we're usually striving for building reusable components. Why is that? We want to ensure that we have a consistent user experience and as developers we're also quite lazy usually so we want to avoid to build the same widget over and over again. And how are we usually doing it? We're usually doing it by building our components straight into screens and the issue is that this approach is quite error prone. And it is quite error prone because first of all, it's quite distracting for us because there are usually many surrounding widgets that are influencing my component if we put it straight into the screen. And it's also annoying that we have to design the API on the fly. And thereby, even if we are very experienced developers, it might still be the case that we add really unnecessary dependencies to our components because the surrounding widgets require them. And let's illustrate that with an example workflow. So what we see here right now is a collaborative counter app. Probably all of us know the famous counter app that is usually the Flutter example. And I mean all of us here, we are going to Flutter conference, so we really believe in the power of community. And that's the same for us always. That's why we were always bothered and that is not collaborative that's why we said okay no we want to change um this counter app and want to make it collaborative actually so what it does is um you if you're logged in in this case we would be joe if we um press the plus button in the bottom we would increase the counter but also if our friends in this case burned and emma or jeff um click the button it would also increase the counter. And first of all, what we would do is we would like to build this page and we are starting with the user avatar component that we're seeing on the top right of the screen here. And this user avatar code that you can see here, how we implement it now is it's based on a user provider dependency. That works perfectly well in this use case. So basically what we say is that when we know the user from our provider, then we show the username. And while it works for this use case, we actually have an issue now. In the end, we made an incorrect assumption here because while the top right component is for the current user, the more recent contributor can be any collaborative member of my team. So in the end, as the user avatar component is reused in the most recent contributor section of the screen, we either need to create another user avatar component now or we need to refactor it. In the end, what we discussed in the beginning, we are striving for building reusable components. So let's refactor it. What you can see here right now illustrates the problem a bit more. So you can see a diagram and this diagram shows that our user avatar component now highly depends on the user model and that user model actually gets the information from a RiverPod provider. That's really not how you should build a reusable component. Let's iterate and in our case right now here the component was changed in a way that any user right now can actually use it but it now depends on the user model. And this dependency is reflected in the user avatar class properties as well as the import statements. And while this might work now for most apps, in a design system that might be used across multiple apps, for example, the example that Anton just presented with 1,5, where over 10 teams are using the design system now, for them, it would really not work really well. Because in the end, the design system should really not be aware of any data dependency, because the focus should be about isolated components, not data. And that's the diagram here now. So right now we see that the user component doesn't depend on a RiverPod provider anymore, but it still depends on the user model. And what we do now is we want to reduce the dependencies even further to make the component even more reusable. And right now we reflected it in a way that it no longer depends on any provider or any data model. Right now it just depends on plain string inputs. That's exactly how you should write it. And here you can see the diagram now. Perfect, right? It's very simple. It's reusable by any app. In the end, it's fully isolated from any data or logic or data elements. So that's exactly how you should write it. And here we can now see the comparison. So before we had, first of all, a Riverpod dependency, then we had the user model dependency. And right now we don't have any dependencies anymore. And the question is, how can we basically simplify this process? What we usually see with a lot of experienced developers, they solve it intuitively by building a sandbox or a debug page for themselves. And that allows them to build their widgets in isolation without having any distraction. However, building such a sandbox is quite time consuming and distracting because in the end, usually as developers, what we should do is we should focus on building a great experience for our users and to not optimizing our own processes. That's really something that we should usually not do with our times. We should really strive for building the best experience for our users as possible and really focus on that. And to give you a solution that you can really focus on your customer experience and not having to optimize your own processes too much, we built Widgetbook. I have a question for this audience again. Who in this room comes from a web development background? Okay, a few. Who have you already used Storybook.js in the past? Okay, quite some people. And in the end, that's exactly the journey that we took as a team. So we are coming from a web development background as well and always use Storybook.js. When we then fortunately made the switch to Flutter, eventually there was no storybook solution out there. That's why we built it ourselves. And that's why you can say widget book is the storybook for Flutter or simple put, it's the environment for you to build your widgets in isolation. And let's check how we can set it up. So what you would do is in your Flutter app, you would create a new folder, a new widget book folder on the same level as your lib folder. So don't put it in your lib folder because all we want to do is we want to have a new separate Flutter app inside your Flutter app. And what we then have, we have a pubspec.yaml file in our widget book folder. And in here, we are then including our widget book dependencies. And what we need is, first of all, our main widget book dependency, then widget book annotation, and then widget book generator. And as the name already suggests, we have an annotation-based code generator. It works very similar to Freeest. And in this case, what you can do then in your new main.dart file inside your widget book, folder you just use the @app annotation and this @app annotation will generate the entire widgetbook UI for you out of the box and then you're returning your widgetbook that's all you got to do and then the widgetbook is being generated now the actual challenge was we want to build reusable components so how do we do it and we're doing it by first of all providing the boilerplate widget and what we do here is and we just have our we just write our user avatar and for now we are only returning a placeholder and afterwards we are cataloging that widget in widget book so that we are able to preview it in widget book. And what we're doing here is we're using an add use case annotation. So whenever using an add use case annotation, you're telling WidgetBook, perfect, I want to include this very widget in WidgetBook. We need a name, the name in this case, because we in this case say we only have one use case, so we only just call it default. And we could, however, add multiple use cases for the same widgets. And then we provide the type. That's just the widget that we'd like to preview in WidgetBook. So in this case, user avatar. Then we have a method and afterwards we are just returning the widget that we'd like to preview. In this case, user avatar. And in our case, we wrap it with the center widget so that it appears in the center of the screen. Writing this only takes us 10 seconds, so it's barely any additional effort. And what you end up with for now is that. So you will already see the widget book UI. And on the left side, we can already see our user avatar was added. But no worries for now. And we only have an X here because we just added a placeholder. And let's make sure to change that. Let's make sure to actually preview our component here. So what we then do is we implement the widget. And I mean, we just learned how to build reusable components. So we're just following exactly that best practice of basically not including any dependencies in there. And the next step would be we need to extend our use case now. And we need to do it because before our user avatar was parameterless, but now it requires two parameters. And therefore, we have to provide those two parameters for the use case so that Flutter is able to render it out properly. And in our case, we just provided a string for the name John Doe. And for the photo URL, we are now using an image from the local file system, which just makes it easier to fill with mock data than fetching images, for example, from a CDN. And the amazing thing right now is that since the widget book use case only depends on Flutter, the component itself and widget book, at this point in time, it's really impossible to make bad decisions. So you're building isolation by default. It would be really, really hard and you have to make consciously a super bad decision to put dependencies in here. So Widgetbook really allows you to follow best practices consistently and always make sure that you are building your component in a reusable way. And that's how it looks then in widget book after you let the build runner run again and therefore update your widget book. So you can see our component is properly rendered out and on the right side we can see knobs and add-ons. And those knobs and add-ons allow us to test our widgets in further details. Let's first of all check out knobs. And our knobs allow us to dynamically override any parameter in the UI. In our case right now, what we're doing is for the name, while we beforehand just provided the mock data straight away, what we now do is we write context.knob.datatype, in our case string. to be able to dynamically overwrite this name later in the UI. And for the photo URL, we're doing the same, but right now we're using another data type. So we're not using string, we're using string or null. So what that does right now is that if the photo URL is null, the component dynamically changes. And instead of the picture that we previously saw, we will see a circle with the first letter of the first name. So let's check it out. And we have a video here. And what we can see now is that we can dynamically overwrite the name from John Doe to Jeff Jefferson, for example. So we have a longer name and we see it still looks good. And for the photo URL as well. So we are able to quickly toggle it to check the different states. And besides the knobs, we also have add-ons. And our add-ons allow us to automatically check not widget-specific parameters, but global parameters of our app. So that we can, for example, test our apps in different device sizes, different themes, different languages, different text scale factors, and much more. The great thing about building Widgetbook as an open source package is that by now we are used by over or we used by a few thousand companies around the globe. And some of them also help us to maintain the package and contribute back to the package. So there are a lot of add-ons that you can actually explore and try. In this small demo app, we are focusing on our viewport add-on and on our theme add-on to test the widgets in different device sizes and also on different themes. And these are all the code lines that you have to add in order to be able to test your widgets either on, for example, an iPhone 12 or an iPad device or on no device frame whatsoever. And you can also automatically test your widgets very quickly in different themes, for example, light or dark mode. Okay, great. We now got it for components. But how about entire screens? Can I actually add entire screens to widget book? The answer is yes, you can. And I would also say yes, you should. And let's check out why. First of all, how do we build that screen? That's the code right now, and I won't go into too many details, but first of all, this screen right now depends on our design system, and thereby it reuses the user avatar. Then we get our data from providers and fill our components here with information. And this whole screen is the only component that has dependencies on providers, which you can see on the next screen. So these are the providers right now. And afterwards you would build the use case again. And in our case, we don't have a provider scope in the widget tree. And that's why we inject it in the use case. And to avoid fetching data from our database, we use mock providers. And the current user provider has a hard-coded user. And because of that, it's impossible to access this screen without being logged in. And for the user's provider, we're using a fixed list of data. And we build a custom knob for this provider to switch between the different states of the screen. And let's check it in action. So we now have our knob and we first of all check the loading state here. Afterwards, we can also quickly switch to seeing the error state. And after that, we can check our data state. And here we can see all the fake data that we just provided. And it works exactly as we anticipated. We as John Doe are adding to the counter and therefore the counter for John Doe increases and also the overall the overarching counter also increases. So this really helps you to build your components in isolation and quickly test your widgets and all the different configurations. And as a side benefit, you are now receiving a catalog. So as a side benefit, all the widgets that you are building with WidgetBook, are being reused here. So you have the chance to basically scroll around the entire catalog. In our case, because we only have this very simple demo app, there's not much added here. But if you imagine, Anton just mentioned, they are using over or about 100 components or 100 variations. It's going to be a really extensive catalog that you can browse that allows you and your team to always keep the overview of everything that you've been building. And therefore, the benefits of the free-to-use and open source widget book are that you can build all of your widgets in isolation. You can quickly test your widgets in all the different use cases. And all of your widgets will definitely be decoupled from business logic and also from data. And all your widgets are automatically cataloged in your own component library. And if you'd like to get started with Widgetbook in the open source package, you can just check out docs.widgetbook.io and try it for free, it's open source. And it's not over yet because I promised you something initially, I promised you that we can also quickly review all of our changes. And that's why Widgetbook in the end is not only a powerful tool for creating new components or screens, but also for changing existing ones. And as we can see all of our widgets in Widgetbook's catalog so easily, we have a great overview of our existing widgets in all of the different configurations. And therefore, we are able to also very quickly see all new changes. And let's check an example workflow. So in our case, what we want to do is we want to change our user avatar. And the issue usually is for us developers, when we're changing a component on some page of our app, the question is, what are all the parts of our app that are affected by it? And maybe we know all of our pages by heart and everything works well, but the moment you are working together with at least one other developer, it already gets quite complicated and you might already run into an issue, have UI flaws that either the QA team has to find out later, or you might even run into the issue of shipping a UI flaw to your customers. And here again, experienced developers already have a solution for that. In Flutter, it's called golden tests. But the issue with golden tests are that first of all, you have to write them manually. Then the issue is that golden tests are quite flaky, depending on the operating systems that you're using. I see a lot of nodding here. So that's usually a big issue. Then another issue is that we always check our golden files into our repository and therefore it clutters the repository. The fourth reason why it's an issue for us is that very often we have the problem that we need to review our failed goldens. And reviewing failed goldens can also be quite cumbersome. and that's why we built widgetbook cloud with widgetbook cloud we allow you to easily review all of your ui changes and now i'd like to um give you a live demo um of a workflow here so we are right now in um a repository um of of ours and it's actually in this case not the right one here we are in the uh in the right um repository um and and that's the repository of our collaborative counter app and what we would usually do right now is um if we make the change that we just discussed we would um create a new pull request in draft mode and afterwards you would commit our changes all of that is already done no worries I'm not going to bore you with that and so we already have the pull request here right now and And kindly enough, my co-founder Jens took care of it. And he wrote a comment about the change that he wanted to make. So he said that he's changing the visual appearance of the user avatar to look less like a chip. And I mean, all of us are familiar with Git tools and of the amazing files change tab. And that allows us as developers always to see exactly what code change do we do. And in this case, we can see. Jens promised something and delivered, he changed the chip. But the question that we have now is, how does this change look visually? That is something that Git can't help us with, but it would be amazing to actually see the change here right now visually. And that's why we built Widgetbook Cloud and are well integrated in your Git providers. What I'm showing you right now works for GitHub, but it also works for all the other major Git providers. So you can also use it for GitLab, Azure DevOps, and also for Bitbucket. And you see here right now, we have a few Widgetbook checks. The first one is the widget book build. That is just the hosted overview of widget book. But what's more exciting is our widget book review check. And this widget book review check is right now pending. And it is pending because we are automatically always analyzing your pull request and are checking for visual regressions or UI changes. in this pull request. And whenever we are finding a UI change, this check remains pending. And then you are not able to merge this pull request right now. You basically have to first of all, make sure to accept all the changes. And that is how it looks like. So you see here on the left side, that's how our user avatar looked before. On the right side, we see how it looks right now. And if you remember correctly, we said we do not only want to include our components in Widgetbook, but also entire screens. That's how we can basically check all the different areas of our app that were affected by this change. In our case, that's why our home screen was also affected. by the change. So we can now also see that's how the home screen looked before and that's how the home screen looks right now. And we always have the chance if we are not really sure what changed right now to use our toggle diff button to highlight for us exactly in pink what is the exact spot of our button in this case that was changed. Additionally, we are not only able to basically compare two screenshots with each other like here, we are also always able to check the interactions afterwards. So we can also always immediately from our review feature jump into the latest widget book build to then explore the widget and further configurations. And I mean, what we already just tested is, we saw how we can use the knobs and add-ons. So in the end, what is happening here, it's a Flutter web build that you can see. And you could then see, for example, not only how my widget looks in a dark mode, but also how my widget looks in light mode. And we have another feature that is called multi snapshot reviews. So we do not only have the chance to manually checking our widgets on the different add-ons, we can automatically test it. And it is actually quite easy to configure. So we recall that. we had our ad app annotation initially that allowed us to generate our widget book in the beginning and with this ad app annotation we then have the chance to configure um theming here or in the end any other add-on that you'd like to automatically test we with our demo app decided we want to automatically test all of our visual changes on light and dark mode but you could also test different device sizes different languages different text scale factors any add-on basically and let's see how that works in more detail. So here in WidgetBook we see basically now the change in dark mode right now. Here's the exact same change in light mode. Here's it again in dark mode for the screen and in light mode. And if we as a developer are happy with our change and therefore know, okay, perfect, there's no unintended change that we have. What we can do is we can go to review changes, approve, and then submit the review. And it will automatically be merged again with GitHub. And therefore, we are able to merge our pull request with Confidence. And that is the workflow that I described if you are reviewing the change yourself. Of course, you can use it together with your team. I mean, Anton was all about collaboration and communication beforehand. And that's why you can, of course, use Widgetbook to collaborate better among developers. So I could, for example, easily review changes of my teammates. Or I could also bring in design or also QA very early. and how teams are using that with Widgetbook. I'd like to give you a few testimonials of our customer groups here. So in the end, Widgetbook is being used by all sorts of different Flutter teams. So we're working together with indie developers, impressive one person armies that are building an entire app and they are building their components quicker with Widgetbook. So it reduces the development time and they also are able to quickly review exactly their changes. Then we're working together with small teams who are building just one app. And they, for example, found out that their UI reviews were simplified drastically. Then we're working together with Schlatter teams that are building multiple apps with the same design system. Teams like Anton with 1,5 or also Salto Cloud Systems, which found out that their workflow became twice as fast. Also working together with one of the largest Flutter teams around the world, they have over 120 Flutter developers, over 50 UX people, 30 QA people on Widgetbook, and it allowed them to build a more maintainable app. They are able to catch all their regressions early in the pull request, and they can then also collaborate a lot earlier with their developers, designers, and also with QA. And with that, if you'd like to get started with Virtual Cloud also, if you'd like to try it, you can do it for free. You can just sign up on our website and get started. Looking forward to your questions. Thanks a lot.
Vadym
Yes, we have quite some questions, so I'll probably ask a few of them, but is there a plan to create a widget preview in IDE? like Jetpack Compose did?
Lukas
Yeah, so it's a great question and we actually had a spike implementation of that already for VS Code. So it's something that is on the roadmap, but honestly I have to say it's not the biggest priority for us right now. So what we basically wanted to find out is, is it technically feasible for us? The answer is yes. And now we are basically prioritizing the roadmap and that's why it's coming eventually. But to be honest, it's not the highest priority for us.
Vadym
Okay, that's it. When will be there more AI in the widget book? AI, AI, AI.
Lukas
Yeah, so that is, of course, the question of the day currently. I mean, everyone is talking about AI and there are actually a few things that we can do with AI. One thing that I'm quite excited about is to enable large existing apps. that already, where basically their design system is already set, but they would like to use Widgetbook, I would like to be able to automatically generate the use cases for them so that they do not need to manually migrate to Widgetbook. And that is something where today already, if you're using any AI-first IDE like Windsurf or Cursor, they can already do it for you. With VS Code, It's a bit more complex, but our friends from LeanCode built a use case generator extension for VS Code, for example. And other features are, of course, our entire review journey that we do. could simplify even more. I mean, what I haven't touched upon with my presentation is we also have a Figma integration that allows you to not only see how does my Flutter widget look before, how does my Flutter widget looks now, but also how does it compare to the Figma design. And I mean, I don't wanna promise too much for now, but we're definitely looking into automating that process as well.
Vadym
And the question was pretty simple. And you're like giving another talk. Yeah, anyway, thank you. Is Widgetbook cloud free?
Lukas
Yeah, so we have a free tier that you can try it with. So we have a usage-based pricing model. You can bring as many users as you like. In the end, we're only charging for the value that we're providing. And up to 1,000 snapshots a month are free. So it's definitely enough for you to try it. If you're a very small team yet and just getting started with using Widgetbook, You can even continuously use it over a few weeks or even months with that. But usually for more professional teams, eventually you run out of your snapshots and then upgrade to our paid plans.
Vadym
It's a different question of different shape, but yeah, I will ask this one. How we could use Widget Cloud with Azure?
Lukas
It's actually quite straightforward. So in our documentation, we basically highlight how you can use Widget Book with all different Git providers. I mean, I just showed you how it can be used with GitHub and we have exact feature parity with Azure. To give you maybe a bit more details here, what you're doing in the end is you are including Widgetbook in your CI/CD pipeline. And afterwards you are installing our Widgetbook app from, in this case, it was on the GitHub marketplace. With Azure, it's from the Azure marketplace. And then it's just like, I think, a two-click installation and you're done.
Vadym
Yeah, that's good. And one thing, you're the last speaker, right? Yeah, now thank you very much for your talk. Please round of applause to Lukas. But you're not leaving. Thank you.