# Install the CLI
cargo install cargo-bubba
# Check your environment
cargo bubba doctor
# Create a new app
cargo bubba new my_app
cd my_app
# Build your APK
cargo bubba build
# Run on a connected device or emulator
cargo bubba runsrc/screens/home.rs
use bubba::prelude::*;
use crate::screens::profile::Profile;
pub fn Home() -> Screen {
view! {
<h1 class="title">"Welcome to Bubba"</h1>
<button class="primary-btn" onclick=alert("You tapped the button!")>
"Tap me"
</button>
<button class="link-btn" onclick=navigate(Profile)>
"Go to Profile"
</button>
<input class="text-input"
oninput=log("Typing...")
onkeypress=log("Key pressed") />
}
}src/screens/profile.rs
use bubba::prelude::*;
use crate::screens::home::Home;
pub fn Profile() -> Screen {
view! {
<img src="avatar.png" class="avatar" />
<p class="label">"Username: Alice"</p>
<button class="danger-btn" onclick=navigate(Home)>
"Log out"
</button>
}
}assets/main.css
.title { font-size: 28px; font-weight: bold; color: #1a1a2e; }
.primary-btn { background: #4CAF50; color: white; border-radius: 10px; }
.danger-btn { background: #e53935; color: white; border-radius: 10px; }
.avatar { width: 88px; height: 88px; border-radius: 44px; }A Bubba project looks like this:
my_app/
├── Cargo.toml
├── src/
│ ├── main.rs ← bubba::launch!(Home)
│ └── screens/
│ ├── mod.rs
│ ├── home.rs ← Home screen
│ └── profile.rs ← Profile screen
├── assets/
│ └── main.css ← Your CSS styles
└── android/
└── app/src/main/
└── AndroidManifest.xml
| Tag | Renders as (Android) |
|---|---|
<h1..h3> |
TextView (bold) |
<p> |
TextView |
<button> |
Button |
<input> |
EditText |
<img> |
ImageView |
<div> |
LinearLayout |
<span> |
TextView (inline) |
<a> |
TextView (link style) |
| Attribute | Fires when |
|---|---|
onclick |
Element is tapped |
oninput |
Text input changes |
onkeypress |
Key is pressed in input |
onfocus |
Element receives focus |
onblur |
Element loses focus |
onchange |
Select / checkbox changes |
// Show a native alert dialog
onclick = alert("Hello!")
// Log to Android logcat
oninput = log("User is typing")
// Navigate to another screen
onclick = navigate(Profile)
// Spawn an async task
onclick = spawn(async { fetch_data().await })# 1. Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 2. Add Android targets
rustup target add aarch64-linux-android
rustup target add x86_64-linux-android
# 3. Install Android SDK + NDK via Android Studio
# Then set environment variables:
export ANDROID_SDK_ROOT=/path/to/sdk
export ANDROID_NDK_ROOT=/path/to/ndk/26.1.xxxxxx
# 4. Install Bubba CLI
cargo install cargo-bubba
# 5. Verify everything
cargo bubba doctor| Command | Description |
|---|---|
cargo bubba new <name> |
Scaffold a new project |
cargo bubba build |
Compile to APK (debug) |
cargo bubba build --release |
Compile optimised APK |
cargo bubba run |
Build + install + launch on device |
cargo bubba doctor |
Check environment & dependencies |
cargo bubba clean |
Remove build artifacts |
Licensed under MIT OR Apache-2.0