Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Mobile Development

Blinc supports building native mobile applications for both Android and iOS platforms. The same Rust UI code runs on mobile with platform-specific rendering backends (Vulkan for Android, Metal for iOS).

Cross-Platform Architecture

┌─────────────────────────────────────────────────────────────┐
│                      Your Blinc App                          │
│         (Shared Rust UI code, state, animations)             │
└─────────────────────────────┬───────────────────────────────┘
                              │
         ┌────────────────────┼────────────────────┐
         │                    │                    │
    ┌────▼────┐         ┌─────▼─────┐        ┌────▼────┐
    │ Desktop │         │  Android  │        │   iOS   │
    │ (wgpu)  │         │ (Vulkan)  │        │ (Metal) │
    └─────────┘         └───────────┘        └─────────┘

Key Features

  • Shared UI Code: Write your UI once in Rust, deploy everywhere
  • Native Performance: GPU-accelerated rendering via Vulkan/Metal
  • Touch Support: Full multi-touch gesture handling
  • Reactive State: Same reactive state system as desktop
  • Animations: Spring physics and keyframe animations work seamlessly

Supported Platforms

PlatformBackendMin VersionStatus
AndroidVulkanAPI 24 (7.0)Stable
iOSMetaliOS 15+Stable

Project Structure

A typical Blinc mobile project looks like this:

my-app/
├── Cargo.toml           # Rust dependencies
├── blinc.toml           # Blinc project config
├── src/
│   └── main.rs          # Shared UI code
├── platforms/
│   ├── android/         # Android-specific files
│   │   ├── app/
│   │   │   └── src/main/
│   │   │       ├── AndroidManifest.xml
│   │   │       └── kotlin/.../MainActivity.kt
│   │   └── build.gradle.kts
│   └── ios/             # iOS-specific files
│       ├── BlincApp/
│       │   ├── AppDelegate.swift
│       │   ├── BlincViewController.swift
│       │   └── Info.plist
│       └── BlincApp.xcodeproj/
└── build-android.sh     # Build scripts

Quick Start

1. Create a new mobile project

blinc new my-app --template rust
cd my-app

2. Write your UI

#![allow(unused)]
fn main() {
use blinc_app::prelude::*;

fn app(ctx: &mut WindowedContext) -> impl ElementBuilder {
    let count = ctx.use_state_keyed("count", || 0i32);

    div()
        .w(ctx.width)
        .h(ctx.height)
        .bg(Color::from_hex(0x1a1a2e))
        .flex_col()
        .items_center()
        .justify_center()
        .gap(20.0)
        .child(counter_display(count.clone()))
        .child(counter_button("+", count.clone(), 1))
}

fn counter_display(count: State<i32>) -> impl ElementBuilder {
    // Stateful elements with deps update incrementally when dependencies change
    stateful::<NoState>()
        .deps([count.signal_id()])
        .on_state(move |_ctx| {
            text(format!("Count: {}", count.get()))
                .size(48.0)
                .color(Color::WHITE)
        })
}

fn counter_button(label: &str, count: State<i32>, delta: i32) -> impl ElementBuilder {
    let label = label.to_string();
    stateful::<ButtonState>()
        .on_state(move |ctx| {
            let bg = match ctx.state() {
                ButtonState::Idle => Color::from_hex(0x4a4a5a),
                ButtonState::Hovered => Color::from_hex(0x5a5a6a),
                ButtonState::Pressed => Color::from_hex(0x3a3a4a),
                ButtonState::Disabled => Color::from_hex(0x2a2a2a),
            };
            div()
                .w(80.0).h(50.0)
                .rounded(8.0)
                .bg(bg)
                .items_center()
                .justify_center()
                .child(text(&label).size(24.0).color(Color::WHITE))
        })
        .on_click(move |_| count.set(count.get() + delta))
}
}

3. Build and run

# Android
blinc run android

# iOS
blinc run ios

Next Steps