Skip to main content

Config Driven UI

Config-driven UI means generating an interface from configuration and data instead of manually hardcoding every section.

Config + Data

Rendering Logic

Reusable Components

Dynamic UI

One-line idea: The configuration describes what to render, while reusable components decide how it appears.

Core Concepts

The Problem with Hardcoded UI

A small interface may begin with manually repeated components:

<Card />
<Card />
<Card />

As the application grows, this approach creates problems:

  • repeated markup increases
  • layouts become harder to manage
  • changing section order requires code changes
  • customization becomes difficult
  • supporting multiple UI variations takes extra effort

Config-driven UI moves the repeated structure into data:

const sections = [
{ id: "one", type: "card" },
{ id: "two", type: "card" },
{ id: "three", type: "card" },
];

The frontend reads the configuration and renders the matching components.

What Is UI Configuration?

A UI configuration is a data structure that describes the sections of an interface.

const pageConfig = [
{
id: "hero",
type: "banner",
data: {
title: "Summer Collection",
description: "Explore the latest products",
},
},
{
id: "recommended",
type: "scrollableRow",
title: "Recommended for You",
data: recommendedProducts,
},
];

The configuration can control:

  • component type
  • content or data
  • section order
  • enabled or disabled sections
  • component variation
  • layout selection

Config and Data

Config and data have related but different jobs.

ValueResponsibility
typeSelects the component to render
dataSupplies the content displayed by that component
variantChooses a visual or behavioral variation
enabledControls whether the section is shown
Array orderControls the order of sections

Example:

{
type: "scrollableRow",
variant: "movie",
enabled: true,
data: movies
}
type     -> render ScrollableRow
variant -> use movie-style cards
enabled -> show the section
data -> display the movie items

Type-Based Rendering

The type field is the core of the rendering decision.

type = "card"          -> Card
type = "banner" -> Banner
type = "scrollableRow" -> ScrollableRow

A simple renderer can use conditional logic:

SectionRenderer.jsx
export default function SectionRenderer({ section }) {
if (section.type === "banner") {
return <Banner data={section.data} />;
}

if (section.type === "scrollableRow") {
return (
<ScrollableRow
title={section.title}
data={section.data}
variant={section.variant}
/>
);
}

if (section.type === "card") {
return <Card data={section.data} variant={section.variant} />;
}

return null;
}

Different configuration values produce different UI without manually rewriting the page.

Independence and Flexibility

When the interface depends on configuration:

  • sections can be reordered
  • layouts can change
  • sections can be enabled or disabled
  • the same component can display different data
  • one rendering system can support multiple UI variations
Fixed page structure

Configurable rendering system

More freedom to change the interface

The frontend becomes a reusable system rather than a collection of fixed pages.

Practical Config-Driven Patterns

Build a Page Renderer

The page renderer loops through the configuration and delegates each section to a section renderer.

PageRenderer.jsx
export default function PageRenderer({ config }) {
return (
<main>
{config.map((section) => (
<SectionRenderer key={section.id} section={section} />
))}
</main>
);
}
HomePage.jsx
const homePageConfig = [
{
id: "main-banner",
type: "banner",
data: {
title: "Discover New Arrivals",
description: "Fresh products selected for you",
},
},
{
id: "popular-products",
type: "scrollableRow",
title: "Popular Products",
variant: "product",
data: popularProducts,
},
];

export default function HomePage() {
return <PageRenderer config={homePageConfig} />;
}

Rendering flow:

HomePage passes config

PageRenderer reads every section

SectionRenderer checks its type

Banner or ScrollableRow renders

Use a Component Registry

As the number of section types increases, a component registry keeps the mapping in one place.

sectionRegistry.js
export const sectionRegistry = {
banner: Banner,
card: Card,
scrollableRow: ScrollableRow,
};
SectionRenderer.jsx
import { sectionRegistry } from "./sectionRegistry";

export default function SectionRenderer({ section }) {
if (section.enabled === false) {
return null;
}

const Component = sectionRegistry[section.type];

if (!Component) {
return null;
}

return <Component {...section} />;
}

The registry connects configuration types to reusable React components.

"banner"        -> Banner
"card" -> Card
"scrollableRow" -> ScrollableRow

Config-Driven Scrollable Row

A scrollable row is reusable because its content comes from configuration.

const movieRowConfig = {
id: "trending-movies",
type: "scrollableRow",
title: "Trending Movies",
variant: "movie",
data: movies,
};
ScrollableRow.jsx
export default function ScrollableRow({ title, data, variant }) {
return (
<section className="scrollable-row">
<h2>{title}</h2>

<div className="scrollable-row__items">
{data.map((item) => (
<Card key={item.id} data={item} variant={variant} />
))}
</div>
</section>
);
}

The same component can render:

  • products
  • movies
  • recommendations
  • donation cards
  • dashboard content

Only the configuration and data need to change.

Multiple UI Variations

One reusable component can support multiple presentations through a variant value.

<Card variant="movie" data={movie} />
<Card variant="product" data={product} />
<Card variant="donation" data={campaign} />

The variation can also come from configuration:

const section = {
type: "scrollableRow",
variant: "donation",
data: donationCampaigns,
};
Card.jsx
export default function Card({ data, variant }) {
return (
<article className={`card card--${variant}`}>
<img src={data.image} alt={data.title} />
<h3>{data.title}</h3>

{variant === "product" && <p>{data.price}</p>}
{variant === "movie" && <p>{data.rating}/10</p>}
{variant === "donation" && <p>{data.progress}% funded</p>}
</article>
);
}
Same component structure
+
Different variant and data

Different UI presentation

Enable or Disable Sections

Configuration can control whether a section is visible.

const pageConfig = [
{
id: "offer-banner",
type: "banner",
enabled: false,
data: offer,
},
{
id: "products",
type: "scrollableRow",
enabled: true,
data: products,
},
];

The renderer ignores disabled sections:

if (section.enabled === false) {
return null;
}

This changes the visible page without rewriting its JSX structure.

Change Section Order

When a page is rendered from an array, the array order becomes the UI order.

const firstLayout = [bannerSection, productSection, movieSection];

const secondLayout = [movieSection, bannerSection, productSection];
Config order changes

Rendered section order changes

This makes page layouts more customizable.

Data-Driven Updates

Components do not need to be manually rewritten when their content changes.

const config = {
type: "card",
data: {
title: "Old title",
},
};

When data.title changes, the same card component renders the new title.

Config changes
Data changes

React receives new props

The UI updates

Benefits, Trade-Offs and Common Mistakes

Benefits

  • reduces manually repeated page markup
  • makes section ordering flexible
  • supports reusable components and layouts
  • allows sections to be enabled or disabled
  • supports multiple visual variations
  • separates page structure from component rendering
  • makes large interfaces easier to customize

Trade-offs

Simple hardcoded UIConfig-driven UI
Direct and easy for a very small fixed pageBetter for repeated or changeable layouts
Structure is visible directly in JSXStructure is split between config and renderer
Changes require editing the pageMany changes can be made through config
Repetition grows across similar pagesReusable renderers reduce duplication

Config-driven UI is most useful when several screens share components or when content, order and variations change. A small fixed screen may not need the extra rendering layer.

Common mistakes

MistakeBetter approach
Hardcoding every repeated sectionStore repeated structure in configuration
Rendering all types in the page componentUse a dedicated section renderer
Using one component for every possible layoutCreate focused reusable components and variants
Mixing content directly into rendering conditionsKeep content in data
Ignoring unknown type valuesReturn a safe fallback or skip the section
Repeating long if chains as types growKeep type-to-component mappings in a registry
Forgetting stable keys for configured sectionsGive every section a stable id

Interview Revision

Quick Revision Checklist

  • Config-driven UI generates components from configuration and data.
  • type selects which component should render.
  • data supplies the component's content.
  • variant supports multiple presentations of a reusable component.
  • enabled can control section visibility.
  • Array order can control rendered section order.
  • A page renderer loops through the section configuration.
  • A section renderer maps each type to a component.
  • A component registry keeps type mappings organized.
  • Reusable components reduce repeated layout code.
  • The same scrollable row can display different content types.
  • Config changes and data changes produce UI changes.

Frequently Asked Interview Questions

1. What is config-driven UI?

Config-driven UI is an approach where the frontend reads configuration and data to decide which components to render instead of manually hardcoding every section of a page.

2. Why use config-driven UI?

It reduces repeated code and makes layouts, ordering, visibility and component variations easier to customize as an application grows.

3. What is the purpose of the type field?

The renderer uses type to select a component. For example, banner renders Banner, while scrollableRow renders ScrollableRow.

4. What is the difference between config and data?

Config describes the UI structure and rendering choices. Data supplies the actual content displayed inside the selected components.

5. How does a component registry help?

A registry stores the mapping between configuration types and React components in one place. The renderer can look up the correct component instead of maintaining a growing list of conditions.

6. How can one component support multiple designs?

Pass a variant through configuration. The component uses that value to select the appropriate styling or content presentation while keeping its reusable structure.

7. How can configuration control page order?

Store page sections in an array and render them with map. Reordering the array changes the order of the rendered sections.

8. When is config-driven UI most useful?

It is useful for large or customizable interfaces with repeated sections, multiple layouts, changing order, reusable rows or several variations of the same component.

9. What is the main rendering flow?

The frontend receives config and data, the renderer checks each section type, the matching reusable component receives the section data, and React produces the final UI.

Memory Trick

Describe -> Select -> Supply -> Render

Describe the page with config
Select a component using type
Supply its content through data
Render the final dynamic UI

One-Line Summary

Config-driven UI turns reusable React components into a flexible rendering system controlled by configuration and data.

Final Mental Model

Page configuration arrives

PageRenderer loops through sections

SectionRenderer reads each type

Registry selects a reusable component

Data and variant become component props

Components render the final UI