Sitemap
Naga Sathya Bharadwaja Dandibhotla

Naga Sathya Bharadwaja Dandibhotla

How to Scale Existing Apps with a Framework-Agnostic Design System

Learn how to build and implement a framework-agnostic, tech-agnostic design system for an existing web application to future-proof your frontend architecture.

9 min readNov 2, 2026

--

Press enter or click to view image in full size
Framework approach to create Design System for an existing web application

⚡ TL;DR

A design system is often described as a collection of reusable components, design tokens, documentation, and guidelines.

That definition is correct — but incomplete.

When you inherit an existing web application, the hardest part of building a design system isn’t writing the first Button component or creating a colors.css file.

The hard part is discovering what the product already believes about design.

An existing application usually contains years of accumulated decisions:

  • slightly different shades of the same color
  • multiple spacing values
  • several button styles
  • inconsistent border radii
  • different typography treatments
  • duplicated components
  • responsive behavior that evolved organically
  • accessibility gaps
  • one-off exceptions that nobody remembers creating

Your job is not to immediately replace all of that.

Your first job is to understand it.

This article presents a technology-independent framework for transforming an existing web application into a coherent, scalable design system.

What Are We Actually Building?

Before starting, it helps to distinguish three related concepts.

Design language

The visual and emotional character of the product.

It answers:

What should this product feel like?

For example:

Warm editorial professionalism.

That might lead to:

  • strong typography
  • generous whitespace
  • dark navy structure
  • warm accent colors
  • restrained decoration
  • paper-like surfaces

Design system

The broader system of reusable design decisions, components, patterns, rules, and documentation.

It answers:

How should we consistently design and build experiences?

Component library

The implementation of reusable UI components.

It answers:

How do we encode those decisions in code?

A design system can therefore be thought of as:

Design intent + design decisions + reusable patterns + implementation + documentation + governance

The component library is only one part of it.

The Framework

For an existing application, use this sequence:

Understand
↓
Audit
↓
Inventory
↓
Find patterns
↓
Define foundations
↓
Extract tokens
↓
Establish semantics
↓
Build primitives
↓
Build components
↓
Build patterns
↓
Validate
↓
Document
↓
Govern
↓
Migrate incrementally

The important thing is the order.

Don’t start by building components.

Phase 1: Understand the Product

Before touching CSS, understand the product.

A design system exists to help a product serve its users.

So begin with three questions.

1. Who are the users?

Identify the primary users and their context.

For example, a resume website might serve:

  • recruiters
  • hiring managers
  • collaborators

An enterprise dashboard might serve:

  • administrators
  • analysts
  • operators

A consumer application might serve:

  • first-time users
  • returning users
  • power users

The answer influences your design decisions.

2. What do users need to accomplish?

Identify the primary tasks.

For example:

Resume website
→ Understand who I am
→ Scan experience
→ Evaluate skills
→ Review projects
→ Contact me

This tells you what deserves visual priority.

3. What should the experience feel like?

Choose a small number of adjectives.

For example:

  • credible
  • thoughtful
  • warm
  • focused
  • memorable

Avoid trying to make the product:

luxurious + playful + futuristic + nostalgic + utilitarian

A design direction becomes difficult to implement when it tries to communicate everything simultaneously.

Phase 2: Establish the Design Direction

Design direction translates product intent into visual language.

For example:

Warm editorial professionalism: a refined, content-first experience using expressive typography, dark structural colors, warm accents, generous whitespace, and restrained decoration.

Now translate each adjective into possible design decisions.

Adjective  -> Design Decisions
Credible -> Strong hierarchy, readable typography, restrained colors
Thoughtful -> Editorial typography, generous whitespace
Warm -> Cream surfaces, warm accent
Focused -> Clear grouping, limited decoration
Memorable -> Distinctive headings or accent treatment

This gives you a design hypothesis.

For example:

If we use editorial typography, generous spacing, dark navy structure, and a warm orange accent, the experience should feel thoughtful and credible.

That hypothesis can later be tested against the actual interface.

Phase 3: Perform a Visual Audit

Now inspect the existing application.

Do not redesign yet.

Your objective is observation.

Walk through the major pages and record what exists.

Look for:

  • typography
  • colors
  • spacing
  • buttons
  • inputs
  • cards
  • navigation
  • tables
  • dialogs
  • alerts
  • badges
  • icons
  • images
  • layouts
  • responsive behavior
  • interaction states

Think of this as archaeology.

You are discovering the design decisions that already exist.

Phase 4: Create a Visual Inventory

A visual inventory is a factual record of the current interface.

It answers:

What visual decisions exist, where are they used, and how consistently are they used?

For every significant surface, record:

  • purpose
  • size
  • spacing
  • color
  • typography
  • shape
  • layout
  • responsive behavior
  • interaction states

For example:

Surface: Card

Purpose

Groups one project, experience, or educational item.

Current implementations

.card
.profile-card
.project-card
.experience-card

Background

rgba(255, 255, 255, 0.78)

Border

1px subtle navy border

Accent

4px orange left border

Radius

18px

Padding

1.4rem 1.35rem

Shadow

0 14px 35px rgba(20, 33, 61, 0.06)

The important point is that you are recording reality.

You are not yet deciding what the values should be.

Phase 5: Identify Repetition

Repetition is where design-system opportunities begin to emerge.

Suppose your inventory reveals:

Card A → 18px radius
Card B → 18px radius
Card C → 16px radius
Card D → 18px radius

You have discovered a potential common decision.

Or:

Section A → 48px gap
Section B → 52px gap
Section C → 48px gap
Section D → 64px gap

You may discover that the application is approximately following a spacing rhythm.

The goal isn’t to force everything into a mathematical system.

The goal is to ask:

Which decisions are intentional enough and repeated enough to become system-level decisions?

Phase 6: Identify Inconsistencies

A design system shouldn’t only document consistency.

It should expose inconsistency.

For example:

Primary button
→ #E87532

Another primary button
→ #E66A27

Another CTA
→ #F0803C

Or:

Input radius → 8px
Card radius → 18px
Modal radius → 12px
Button radius → 10px

These differences might be intentional.

Or they might simply be historical accidents.

Your job is to determine which is which.

Get Naga Sathya Bharadwaja Dandibhotla’s stories in your inbox

Join Medium for free to get updates from this writer.

This is an important mindset:

Difference does not automatically mean inconsistency.

Sometimes two values are different because they represent different semantic roles.

Phase 7: Discover Relationships

Values become meaningful through relationships.

Instead of looking at:

4px
8px
12px
16px
24px
32px
48px

look for the underlying rhythm.

You might discover:

4px → 8px → 12px → 16px → 24px → 32px → 48px

That suggests a spacing system.

The same idea applies to:

Typography

12px
14px
16px
20px
24px
32px
48px

Border radius

4px
8px
12px
16px

Container widths

640px
768px
960px
1200px

You are looking for relationships rather than isolated numbers.

Phase 8: Establish Foundations

Once the inventory is understood, define the foundational design decisions.

Typical foundations include:

Color
Typography
Spacing
Sizing
Grid
Layout
Breakpoints
Border
Radius
Elevation
Motion
Iconography
Accessibility

Not every product needs every category.

Start with what the product actually needs.

Phase 9: Extract Design Tokens

Now you can begin converting repeated decisions into tokens.

For example:

:root {
--color-navy-900: ...;
--color-navy-700: ...;
--color-orange-500: ...;
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
--space-5: 1.5rem;
--space-6: 2rem;
--space-7: 3rem;
--space-8: 4rem;
}

But there is an important distinction.

A raw value describes what something is.

A semantic token describes why it exists.

For example:

--orange-500

is a raw/color token.

Whereas:

--color-action-primary

communicates its purpose.

This distinction becomes increasingly important as the system grows.

Phase 10: Separate Primitive and Semantic Tokens

A useful model is:

Primitive tokens
↓
Semantic tokens
↓
Component tokens

For example:

--color-orange-500: #...;
--color-action-primary: var(--color-orange-500);

--button-primary-background:
var(--color-action-primary);

This creates layers of abstraction.

If the brand orange changes, you can change the primitive.

If the meaning of primary action changes, you can change the semantic mapping.

If only buttons need a special treatment, you can adjust the component-level decision.

Phase 11: Define Layout Rules

Now establish the structural system.

A container might begin with:

.container {
width: min(100% - 3rem, 1120px);
margin-inline: auto;
}

But don’t blindly copy a number from another design system.

Ask:

  • How wide is the content?
  • How long should text lines be?
  • Do cards need more width?
  • How much breathing room does the design need?
  • What happens on smaller screens?

The correct container width is a design decision derived from content and layout requirements.

Phase 12: Define Responsive Behavior

Don’t start with:

mobile
tablet
desktop

Start with:

When does the design stop working?

Resize the interface.

Look for failure points:

Header becomes crowded
↓
Navigation wraps
↓
Card metadata collides
↓
Buttons become cramped
↓
Text becomes difficult to scan

The point where the layout fails is evidence for a breakpoint.

For example:

@media (max-width: 720px) {
...
}

The breakpoint is therefore derived from the interface — not from a device marketing category.

Phase 13: Build Primitives

Now begin implementation.

Start with small primitives.

Examples:

Box
Stack
Inline
Container
Text
Heading
Icon
Divider
Button
Link

The exact names don’t matter.

The principle does:

Build reusable primitives around recurring design decisions.

Phase 14: Build Components

Once primitives are stable, build higher-level components.

For example:

Button
Input
Select
Card
Badge
Alert
Navigation
Modal
Tooltip

Each component should encode:

  • structure
  • visual behavior
  • states
  • accessibility behavior
  • responsive behavior
  • token usage

A Button isn’t merely:

<button>Save</button>

It also needs to define states such as:

default
hover
focus
active
disabled
loading

Phase 15: Build Patterns

Components solve individual UI problems.

Patterns solve recurring user-interface problems.

For example:

Search + filters + results

might combine:

Input
Select
Button
Badge
Card
Pagination

into a reusable interaction pattern.

This is where a design system starts becoming more than a component library.

Phase 16: Validate Against Real Screens

Don’t validate components in isolation only.

Put them back into real pages.

Ask:

Visual

Does the interface feel coherent?

Functional

Does the component behave correctly?

Responsive

Does it survive different viewport sizes?

Accessibility

Can it be used with:

  • keyboard
  • screen readers
  • zoom
  • reduced motion
  • different contrast conditions?

Content

What happens with:

  • long names?
  • missing images?
  • large numbers?
  • translated text?
  • empty states?
  • errors?

Real content exposes weaknesses that isolated component demos often hide.

Phase 17: Document the System

Documentation should answer:

When should I use this?

Not simply:

What properties does this component have?

For a Button, document:

Purpose
When to use
When not to use
Variants
States
Accessibility
Examples
Content guidance

For tokens, explain their meaning.

For patterns, explain the user problem they solve.

Good documentation reduces decision-making effort.

Phase 18: Migrate Incrementally

Do not attempt to rewrite the entire application.

Instead:

Existing application
↓
Inventory
↓
Tokenize one area
↓
Build components
↓
Migrate one feature
↓
Validate
↓
Repeat

This reduces risk and lets the design system evolve based on real usage.

A design system that nobody uses is not a successful design system.

Phase 19: Establish Governance

Eventually, questions will arise:

Should we add another button variant?

Should this spacing value become a token?

Should we create a new component?

When is an exception justified?

You need rules.

For example:

Add a new component when

  • the interaction repeats
  • the visual behavior repeats
  • accessibility behavior needs to be standardized
  • multiple teams need the same pattern

Don’t add a component when

  • it is used once
  • abstraction makes the implementation harder
  • the differences between instances are greater than the similarities

This prevents the design system from becoming an abstraction factory.

The Complete Existing-App Workflow

The entire process can be summarized as:

1. Understand users
2. Understand product goals
3. Define design direction
4. Audit existing interfaces
5. Create visual inventory
6. Identify repetition
7. Identify inconsistencies
8. Discover relationships
9. Define foundations
10. Extract primitive tokens
11. Define semantic tokens
12. Establish layout rules
13. Establish responsive rules
14. Build primitives
15. Build components
16. Build patterns
17. Validate against real pages
18. Document
19. Migrate incrementally
20. Govern and evolve

The Most Important Principle

When building a design system for an existing application:

Don’t start by asking, “What components should I build?”

Start by asking:

“What design decisions already exist, why do they exist, and which of them should become shared decisions?”

That change in perspective is fundamental.

You’re not simply converting CSS into components.

You’re turning an accumulated collection of UI decisions into a coherent system.

The transformation is:

Existing UI
↓
Observation
↓
Inventory
↓
Patterns
↓
Design decisions
↓
Tokens
↓
Components
↓
Patterns
↓
System

And that is the real process of extracting a design system from an existing product.

--

--