CraftD: An Ideal Solution for Server-Driven UI in Flutter Apps

Gabriel Bronzatti Moro
CodandoTV
Published in
3 min readAug 21, 2024

Many companies are embracing the Server-Driven UI pattern for its flexibility in customizing and updating user interfaces and enhancing user experiences. However, the variety of strategies developers use to implement this pattern can lead to inconsistencies and fragmented solutions. CraftD addresses this issue by offering a unified approach that ensures consistency across platforms. In this article, I will show you how to integrate CraftD into your Flutter application.

CraftD + Flutter

📚Add CraftD library

First, we need to add CraftD as a dependency to our project:

flutter pub add craftd_widget

🎯 Define your data source

Your data source could be a server, local database, or another option. In my case, I’m loading a JSON file from the assets directory:

class LocalDataSource {

Future<List<SimpleProperties>> loadProperties(BuildContext context) async {
var value = await DefaultAssetBundle.of(context)
.loadString("assets/uiElements.json");

List<dynamic> list = jsonDecode(value);
return list.map((properties) {
return SimpleProperties.fromJson(properties);
}).toList();
}
}

At the uiElements.json file, I have a JSON where I define some components:

[
{
"key": "CraftDTextView",
"value": {
"text": "Chuck Norris",
...
}
},
{
"key": "CraftDTextView",
"value": {
"text": "X",
...
}
},
{
"key": "CraftDTextView",
"value": {
"text": "Bruce Lee",
...
}
},
{
"key": "CraftDButton",
"value": {
"text": "Fight!",
...
}
}
]

Basically, we have three text elements (Chuck Norris, X, Bruce Lee) and a button labeled ‘Fight!’.

It is very important to highlight the LocalDataSource exposes the type List<SimpleProperties> .

🏗 Specify your UI Builder

In my home screen, I am creating an instance of LocalDataSource:

class _MyHomePageState extends State<MyHomePage> {
List<SimpleProperties> simplePropertiesList = [];
final LocalDataSource localDataSource = LocalDataSource();
final craftDBuilderManager = CraftDBuilderManager();

@override
void initState() {
super.initState();
...
loadProperties();
}
...

It’s crucial to create an instance of CraftDBuilderManager, as this builder will take the list of SimpleProperties from your data source and convert them into widgets. Now, let’s take a look at the loadProperties method:

void loadProperties() async {
List<SimpleProperties> properties =
await localDataSource.loadProperties(context);

setState(() {
simplePropertiesList = properties;
});
}

The loadProperties method fetch the simple properties, and update the uiState with the result. After that, the simplePropertiesList will trigger the builder definition:

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: ...
body: Center(
...
child: CraftDynamic(
simplePropertiesList: simplePropertiesList,
craftDBuilderManager: craftDBuilderManager,
onAction: (actionProperties) {
...
},
..
}

The CraftDynamic will take in both the CraftDBuilderManager and the simplePropertiesList to generate the widgets using the simplePropertiesList as input.

Screenshot of a sample app using CraftD library.

🤔 Conclusion

CraftD is an impressive library, and what I liked most about it includes:

  • Flexibility, allowing integration with various data sources;
  • Ease of use, with no need for UI layer adjustments;
  • Comprehensive documentation with well-organized examples;
  • Standardization across different frameworks (native iOS, native Android), making it easier for teams to collaborate and speak the same language.

🔗 Useful links

--

--