Documentation

Quick Start

Build your first Whitehall app in minutes.

Install

cargo install whitehall

Create a New Project

whitehall init myapp --app && cd myapp

Your First Component

Open src/routes/+screen.wh and replace its contents with:

var count = $state(0)

<Column class="gap-16 p-20">
  <Text fontSize={24}>Count: {count}</Text>
  <Button onClick={() => count++}>Increment</Button>
</Column>

Run It

whitehall dev

This builds your app, installs it on your connected Android device, launches it, and watches for changes.

whitehall dev is the edit loop: save a file, see the change on the device.

Understanding the Code

State

Declare a variable with $state to make it reactive:

var count = $state(0)

Behind the scenes, this becomes remember { mutableStateOf(0) } in Compose. A plain var, without $state, is a plain Kotlin variable — changing it redraws nothing.

Components

Use HTML-like syntax for Compose components:

<Column class="gap-16">
  <Text>Hello</Text>
</Column>

Event Handlers

Arrow functions work everywhere:

<Button onClick={() => count++}>Increment</Button>

Two-Way Binding

Use bind:value for form inputs:

var email = $state("")

<TextField bind:value={email} label="Email" />
<Text>You typed: {email}</Text>

Conditional Rendering

Use @if to conditionally render components:

var showPanel = $state(false)

<Button onClick={() => showPanel = !showPanel}>Toggle</Button>

@if (showPanel) {
  <Card class="p-16">
    <Text>Panel content</Text>
  </Card>
}

Lists

Use @for to iterate over arrays:

val items = ["Apple", "Banana", "Cherry"]

<LazyColumn class="gap-8">
  @for (item in items) {
    <Text>{item}</Text>
  }
</LazyColumn>

Styling with Tailwind Classes

Whitehall supports Tailwind-style utility classes for styling:

<Column class="p-16 gap-8 items-center bg-surface rounded-lg">
  <Text class="text-2xl font-bold text-primary">Welcome</Text>
  <Text class="text-sm text-secondary">Styled with Tailwind classes</Text>
</Column>

Use class="" for static values and props for dynamic values. Props override classes when both are present.

Next Steps