Flutter SDK App Features
App Features let you customize application behavior remotely, without releasing a new version — flip a flag, tune a number, or ship a small config blob, and every client picks it up the next time its config reloads.
magify_flutter_sdk exposes two independent flag sets from the loaded config:
MagifyClient.instance.features and MagifyClient.instance.storedFeatures. Both share the same
getter shape; they differ in where the values come from.
Value features — features
MagifyFeatures get features reads flags whose values live directly in the config. Reads are
immediate — no network round trip.
A typed getter (string, boolean, integer, number, dictionary) answers null both
when the key is missing and when it holds a different type; json shows the value exactly as
stored — a quoted string, a bare number, an object.
final isNewOnboardingEnabled = await MagifyClient.instance.features.boolean('new_onboarding');
final maxRetries = await MagifyClient.instance.features.integer('max_retries');
MagifyClient.instance.features.updates.listen((_) async {
final refreshed = await MagifyClient.instance.features.boolean('new_onboarding');
});
Stored features — storedFeatures
MagifyStoredFeatures get storedFeatures is a second, separate flag set. Instead of holding
the value directly, the config names a file; the SDK downloads it, caches it on disk, and the
feature's value is the JSON content of that file. It exposes the same getters as features,
but a read may go to the network.
Cold start
A stored feature's value isn't necessarily readable the moment a config arrives — the file
still has to download and get cached on disk first, and a read may answer null until that
finishes. This is why updates is the reliable trigger to re-read from, rather than a
single read at startup.
A non-JSON payload (an image, an archive) resolves to null — stored features are only
exposed as decoded JSON values.
MagifyClient.instance.storedFeatures.updates.listen((_) async {
final banner = await MagifyClient.instance.storedFeatures.dictionary('home_banner');
if (banner != null) {
// update UI with the newly downloaded banner config
}
});
Next step
Continue to Content for server-driven content items.