white_label_kit

pub package Dart Flutter License: MIT

The modern, automated flavor & multi-tenant white-label toolkit for Flutter.

Easily manage multiple branded apps, flavors, and client tenants from a single Flutter codebase. Define all your tenants in white_label.yaml, and let white_label_kit automate Android Gradle flavors, iOS Xcode build schemes, IDE configurations, and compile-time asset isolation.


💡 Why white_label_kit?

Managing multiple flavors or white-label client apps in Flutter usually means:

  • Hand-editing complex android/app/build.gradle.kts product flavors.
  • Manually creating and wiring iOS Xcode build configurations, schemes, and bundle identifiers.
  • Risking asset leakage where one tenant's logos or credentials accidentally get bundled into another tenant's app.
  • Manually configuring IDE debug and build tasks for every new flavor.

white_label_kit automates all of this:

  • 📄 Single Source of Truth: Declare all tenants, bundle IDs, colors, API endpoints, and feature flags in one white_label.yaml.
  • 🤖 Native File Automation: Patches Android Gradle and iOS Xcode schemes automatically with dart run white_label_kit:configure.
  • 🛡️ Asset Isolation: Guarantees only the active tenant's assets and configs are compiled into the binary.
  • Interactive CLI Runner: Launch dart run white_label_kit to easily run or build APK, AAB, and iOS apps without memorizing long commands.
  • 💻 1-Click IDE Configurations: Generates ready-to-use Run/Build configurations for Android Studio, IntelliJ, and VS Code.
  • 🔒 Type-Safe Runtime API: Access tenant metadata cleanly in your Flutter widgets and services using WhiteLabelRuntime.

🚀 Getting Started

1. Add Dependency

Add white_label_kit to your Flutter project's dependenciesnot dev_dependencies:

flutter pub add white_label_kit

Or manually in pubspec.yaml:

dependencies:
  white_label_kit: ^0.0.4

Why a regular dependency, not dev-only: lib/white_label.g.dart (the generated file — see step 3) imports WhiteLabelRuntime/WhiteLabelTheme from this package and is compiled directly into your app, read by your own runtime code (whiteLabelRuntime.environment.apiBaseUrl, theme colors, feature flags, etc.). It is not purely a build-time codegen tool the way build_runner is — putting it under dev_dependencies would still happen to compile for a leaf app, but is the wrong semantic declaration for a package your shipped binary actually reads from at runtime, and would break if this package's code ever needed to reach another package that's only resolved via dependencies.

2. Initialize Configuration

Generate a starter white_label.yaml in your project root:

dart run white_label_kit:init

3. Add Your Tenants / Brands

Add a new brand with a single command:

dart run white_label_kit:add-tenant acme "Acme App" com.example.acme

This automatically creates the configuration entry in white_label.yaml and prepares the asset folder tenants/acme/.

4. Configure Android & iOS Native Files

Sync all native Gradle flavors, Xcode schemes, and IDE run configurations:

dart run white_label_kit:configure

5. Launcher Icons & Native Splash (per tenant)

Launcher/notification icons and the native splash screen are generated by two well-established, purpose-built packages — icons_launcher and flutter_native_splash — not re-modeled by white_label_kit itself.

icons_launcher is a real dependency of this package, so dart run icons_launcher:create resolves for your app with nothing added to your own pubspec.yaml. flutter_native_splash can't be a dependency of this package the same way (see maybeGenerateNativeSplash's doc comment for why). Add flutter_native_splash to your own app's pubspec.yaml (flutter pub add flutter_native_splash) if you want the splash generation below — icon generation needs no such step.

Opt-in auto-generation (recommended default): declare features: { icon_generate: true } / { splash_generate: true } for a tenant in white_label.yaml, and configure/build create icons_launcher-<id>.yaml / flutter_native_splash-<id>.yaml for you — derived from that tenant's assets.icon/assets.logo (icon) or assets.splash/assets.icon/assets.logo + theme.primary_color (splash) — only if the file doesn't already exist. Nothing to hand-author for the common case, and a file you've already customized is never touched or overwritten:

tenants:
  acme:
    features:
      icon_generate: true
      splash_generate: true

Manual (full control): skip the flags, hand-author icons_launcher-acme.yaml / flutter_native_splash-acme.yaml yourself using either package's full config reference (adaptive icon background/foreground, dark-mode variants, fullscreen, per-platform overrides, and everything else either supports), then run:

dart run icons_launcher:create --flavor acme
dart run flutter_native_splash:create --flavor acme

Both flags are off by default — a tenant that declares neither sees no change in behavior at all.


🖥️ Running & Building Your App

Launch the interactive runner:

dart run white_label_kit
╔══════════════════════════════════════════════════════════════════╗
║              ✨ WHITE_LABEL_KIT RUNNER & BUILDER                 ║
║          Automated Multi-Tenant Flutter CLI & Launcher           ║
╚══════════════════════════════════════════════════════════════════╝

📌 SELECT TENANT:
   [0] Acme App [acme] (Default)

Enter tenant number (default: acme): 0

⚡ SELECT ACTION:
   [1] ▶️  Run in Debug Mode (Simulator / Connected Device)
   [2] ⚡  Run in Release Mode (Device)
   [3] 🚀  Build Release APK (Android)
   [4] 📦  Build Release AppBundle / AAB (Google Play Store)
   [5] 🍎  Build Release iOS (Simulator / Archive)
   [6] 🔧  Configure All Tenants (white_label_kit:configure)
   [7] ➕  Add New Tenant (white_label_kit:add-tenant)
   [8] ❌  Remove Tenant (white_label_kit:remove-tenant)
   [9] 🔍  Analyze & Health Check (Flutter Analyze + Tests)
   [0] 🚪  Exit

Option B: Flutter CLI Commands

You can also run or build directly with standard Flutter commands:

# Run tenant in debug mode
flutter run --flavor acme --dart-define=TENANT_ID=acme

# Build Android Release APK
flutter build apk --release --flavor acme --dart-define=TENANT_ID=acme

# Build Android Release AppBundle (Google Play)
flutter build appbundle --release --flavor acme --dart-define=TENANT_ID=acme

# Build iOS Release App
flutter build ios --release --flavor acme --dart-define=TENANT_ID=acme

Group tenant-specific logos and platform credentials under the root tenants/ folder:

my_flutter_app/
├── white_label.yaml                # 🌟 Central configuration for all tenants
├── tenants/                        # 📂 Assets grouped per tenant
│   ├── acme/
│   │   ├── logo.png                # 🎨 App logo / icon asset
│   │   └── firebase/               # 🔒 Firebase credentials (optional)
│   │       ├── google-services.json
│   │       └── GoogleService-Info.plist
│   │
│   └── beta/
│       ├── logo.png
│       └── firebase/
│           ├── google-services.json
│           └── GoogleService-Info.plist
│
├── lib/
│   ├── main.dart
│   └── white_label.g.dart          # ⚡ Generated typed tenant constants
└── pubspec.yaml

⚙️ Configuration File (white_label.yaml)

Define all tenant properties in white_label.yaml:

white_label:
  default_tenant: acme

  tenants:
    acme:
      name: "Acme App"
      version:
        name: "1.0.0"
        build_number: 1

      android:
        application_id: "com.example.acme"
        app_name: "Acme App"
        # version:                # optional — overrides the shared
        #   name: "1.0.0"         # `version:` above for Android only, if
        #   build_number: 1       # this platform's release cadence diverges

      ios:
        bundle_id: "com.example.acme"
        app_name: "Acme App"
        # version: { ... }        # same override shape as android.version

      theme:
        primary_color: "#1E88E5"
        secondary_color: "#FFC107"
        # brand_colors: { logo_accent: "#FF0000" }    # optional, arbitrary
        # feature_colors: { courses: "#00FF00" }      # keyed hex-color maps
        # section_colors: { header: "#0000FF" }       # for apps whose UI
        # gradient_colors: { start: "#111111" }       # needs more than one
        #                                              # primary/secondary

      environment:
        api_base_url: "https://api.example.com"

      features:
        enable_push_notifications: true
        enable_downloads: true

      assets:
        logo: "tenants/acme/logo.png"
        # icon: "tenants/acme/icon.png"       # optional
        # splash: "tenants/acme/splash.png"   # optional

      firebase:
        google_services_json: "tenants/acme/firebase/google-services.json"
        google_service_info_plist: "tenants/acme/firebase/GoogleService-Info.plist"

📱 Accessing Tenant Data in Flutter (Dart)

Access your active tenant's branding, API endpoints, and feature flags anywhere in your Dart code:

dart run white_label_kit:generate compiles the current build's tenant into lib/white_label.g.dart as a single whiteLabelRuntime constant (a WhiteLabelRuntime) — never a map of every tenant, so no other tenant's data is ever compiled into a build that isn't theirs:

import 'package:flutter/material.dart';
import 'white_label.g.dart';

void main() {
  print('Tenant ID: ${whiteLabelRuntime.tenantId}');
  print('App Name: ${whiteLabelRuntime.tenantName}');
  print('API URL: ${whiteLabelRuntime.environment.apiBaseUrl}');
  print('Primary Color: ${whiteLabelRuntime.theme.primaryColorHex}');

  final hasPush = whiteLabelRuntime.isFeatureEnabled('enable_push_notifications');
  print('Push Notifications: $hasPush');

  runApp(const MyApp());
}

📖 CLI Commands Reference

Command Description
dart run white_label_kit Opens the interactive terminal runner & builder menu
dart run white_label_kit:init Creates a starter white_label.yaml file
dart run white_label_kit:configure Automatically patches Android Gradle, iOS Xcode schemes, and IDE configurations
dart run white_label_kit:add-tenant <id> "<Name>" <pkg> Adds a new tenant and creates its asset directory
dart run white_label_kit:update-tenant <id> [options] Updates tenant configuration fields
dart run white_label_kit:remove-tenant <id> [--keep-assets] Removes the tenant's entry from white_label.yaml, deletes its tenants/<id>/ asset folder (unless --keep-assets), and cleans up its generated Android Gradle flavor, iOS Xcode build configs/scheme, and IDE run configurations
dart run white_label_kit:generate [--tenant <id>] Generates lib/white_label.g.dart
dart run white_label_kit:validate Validates white_label.yaml syntax and asset paths
dart run white_label_kit:list Lists all declared tenants and the default tenant
dart run white_label_kit:doctor Performs a multi-tenant health check

🤝 Contributing

Contributions, issues, and feature requests are welcome! Feel free to check the issues page.


📄 License

This project is licensed under the MIT License — see the LICENSE file for details.

Libraries

builder
OPTIONAL, advanced alternative to dart run white_label_kit:generate (see bin/generate.dart — that's the primary, recommended path, the same way flutter_native_splash:create/icons_launcher:create work: one direct command, no build_runner involved). If your project already runs dart run build_runner build for freezed/json_serializable/ injectable_generator, this lets that same command also regenerate lib/white_label.g.dart — but it requires a build.yaml sources: override (white_label.yaml sits at the project root, outside build_runner's default lib/** scan) that generate/init do not. Both paths call the exact same generation logic (lib/src/generation/dart_config_generator.dart) — pick whichever fits your project, they produce identical output.
white_label_kit
Unified white-label build platform for Flutter apps.