In mobile development, creating responsive and dynamic user interfaces is a fundamental challenge. Developers typically rely on various layout patterns to organize and present content effectively. However, as applications grow in complexity, there's a growing need for UIs that can adapt in real time without requiring app updates.
Key challenges include:
Dynamically reordering components
Adding new components on the fly
Changing layout or placement without releasing a new version
The Flash framework addresses these needs by leveraging JSON-based layout configurations sent from the server.
To support these dynamic capabilities and maintain a robust UI system, we introduce Inflaters. Inflaters are responsible for understanding and rendering the JSON-based layout data received from the server. They are core components in the Flash system that enable powerful layout-driven configurations, such as reordering components or adding new ones dynamically.
This document explores Inflaters in more detail.
Common layout types in mobile apps include:
Tab layouts
Stack layouts
List layouts
Scroll layouts
These help structure content and enhance user experience. However, adapting these layouts dynamically based on server data is where the real challenge lies.
Inflaters are responsible for interpreting the layout structure defined in server responses and rendering components accordingly. This allows UIs to be updated or changed remotely—without the need for app redeployment.
Flash provides several generic inflaters:
TabLayoutInflater: Renders child components as tabs
StackLayoutInflater: Renders components in a vertical stack
ListInflater: Renders components in a scrollable list (vertical, horizontal, or nested)
ScrollInflater: Renders components inside a scrollable container
These inflaters enable the Flash Client SDK to support flexible, layout-driven UIs across a variety of use cases.
As explained in the Flash Components section, every Flash-compatible component manages its own configuration. Inflaters play a key role when it comes to enabling dynamic layout capabilities, such as reordering elements or adding new ones.
Components that require any of these layout capabilities should use inflaters to interpret and apply the layout configuration provided by the server. The specific inflater used depends on the desired layout behavior.
To demonstrate this, we walk through an example of enhancing SportsListComponent
using ListInflater
, enabling it to support reordering and component insertion.
Example: Regular FlatList Component
To illustrate how inflaters work, let's look at an example of a ListInflater.
Inflaters receive a list of components from the server as part of the layout configuration. These components define the structure and content that should be rendered dynamically.
Data from existing APIs is transformed to match the format expected by inflaters. This transformation ensures that inflaters can properly associate data with each component and render them accordingly.
The style
prop applies styling to the parent container of the inflater. This enables layout-level styling while maintaining flexibility for child components.
The overrides
prop allows components to override specific layout or style properties of nested children. This adds a layer of customization on top of the default configuration.
Inflaters also support nested scrollable elements. If a child item needs to scroll (horizontally or vertically), its layout should include the appropriate configuration from the server. This enables complex nested structures—like scrollable carousels inside a vertical list.
Below is a summary of the current inflater types supported by the Flash framework:
ListInflater: Uses FlatList
to dynamically render lists of child components.
ScrollInflater: Uses ScrollView
to enable vertical or horizontal scrolling of child components.
TabInflater: Organizes child components into swipeable or clickable tabs.
StackInflater: Renders components in a vertically stacked format.
These inflaters provide the flexibility required to design dynamic, data-driven layouts with minimal hardcoding.
Components are the fundamental building blocks of the UI in Flash. They represent reusable visual elements such as Button, Text, Image, Card, etc., which are used to construct layouts and interactive screens.
To use components in Flash, they must go through specific steps: making them configurable (Flash compliant) and then registering them. This process ensures the components can respond to server-driven configuration for styling, data, and behaviour.
A component refers to a standard React (or React Native) component that is static in nature it uses hardcoded props and styles and behaves the same way every time it is rendered.
A configured component is a wrapper around such a component that makes it Flash compatible It can:
Dynamically apply styles from config
Render data passed from config
Attach configurable events and actions
This transformation allows the component to be controlled remotely through the server.
Example:
A configured component is capable of consuming server driven configuration, but it is not yet known to the Flash system until it is explicitly registered.
A registered component is a configured component that has been linked to a unique componentName using the registerComponent() method. Once registered, it becomes available for use in templates created on the Flash dashboard.
In short:
A configured component can read and apply config
A registered component is a configured component that the Flash system can recognize and render dynamically
To create a Flash template in realtime from backend, we need basic building blocks. It is not always possible to create complex templates with only building blocks which has complex ui or stateful logic. So, along with basic building blocks, we also need project specific prebaked components whose ui and logic is written in codebase. Similar to basic building blocks, we register prebaked components and make them available in the dashboard during template creation in realtime.
BaseComponent
Stateless components with no children.
Text
, Image
, Toast
BaseComponentWithChildren
Stateless, layout-like components that support children.
View
, Pressable
PreBakedComponent
Project-specific, complex components with custom logic, no children.
CardComponent
, TeamCard
PreBakedComponentWithChildren
Complex project components that also support nesting/children.
Accordion
, TabLayout
, Modal
These types allow balancing flexibility (basic blocks) with performance and logic encapsulation (prebaked).
Every UI element that is rendered in your app via Flash is described using a JSON object. This schema defines the structure, style, behavior, and children of a component — all of which are interpreted by the Flash renderer on the client side.
Let’s break down each field:
name
string
This must match the registered name of a component (via registerComponent
). Example: "FooterButtonFlash"
components
Component[]
Nested or child components, used by layout-type components like View
, ScrollView
, etc.
styles
Style
Styling config like margin, padding, color, etc., applied to the root of the component.
overrides
Overrides
Style or prop overrides targeted via nativeID
inside the component.
data
PropData
Dynamic props to control content and behavior (text, image source, backend data etc.).
dataId
string
(optional)
Can be used for fetching external data via binding systems.
Render the component registered as FooterButtonFlash
Pass data.text
to it
Style the outer wrapper with padding and background color
Override styles for inner FlashText
using nativeID="footer-button-title"
This is a union of style objects similar to React Native's StyleSheet
.
It supports keys like:
margin
, padding
, flexDirection
→ from ViewStyle
color
, fontSize
, fontWeight
→ from TextStyle
resizeMode
, tintColor
→ from ImageStyle
These styles are applied to the root of the component, unless used in overrides
.
This is the data prop passed to the component.
It's fully dynamic and recursive — it can contain primitives, objects, or arrays.
Used to drive:
Text or image content
Test IDs, flags, booleans, etc.
Props inside data
are typically used inside the component like:
Overrides allow the server to reach deep inside a component and override:
Its props
Its styles
This is possible only if that inner component uses nativeID
.
nativeID
is a identifier that says: “You can target this element with overrides.”
Example Use Case
Imagine a card component that has a title and a subtitle. You want to override the color of the subtitle only in one use case without changing the entire card component.
You can assign nativeID="card-subtitle"
and override it like:
⚠️ If
nativeID
is missing, overrides will have no effect.
To make the component configurable, the component should take configProps
. configProps
is passed as props to the component and has flash data.
Configurability refers to the ability of UI components and behaviors to be dynamically driven by server-provided configuration. In the context of Flash, configurability allows components to adapt their data, styles, and interactions based on JSON or similar config formats without requiring code changes or app updates. This includes making visual elements configurable through styling, functional behavior through events and actions, and structural flexibility through overrides.
By enabling configurability, developers can create flexible, testable, and version-aware UI experiences that are controlled remotely from the server.
Behaviour defines how UI components respond to user interactions. It consists of:
By making behavior configurable, Flash enables dynamic user flows, feature toggles, and personalized interactions—without hardcoding logic into the app.
Wrap your existing UI component in a way that allows it to consume configuration from the Flash system. This includes:
Accepting configProps for data and styles
Applying the received styles to the component’s layout
Rendering dynamic values based on the config-driven data
This wrapper ensures the component can adapt its appearance and behavior without code changes.
Once the component is made configurable, register it with the Flash system using a unique componentName. This makes it available for use in templates created via the dashboard.
Registered components must follow the expected schema and can now be referenced and configured dynamically at runtime by the server.
Events define how a component responds to user interactions (e.g., taps, changes, scrolls). In Flash, events are made configurable inside the component, and their configuration is tightly coupled with the component’s wrapper. Events are not configured separately in templates, they are defined and registered as part of making the component configurable.
If a component doesn’t use any events, this step can be skipped.
Inside the component wrapper, wire up the event handler to read from configProps.events.
Ensure the event follows the standard schema defined for that event type so that the Flash engine can interpret and execute it consistently across different components.
This enables you to pass arguments, trigger actions, and compose conditional flows all from config.
Register each event used by the component using a unique name, so the Flash system can map and handle it correctly.
If an event with the same name is already registered globally (with the same schema), re-registration is not needed.
Multiple events can be registered if the component supports more than one interaction.
Actions define the side effects or operations that occur in response to events such as navigation, API calls, logging, or custom logic. In the Flash system, actions are configured and registered independently of components and events.
Design your action to accept arguments and callbacks from config and execute the desired logic. Ensure the action supports:
Arguments from config
Optional success and failure actions
Nested execution when needed
This structure allows actions to be chained or wrapped for retry/fallback logic.
Register each action using a unique identifier via the Flash action registry. This makes the action available across all components and templates.
Since actions are decoupled from components, they can be reused across the app. The SDK uses the registered action name in the config to resolve and execute the correct logic when triggered by an event.
UI defines the visual structure and presentation of the screen. It includes such as buttons, cards, inputs, images, and layout containers. These components are configured via server-supplied data and styling properties, enabling the app to render screens dynamically while maintaining platform-specific theming and consistency.
Triggers such as onPress, onChange, or onScroll
The side effects or logic executed in response, such as navigation, API calls, or analytics