Theming Engine Implementation for White-Label Mobile App

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Theming Engine Implementation for White-Label Mobile App
Complex
~1-2 weeks
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Implementing Theming Engine for White-Label Mobile App

Static resources in xcconfig and flavors work when tenants known at compile-time and few in count. With 20+ tenants or runtime theme changes (seasonal sales or user selection), need dynamic Theming Engine—system applying design tokens to UI without recompile.

Design Tokens Concept

Theming Engine works with design tokens—named variables for all visual parameters: colors, fonts, sizes, corner radii, shadows. Loaded from config, applied globally.

Config structure (JSON from backend or bundled):

{
  "tenant": "brand_b",
  "version": "2",
  "colors": {
    "primary": "#1A73E8",
    "secondary": "#FB8C00",
    "background": "#FFFFFF",
    "error": "#B00020"
  },
  "typography": {
    "font_family": "Inter",
    "scale_factor": 1.0
  },
  "shape": {
    "card_corner_radius": 12,
    "button_corner_radius": 8
  }
}

Implementation on Android (Jetpack Compose)

Jetpack Compose makes dynamic theming significantly easier than XML: MaterialTheme accepts ColorScheme and Typography as parameters, applying to entire component tree.

data class TenantTheme(
    val colors: TenantColors,
    val typography: TenantTypography,
    val shapes: TenantShapes
)

@Composable
fun TenantThemedApp(
    theme: TenantTheme,
    content: @Composable () -> Unit
) {
    val colorScheme = lightColorScheme(
        primary = Color(android.graphics.Color.parseColor(theme.colors.primary)),
        secondary = Color(android.graphics.Color.parseColor(theme.colors.secondary)),
        background = Color(android.graphics.Color.parseColor(theme.colors.background))
    )

    MaterialTheme(
        colorScheme = colorScheme,
        content = content
    )
}

Usage in Activity:

setContent {
    val theme by themeViewModel.tenantTheme.collectAsState()
    TenantThemedApp(theme = theme) {
        AppNavHost()
    }
}

On tenantTheme change entire UI redraws automatically—main declarative advantage.

Runtime Font Loading

Custom brand fonts must load before first render. Downloadable Fonts API or manual via Coil:

class FontLoader(private val context: Context) {
    suspend fun loadFont(fontUrl: String): Typeface? = withContext(Dispatchers.IO) {
        val cacheFile = File(context.cacheDir, "fonts/${fontUrl.md5()}.ttf")
        if (!cacheFile.exists()) {
            downloadFont(fontUrl, cacheFile)
        }
        Typeface.createFromFile(cacheFile)
    }
}

Font cached after first load—next start reads from cache without network request.

Implementation on iOS (SwiftUI)

struct TenantTheme {
    let primary: Color
    let secondary: Color
    let background: Color
    let cardCornerRadius: CGFloat
    let buttonCornerRadius: CGFloat
    let fontFamily: String

    static let `default` = TenantTheme(
        primary: .blue,
        secondary: .orange,
        background: .white,
        cardCornerRadius: 12,
        buttonCornerRadius: 8,
        fontFamily: "SF Pro"
    )
}

struct TenantThemeKey: EnvironmentKey {
    static let defaultValue = TenantTheme.default
}

extension EnvironmentValues {
    var tenantTheme: TenantTheme {
        get { self[TenantThemeKey.self] }
        set { self[TenantThemeKey.self] = newValue }
    }
}

@main
struct MyApp: App {
    @StateObject private var themeStore = ThemeStore()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.tenantTheme, themeStore.currentTheme)
        }
    }
}

Usage in any component:

struct PrimaryButton: View {
    @Environment(\.tenantTheme) var theme
    let title: String
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            Text(title)
                .foregroundColor(.white)
                .background(theme.primary)
                .cornerRadius(theme.buttonCornerRadius)
        }
    }
}

No hardcoded colors in components—only via theme.

Runtime Theme Loading

class ThemeStore: ObservableObject {
    @Published var currentTheme: TenantTheme = .default

    func loadTheme(tenantId: String) async {
        do {
            if let cached = ThemeCache.load(tenantId: tenantId) {
                await MainActor.run { currentTheme = cached }
            }
            let dto = try await api.fetchTheme(tenantId: tenantId)
            let theme = TenantTheme(from: dto)
            ThemeCache.save(theme, tenantId: tenantId)
            await MainActor.run { currentTheme = theme }
        } catch {
            // Fallback to default, don't crash
        }
    }
}

Stale-while-revalidate pattern: show cached immediately, update in background.

React Native / Flutter

Flutter: ThemeData in MaterialApp parametrized similarly. Full control via InheritedWidget or Riverpod Provider. Runtime font loading via FontLoader API.

React Native: ThemeContext via React Context API, StyleSheet.create called with tokens. Hot-reload theme without restart via useContext(ThemeContext) in components.

Theme Versioning

Important: theme is versioned data. On contract update (new token added) old cached themes must validate:

data class ThemeDto(
    val version: Int,
    val colors: Map<String, String>
)

fun ThemeDto.toTenantTheme(): TenantTheme? {
    if (version < MIN_SUPPORTED_VERSION) return null
    return TenantTheme(
        primary = colors["primary"]?.let { Color.parseColor(it) }
            ?: return null,
    )
}

Invalid theme—fallback to bundled default, don't show broken UI.

Process

UI Audit: inventory all colors, fonts, radii. Identify hardcode.

Token Design: with designer—which params change between brands.

ThemeProvider Implementation: Environment-based application, API loading.

Component Refactoring: hardcode replacement with tokens. Visual test coverage.

Runtime Theme Switch Testing: all components redraw correctly, fonts load without flicker.

Timeline

Theming Engine for new app from scratch (Compose or SwiftUI)—2–3 weeks. Refactoring existing app with hardcoded colors—3–6 weeks depending on codebase. Cost calculated individually.