White-Label Setup
Keep one shared base file in the app repo and resolve one override file per brand at
build time, with environment-specific values inside flavors.
The brand file does not need to live in the same repo. Another checkout, object storage bucket, or raw URL can provide it. The app repo stays single-source and the branded build is selected by a file path, not by forking.
Project structure
Section titled “Project structure”config/ default.jsonbuild.gradle.ktsYou can use default.yml instead if the project standardizes on YAML. The important part is that
base and override files use the same configured format.
Gradle configuration
Section titled “Gradle configuration”val brandConfigPath = providers.gradleProperty("brandConfigPath") .orElse( layout.projectDirectory .file("config/brands/wafflewizard.json") .asFile.absolutePath )
kayan { flavor.set( providers.gradleProperty("kayanFlavor") .orElse("prod") ) baseConfigFile.set( layout.projectDirectory.file("config/default.json") ) customConfigFile.set( layout.file(brandConfigPath.map { file(it) }) ) // Optional for YAML inputs: // configFormat.set(io.kayan.ConfigFormat.YAML)}Building a branded variant
Section titled “Building a branded variant”Fetch the brand override and pass it as a Gradle property:
curl -o /tmp/wafflewizard.json \ https://example.com/mobile-branding/wafflewizard.json
./gradlew generateKayanConfig \ -PbrandConfigPath=/tmp/wafflewizard.json \ -PkayanFlavor=prodOr reference a file from another local checkout:
./gradlew generateKayanConfig \ -PbrandConfigPath=../branding/bananabeacon.json \ -PkayanFlavor=stagingBy the time Kayan runs, the external override has already been materialized somewhere on disk. Kayan only sees a file path, which keeps the plugin focused on validation, merge rules, and source generation.