diff --git a/docs/docs/recipes/23-build-types-and-flavors.md b/docs/docs/recipes/23-build-types-and-flavors.md
new file mode 100644
index 00000000..2fb22f63
--- /dev/null
+++ b/docs/docs/recipes/23-build-types-and-flavors.md
@@ -0,0 +1,157 @@
+---
+keywords: [build type, build variant, product flavor, flavors, productFlavors, installTask, installAndroidTestTask, applicationPackageId, testPackageId, moduleName, nested module, Unable to find instrumentation info]
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# Using custom build types and product flavors
+
+The Testify Gradle Plugin infers how to install and run your tests from your module's configuration. The inference assumes a `debug` build type and no product flavors. If your tests run against a custom build type, or your app has product flavors, tell the plugin which variant to use.
+
+## What the plugin infers
+
+| Setting | Inferred value |
+|---|---|
+| `installTask` | The first task, alphabetically, whose name matches `install…Debug` |
+| `installAndroidTestTask` | The first task, alphabetically, whose name matches `install…DebugAndroidTest` |
+| `applicationPackageId` | Your `applicationId`, plus the `applicationIdSuffix` of the `debug` build type |
+| `testPackageId` | The inferred `applicationPackageId` followed by `.test` |
+
+The inferred package IDs don't include a product flavor's `applicationId` or `applicationIdSuffix`. With more than one flavor, the inferred install tasks belong to whichever flavor sorts first alphabetically.
+
+When the install tasks or `testPackageId` don't match the variant you're testing, the tests fail to start. The message comes from Android rather than Testify, and you'll see an error like this:
+
+```
+INSTRUMENTATION_STATUS: Error=Unable to find instrumentation info for: ComponentInfo{com.example.app.test/androidx.test.runner.AndroidJUnitRunner}
+```
+
+When `applicationPackageId` doesn't match, the tests can still run, but `screenshotPull` and `screenshotClear` look for screenshots in the wrong app.
+
+## Configure all four settings together
+
+Setting only the install tasks isn't enough. Testify runs the tests with `adb shell am instrument` using `testPackageId`, and reads screenshots from the device using `applicationPackageId`. Set all four values for the variant you're testing.
+
+For example, for an app with a `googleMock` product flavor tested on its `debug` build type:
+
+
+
+
+```groovy
+android {
+ defaultConfig {
+ applicationId "com.example.app"
+ }
+ flavorDimensions = ["backend"]
+ productFlavors {
+ googleMock {
+ dimension "backend"
+ applicationIdSuffix ".mock"
+ }
+ }
+}
+
+testify {
+ installTask "installGoogleMockDebug"
+ installAndroidTestTask "installGoogleMockDebugAndroidTest"
+ applicationPackageId "com.example.app.mock"
+ testPackageId "com.example.app.mock.test"
+}
+```
+
+
+
+
+```kotlin
+android {
+ defaultConfig {
+ applicationId = "com.example.app"
+ }
+ flavorDimensions += "backend"
+ productFlavors {
+ create("googleMock") {
+ dimension = "backend"
+ applicationIdSuffix = ".mock"
+ }
+ }
+}
+
+testify {
+ installTask = "installGoogleMockDebug"
+ installAndroidTestTask = "installGoogleMockDebugAndroidTest"
+ applicationPackageId = "com.example.app.mock"
+ testPackageId = "com.example.app.mock.test"
+}
+```
+
+
+
+
+- **`installTask` and `installAndroidTestTask`** are task names only, such as `installGoogleMockDebug`, not task paths like `:app:installGoogleMockDebug`. The name is `install` followed by the flavor name and then the build type.
+- **`applicationPackageId`** is the application ID of the APK under test, with every flavor and build type suffix applied.
+- **`testPackageId`** is the application ID of the test APK. Unless you've set `testApplicationId`, it's `applicationPackageId` followed by `.test`.
+
+To test a custom build type instead of `debug`, set `testBuildType` in the `android` block and use that build type in the task names, for example `installStaging` and `installStagingAndroidTest`.
+
+## Check the configuration
+
+Print the settings the plugin will use:
+
+```shell-session
+$ ./gradlew app:testifySettings
+
+ …
+ installAndroidTestTask = installGoogleMockDebugAndroidTest
+ installTask = installGoogleMockDebug
+ …
+ targetPackageId = com.example.app.mock
+ testPackageId = com.example.app.mock.test
+ testRunner = androidx.test.runner.AndroidJUnitRunner
+ …
+```
+
+`testifySettings` prints `applicationPackageId` as `targetPackageId`.
+
+To see exactly which `adb` commands Testify runs, add `-Pverbose=true` to any Testify task:
+
+```shell-session
+$ ./gradlew app:screenshotTest -Pverbose=true
+```
+
+## Nested modules
+
+`screenshotTest` and `screenshotRecord` depend on the install tasks, so the APKs are installed before the tests run. The plugin looks for the install tasks at `::`, and `moduleName` defaults to the module's own name, without its parent directories. For a module nested inside another directory, such as `:feature:login`, that gives `:login:installGoogleMockDebugAndroidTest`, which doesn't exist, so the plugin skips installing without an error ([#238](https://github.com/ndtp/android-testify/issues/238)).
+
+Set `moduleName` to the module's full path, without the leading colon:
+
+
+
+
+```groovy
+testify {
+ moduleName "feature:login"
+}
+```
+
+
+
+
+```kotlin
+testify {
+ moduleName = "feature:login"
+}
+```
+
+
+
+
+The plugin then finds `:feature:login:installGoogleMockDebugAndroidTest` and installs the APKs before the tests run. Testify also uses `moduleName` in the commands it suggests in error messages, so those name the right module too.
+
+If the install tasks still aren't found, run them yourself before the tests:
+
+```shell-session
+$ ./gradlew :feature:login:installGoogleMockDebug :feature:login:installGoogleMockDebugAndroidTest
+$ ./gradlew :feature:login:screenshotTest
+```
+
+For Android library modules, see [Configuring Testify for Android Library Projects](21-library-projects.md).