Configuration
Everything whitehall.toml accepts. Only the top-level keys and [screen] are required; every other table has defaults.
Top level
| Key | Meaning |
|---|---|
name | Project name. Also the source of the default app icon. |
version | App version. |
package | Application ID, e.g. com.example.myapp |
whitehall | Optional. The oldest Whitehall this project is written for — a floor, like cargo's rust-version |
name = "my-app"
version = "0.1.0"
package = "com.example.myapp"
whitehall = "0.1.3" The check runs before anything else. A compiler older than the floor stops with the version it needs and how to install it, instead of building a tree it half understands. It is a floor, not a range: a newer compiler is always fine.
[screen]
Required — no file on disk turns Gradle on. Its presence is what tells the build there is a
Compose screen at all, the way cargo's [workspace] does.
[screen]
routes = "src/routes"
tabs = ["/", "/search", "/me"] routes is where the screens live. tabs is optional: the
top-level destinations in tab-bar order. Given the order, a move to a lower index plays
the back transition instead of the forward one. Routes not in the list are unaffected. tabs belongs here; under [android] it is an error.
[android]
| Key | Default | Meaning |
|---|---|---|
min_sdk | 24 | Oldest Android supported |
target_sdk | — | API level the app targets |
compile_sdk | derived | Override only. Whitehall picks the floor the bundled AndroidX libraries need; setting it lower fails in Gradle's AAR metadata check |
icon | — | Path to a PNG. Omit for the default icon |
notification_icon | — | Status bar icon. See App Icon |
predictive_back | true | Android's back preview gesture. See Navigation Hooks |
deep_link | — | URL scheme (myapp:///…). See Deep Links |
app_link | — | An https App Link (https://example.com/…). See Deep Links |
permissions | [] | Extra manifest permissions. $permission already declares what it names |
manifest_additions | — | Raw XML spliced into AndroidManifest.xml, for what nothing else covers |
[android]
min_sdk = 24
target_sdk = 36
deep_link = "myapp"
app_link = "example.com"
[android.icons]
default = "static/icon-default.png"
dark = "static/icon-dark.png" permissions is for what cannot be inferred — permissions that follow from runtime
behavior, or that get granted out of band with pm grant. Anything $permission() names is added to the manifest for you, so there
is nothing to declare twice.[theme]
| Key | Meaning |
|---|---|
preset | "shadcn", "material3", or "none". Chooses the component library and what paints it — see Theming |
base_color | Which neutral ramp the palette is built on. "shadcn" only |
file | Path to the theme stylesheet. Defaults to theme.css beside whitehall.toml, found without being named — a web app's own app.css works as is |
mode | "light", "dark", or "auto" (default). The scheme <App> uses when nothing is bound at runtime |
font | "geist", "system", or a path to a font file |
[theme]
preset = "shadcn"
base_color = "olive"
mode = "auto" Tokens themselves live in theme.css — CSS custom properties, shadcn's own
format:
/* theme.css, beside whitehall.toml */
:root {
--radius: 0.625rem;
--primary: oklch(0.205 0 0);
}
.dark {
--primary: oklch(0.922 0 0);
} See Theming for the full token list and the radius scale.
[icons]
Icon sets, by Iconify prefix and pinned version. Only the icons a source file names are compiled in.
[icons]
lucide = "1.2.121" See Icons.
[signing]
One keystore, committed with the project, so every machine signs the same way. Written by whitehall keystore init; the password is read from the environment variable password_env names, never from the file.
[signing]
keystore = "keys/app.keystore"
alias = "myapp" See Signing.
[toolchain]
Pin the versions Whitehall downloads and builds with:
[toolchain]
java = "21"
gradle = "8.4"
agp = "8.2.0"
kotlin = "2.0.0" Omit the table entirely to track Whitehall's tested set. See CLI.
[build]
| Key | Default | Meaning |
|---|---|---|
output_dir | ".whitehall/android" | Where the generated Gradle project goes |
optimize_level | — | Release optimization level |
[env]
| Key | Meaning |
|---|---|
debug / release | Env file for each build type |
flavors | Named env files beyond debug and release |
public_prefix | The prefix that marks a variable safe to compile in. Defaults to PUBLIC_ |
[env]
debug = ".env.debug"
release = ".env.release" See $env — only prefixed variables compile into the app, and reading any other from .wh is a build error.
[wear]
[wear]
min_sdk = 30
target_sdk = 36
[wear.dependencies]
"androidx.wear.compose/compose-material" = "1.3.0" See Wear OS.
[native]
A screen's logic in Rust, C, C++ or Zig, in a sibling file (+screen.rs, an
app-scoped module under src/lib/). Renamed from the old [ffi] —
a project still carrying [ffi] is an error naming the table to rename.
| Key | Meaning |
|---|---|
abis | ABIs to build for, stated once for the whole app |
[native.rust] profile | Cargo profile for the generated crate |
[native.rust.dependencies] | Crates, copied verbatim into the generated Cargo.toml |
[native.module.<name>] | Per-module C/C++ settings, keyed by the name $native.<name> already uses: include, link, standard, flags |
[native]
abis = ["arm64-v8a"]
[native.rust]
profile = "release"
[native.rust.dependencies]
serde = "1"
[native.module.codec]
include = ["vendor/codec/include"]
link = ["z"]
standard = "c++17" A link line belongs to the module that needs it, not to every module sharing its
language — [native.module.codec] only affects $native.codec.
Dependencies
Four tables, by when the dependency is needed:
[dependencies]
"io.coil-kt/coil-compose" = "2.6.0"
[build-dependencies]
"com.google.devtools/ksp" = "2.0.0-1.0.21"
[dev-dependencies]
"io.mockk/mockk" = "1.13.9"
[android-dev-dependencies]
"androidx.test.espresso/espresso-core" = "3.5.1" | Table | Goes to |
|---|---|
dependencies | implementation |
build-dependencies | Annotation processors and Gradle plugins |
dev-dependencies | testImplementation — JVM tests |
android-dev-dependencies | androidTestImplementation — instrumented tests |
Prefer whitehall deps add over editing these by hand — it resolves the version for you.
See Also
- Project Structure
- $env — environment variables and load order
- Theming