Core UI
Reusing the UI You Have Built
Building a UI template from Figma in Flutter is quite labor-intensive, from typography, font styles, colors, to the widgets used in the application. Typically, in personal projects, we tend to reuse interface templates we've created before to save time on app development, for example, web and app applications with nearly identical interfaces. Separating reusable interface code into a different part of the application is a clean coding method and also applies knowledge of object-oriented programming. Additionally, it can be transformed into multiple themes within your app.
Overview of Building a Core UI for an Application
Take a look at thewebsite https://wongcoupon.com/. It is built with Flutter, and I will walk you through how I structured a separate UI for my web application.

As shown in the image, I placed all UI components inside the packages directory outside the lib folder and named it web_ui_core. You can also see several other core UI packages around it, which I plan to reuse in future projects.
You might be wondering how I synchronize these packages across different projects. The answer is: I use Git to manage them. I will explain this in more detail in the article about packages.
Package
The image above shows how I implemented a UI package for this website. The same approach applies to the UI of my mobile applications.
I divide it into five main parts:
assets folder – This contains colors, SVG icons, and UI-related images. Any images unrelated to the UI are stored elsewhere. I use the flutter_gen_runner package to automatically generate asset paths in the gen folder, making them easily accessible and reducing errors. I will explain this in more detail later.
artist folder – This includes colors, SVG transformations, gradient effects, shadows, and styles for widgets. I have written a short article about switching between dark and light themes.
widget folder – This contains reusable widgets.

widget folderHere’s an example of a search input field (search_text_field) that I created. I also take screenshots of widgets for future reference, making it easier for colleagues to find and reuse components instead of rewriting them.
sub_widget folder – This holds secondary UI components such as dialogs and bottom sheets. Common dialogs include confirmation dialogs, notification dialogs, and date-time pickers.
How to Set Up a Core UI Package
From the structure outlined above, you may notice that there are quite a few directories. To manage this efficiently, I use Mason. If you're unfamiliar with Mason, check out my article here:
MasonYou can also refer to my code template and create your own, as this article does not cover some core libraries. Here is my template: dr_ui_core.
Now, I will guide you through how I set up my personal core UI package.
Step 1: Set Up the Package
The first step is to create a package that will contain the UI components you plan to add. Name it ..._ui_core so that you can easily distinguish UI core packages from other core packages. Check out my article on how I organize my packages.
Create a packages folder outside the lib directory and then run the following command:
Step 2: Add Essential Libraries
Next, add some libraries to improve code clarity and maintainability by running:
I recommend using the lint package, which helps enforce clean code practices following Effective Dart. I will cover this in more detail in my article LINK.
Step 3: Replace analysis_options.yaml
analysis_options.yamlReplace the contents of analysis_options.yaml in your package with:
This ensures that the package follows the same analysis_options.yaml as the entire project. I will share the analysis_options.yaml file I used in the project that powers this website.
Step 4: Generate the Prebuilt Code with Mason
I will use Mason to generate the code template I introduced at the beginning of this article.
Then, copy the folders inside out_site_lib into the lib folder of the package.
Step 5: Set Up flutter_gen_runner
flutter_gen_runnerflutter_gen_runner simplifies asset management and reduces errors. Run the following command:
This library makes working with assets much easier and helps minimize mistakes. Check out my article on coding faster for more details.
Tip Code FasterI have already preconfigured all the necessary settings for flutter_gen_runner in the template.
Step 6: Add the Package to Your Project
In the project's pubspec.yaml file, add:
Final Notes
After setting everything up, you may notice that a ui_core package is missing. This is a core package, but it won't cause issues if you remove it and create your own version.
I will cover the missing components in a later section. Since the ui_core library requires an in-depth explanation, I will introduce it in an upcoming article.
Explanation of Basic UI Setup
Light & Dark Mode
I have written a dedicated article on this topic, which you can find here:
Dark ModeDetails on the isDarkMode variable:
Usage:
Font Scaling
One common issue we face is that font sizes need to adjust based on screen size. For example, the font size on mobile and web differs. You can see this effect directly on this website—font sizes dynamically change depending on whether the screen is large or small.
Here’s how I handle it:
In the code above, you can see that I calculate the horizontal scaling ratio (webRatio) by dividing the current screen width by the width designed in Figma. However, I keep this ratio within the range of 0.75 to 1 to ensure that the text does not become too small when the screen size is reduced.
Additionally, I use GoogleFonts for easy font management. You can add your own custom fonts by referring to my comments in the code.
Usage Example:
You can fully customize the text style to match your design system. Here’s an example of customizing the color:
Custom Widgets
Using screen scaling ratios and Figma-based dimensions is common when designing custom widgets. Here’s an example of how I combine colors, text styles, and scaling ratios into a custom widget:
Using the Widget in the UI
For more details, check out my article on responsive screen design at here.
ResponsiveIcon
One of the indispensable parts of a UI kit is the icons. I love using SVGs because of their light weight and simplicity. If an icon is complex, I tend to prefer using PNGs over SVGs.
I use flutter_gen_runner to simplify the process of creating these icons. First, I save them in the assets folder, then configure them in the package's pubspec.yaml file as follows:
Then run this command to generate the icon paths in the gen folder:
You can find more detailed setup instructions on the library's website: https://pub.dev/packages/flutter_gen_runner
This way, using icons becomes much easier while ensuring the accuracy of the icon paths.
Change to:
This is how I implement a UI package, keeping it separate from the lib directory for easier maintenance, scalability, and cleaner code organization.
To learn more about how I synchronize packages across projects without manually copying files, check out my article on package management at here.
PackageLast updated