Documentation

Project Structure

Understanding how Whitehall projects are organized.

File Layout

myapp/
├── whitehall.toml          # Project config
├── .env                    # Environment vars (base)
├── .env.local              # Local secrets (gitignored)
├── .env.debug              # Debug overrides
├── .env.release            # Release overrides
├── src/
│   ├── main.wh             # App entry
│   ├── components/         # Reusable UI
│   ├── routes/             # File-based routing
│   │   ├── +screen.wh      # → /
│   │   ├── +layout.wh      # Root layout
│   │   ├── +screen.load.wh # Screen loader
│   │   └── user/[id]/
│   │       ├── +screen.wh  # → /user/:id
│   │       └── +screen.load.wh
│   ├── stores/             # ViewModels
│   ├── models/             # Data classes
│   ├── lib/                # Library code
│   ├── widgets/            # Home screen widgets
│   │   └── +Clock.wh       # Widget (+ prefix)
│   └── notifications/      # Notification channels
│       └── +Alerts@high.wh # Channel with priority
├── static/
│   ├── icon.png            # App icon
│   └── fixtures/           # $import files
└── build/                  # Generated output

File Naming Conventions

Screens

  • +screen.wh - Screen component
  • +layout.wh - Layout wrapper
  • +screen.load.wh - Screen data loader
  • +layout.load.wh - Layout data loader
  • +screen@.wh - Screen with no layouts
  • +screen@root.wh - Screen with only root layout

Dynamic Routes

Use [param] folders for dynamic segments:

routes/
├── user/[id]/+screen.wh     # → /user/:id
└── posts/[slug]/+screen.wh  # → /posts/:slug

Access params via $route.params.id or $screen.params.id.

Widgets

Widget files must start with + and live in src/widgets/:

src/widgets/
└── +Clock.wh       # Home screen widget

Notifications

Notification channel files use +Name@priority.wh format:

src/notifications/
├── +Alerts@high.wh    # High priority
├── +Messages@default.wh
└── +Updates@low.wh

Package Mapping

PathPackage
src/components/Foo.whapp.components.Foo
src/routes/user/[id]/+screen.whapp.routes.user.id.UserScreen
src/stores/Auth.whapp.stores.Auth
src/models/User.whapp.models.User
src/widgets/+Clock.whapp.widgets.Clock

Import Aliases

Whitehall provides convenient import aliases:

AliasExpands To
$models.Usercom.example.app.models.User
$app.stores.Xcom.example.app.stores.X
$routesRoutes object
$ffi.rust.Xcom.example.app.ffi.rust.X
$ffi.cpp.Xcom.example.app.ffi.cpp.X

Configuration

The whitehall.toml file configures your project:

[project]
name = "my-app"
version = "0.1.0"

[android]
package = "com.example.myapp"
min_sdk = 24
target_sdk = 34

[toolchain]
java = "21"
gradle = "8.4"
agp = "8.2.0"
kotlin = "2.0.0"

[dependencies]
"io.coil-kt/coil-compose" = "2.6.0"

[android.icons]
default = "static/icon-default.png"
dark = "static/icon-dark.png"

Next Steps