Documentation

Quick Start

Build your first Whitehall app in minutes.

Create a New Project

whitehall init myapp
cd myapp

Your First Component

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

var count = 0

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

Run It

whitehall run

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

Watch mode rebuilds automatically: whitehall build --watch

Understanding the Code

State

Declare a variable with var to make it reactive:

var count = 0

Behind the scenes, this becomes remember { mutableStateOf(0) } in Compose.

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++} />

Two-Way Binding

Use bind:value for form inputs:

var email = ""

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

Conditional Rendering

Use @if to conditionally render components:

var showPanel = false

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

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

Lists

Use @for to iterate over arrays:

var 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