Introduction

In enterprise software, user interface (UI) design is not just about good looks — it’s about adaptability, consistency, and flexibility. Large organizations often have multiple brands, regional clients, or departments that require their own color schemes, logos, and typography, all under a single unified application.

To achieve this, developers need a multi-theme architecture that allows brand customization without rebuilding or redeploying the app.

In this guide, we’ll go step-by-step through building a multi-theme and brand customization system using Angular (frontend) and ASP.NET Core (backend) — ideal for enterprise-scale products.

Why Multi-Theming is Essential in Enterprise UIs

Enterprises typically manage:

Manually maintaining separate codebases for each theme is inefficient. Instead, a centralized theming system ensures:

The Importance of Theming and Branding

A scalable enterprise app needs both functional theming (colors, layout, icons) and brand theming (logos, fonts, identity).

TypePurposeExample
Functional ThemeUser preference or accessibilityDark/Light Mode
Brand ThemeClient-specific identity“Brand A” uses blue, “Brand B” uses red

A good system separates core layout logic from theme presentation, ensuring that adding a new brand is just configuration — not new development.

Common Enterprise Requirements

  1. Dynamic Light/Dark Mode Switching
    Users can toggle between modes without page reload.

  2. Multiple Brand Palettes
    Each client gets unique color, logo, and font.

  3. Runtime Theme Loading
    Theme data fetched from backend during login or context change.

  4. Brand Assets from API
    Logos, favicons, and accent colors loaded dynamically from an ASP.NET Core API.

  5. Accessibility Compliance
    All color contrasts meet WCAG 2.1 AA standards.

Architecture Overview

The high-level architecture of a multi-theme enterprise app looks like this:

+---------------------------------------------------+
|                   User Interface (Angular)         |
|---------------------------------------------------|
| - Theme Service                                   |
| - CSS Variables / SCSS Mixins                     |
| - Angular Material Palette                        |
+---------------------------------------------------+
|                 API Layer (ASP.NET Core)           |
|---------------------------------------------------|
| - Brand Configuration Controller                  |
| - Fetch theme colors, fonts, logo URLs            |
| - Serve JSON responses                            |
+---------------------------------------------------+
|                   Database Layer                   |
|---------------------------------------------------|
| - Brand table: BrandId, PrimaryColor, Font, Logo  |
+---------------------------------------------------+

Technical Flowchart: Theme Customization Workflow

        ┌─────────────────────┐
        │  User Logs In       │
        └────────┬────────────┘
                 │
                 ▼
     ┌──────────────────────────┐
     │  ASP.NET Core API loads  │
     │  brand/theme info from DB│
     └────────┬─────────────────┘
              │ (returns JSON)
              ▼
      ┌──────────────────────────┐
      │ Angular loads Theme JSON │
      │ via ThemeService         │
      └────────┬─────────────────┘
               │
               ▼
      ┌──────────────────────────┐
      │ CSS variables + logo set │
      │ dynamically via renderer │
      └──────────────────────────┘

Implementation Approaches in Angular

There are multiple ways to implement dynamic theming in Angular:

  1. Using CSS Variables (Recommended for modern Angular)

  2. Using SCSS Mixins with Angular Material Palettes

  3. Dynamic Class Injection (for older browsers)

Let’s explore a practical implementation.

Step 1: Define CSS Variables

In styles.scss:

:root {
  --primary-color: #0078d7;
  --secondary-color: #2b2b2b;
  --text-color: #222;
}

[data-theme="dark"] {
  --primary-color: #1e88e5;
  --secondary-color: #121212;
  --text-color: #fff;
}

Use these variables in components:

button {
  background-color: var(--primary-color);
  color: var(--text-color);
}

Step 2: Angular Theme Service

Create a service to manage themes dynamically.

import { Injectable, Renderer2, RendererFactory2 } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class ThemeService {
  private renderer: Renderer2;
  private currentTheme = 'light';

  constructor(rendererFactory: RendererFactory2) {
    this.renderer = rendererFactory.createRenderer(null, null);
  }

  setTheme(theme: string) {
    this.currentTheme = theme;
    this.renderer.setAttribute(document.body, 'data-theme', theme);
  }

  getTheme() {
    return this.currentTheme;
  }
}

Switching theme:

this.themeService.setTheme('dark');

Step 3: Load Brand Config from ASP.NET Core API

Backend (ASP.NET Core)

Model

public class BrandTheme
{
    public string BrandId { get; set; } = string.Empty;
    public string PrimaryColor { get; set; } = "#0078d7";
    public string SecondaryColor { get; set; } = "#2b2b2b";
    public string LogoUrl { get; set; } = string.Empty;
    public string FontFamily { get; set; } = "Roboto, sans-serif";
}

Controller

[ApiController]
[Route("api/[controller]")]
public class BrandController : ControllerBase
{
    [HttpGet("{brandId}")]
    public IActionResult GetBrandTheme(string brandId)
    {
        var theme = new BrandTheme
        {
            BrandId = brandId,
            PrimaryColor = "#1a73e8",
            SecondaryColor = "#f5f5f5",
            LogoUrl = "/assets/brandA-logo.png",
            FontFamily = "Poppins, sans-serif"
        };
        return Ok(theme);
    }
}

Frontend (Angular)

Service

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class BrandService {
  constructor(private http: HttpClient) {}

  getBrandConfig(brandId: string) {
    return this.http.get(`/api/brand/${brandId}`);
  }
}

Applying Brand at Runtime

this.brandService.getBrandConfig('BrandA').subscribe((config: any) => {
  document.documentElement.style.setProperty('--primary-color', config.primaryColor);
  document.documentElement.style.setProperty('--secondary-color', config.secondaryColor);
  document.body.style.fontFamily = config.fontFamily;
});

Step 4: Multiple Themes in Angular Material

Angular Material supports custom palettes.

theme.scss

@use '@angular/material' as mat;

$light-primary: mat.define-palette(mat.$indigo-palette, 500);
$light-accent: mat.define-palette(mat.$pink-palette, A200);

$dark-primary: mat.define-palette(mat.$blue-grey-palette, 700);
$dark-accent: mat.define-palette(mat.$deep-orange-palette, A200);

$light-theme: mat.define-light-theme((
  color: (primary: $light-primary, accent: $light-accent)
));

$dark-theme: mat.define-dark-theme((
  color: (primary: $dark-primary, accent: $dark-accent)
));

Switch dynamically

this.themeService.setTheme('dark');

Step 5: Storing Brand Info in Database

Table: BrandTheme

BrandIdPrimaryColorSecondaryColorLogoUrlFontFamily
BrandA#1a73e8#f5f5f5/assets/brandA.pngPoppins
BrandB#00695c#ffffff/assets/brandB.pngOpen Sans

You can expose an API to update these values from an admin panel — enabling runtime brand configuration without code changes.

Step 6: Accessibility and WCAG Compliance

Each theme must follow WCAG 2.1 AA guidelines.
Test for:

Tools like axe, Lighthouse, and Accessibility Insights can automate A11y testing.

Step 7: Performance Optimization

Example

APP_INITIALIZER: {
  provide: APP_INITIALIZER,
  useFactory: (brandService: BrandService) => () => brandService.loadDefaultTheme(),
  deps: [BrandService],
  multi: true
}

Step 8: Deployment and Maintenance

Example (Jenkins/GitHub Actions):

Conclusion

Multi-theme and brand customization are critical capabilities for any enterprise-grade web application.

With the right approach, developers can:

By combining Angular’s modern theming tools with ASP.NET Core’s configuration APIs, you can build a scalable and future-ready UI system that adapts to every client’s identity — all without sacrificing performance or maintainability.