# Cranpose
**Repository Path**: compose4rs/Cranpose
## Basic Information
- **Project Name**: Cranpose
- **Description**: Cranpose is a Jetpack Compose-inspired declarative Rust UI framework. https://crates.io/crates/cranpose
- **Primary Language**: Rust
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-08-14
- **Last Updated**: 2026-08-31
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Cranpose
Cranpose is a declarative UI framework for Rust, modelled on Jetpack Compose:
`#[composable]` functions, a slot-table runtime with fine-grained recomposition,
snapshot state, and a modifier-chain layout system. One Rust codebase targets
**desktop** (Linux, macOS, Windows), **Android** (including Wear OS),
**iOS**, and the **web** through WebAssembly, rendering through wgpu on all of
them.
**[Try the web demo in your browser](https://samoylenkodmitry.github.io/Cranpose/)** ·
[Releases](https://github.com/samoylenkodmitry/Cranpose/releases) ·
[crates.io](https://crates.io/crates/cranpose)
[v0.0.40.webm](https://github.com/user-attachments/assets/df50209b-abfd-426a-b79c-a51a9543b385)
> Pre-alpha. The API changes without deprecation cycles, and versions are not
> compatible with each other.
## Quick start
[`apps/isolated-demo`](apps/isolated-demo) is a complete starter project that
depends only on published crates — copy it rather than starting from scratch.
It targets desktop, Android, and the web. The workspace's comprehensive demo
(`apps/desktop-demo`) also contains the iOS entry point.
```bash
git clone https://github.com/samoylenkodmitry/cranpose.git
cd cranpose/apps/isolated-demo
cargo run --features desktop,renderer-wgpu
```
Or add the framework to an existing project:
```toml
[dependencies]
cranpose = { version = "0.1.95", features = ["desktop", "renderer-wgpu"] }
```
## Example
State, layout, and input, in the shape the framework actually has: composables
take a `Modifier`, a spec, and their content; state comes from `rememberMutableStateOf` and is
read with `.value()`.
```rust
#![allow(non_snake_case)] // #[composable] functions are CamelCase
use cranpose::prelude::*;
#[derive(Clone, PartialEq)]
struct Todo {
text: String,
done: bool,
}
#[composable]
fn TodoApp() {
let todos = rememberMutableStateOf(|| {
vec![
Todo { text: "Buy milk".into(), done: false },
Todo { text: "Walk the dog".into(), done: true },
]
});
Column(
Modifier::empty().fill_max_size().padding(24.0),
ColumnSpec::default().vertical_arrangement(LinearArrangement::spaced_by(12.0)),
move || {
Text("Todo", Modifier::empty(), TextStyle::default());
for (index, todo) in todos.value().into_iter().enumerate() {
Row(
Modifier::empty().fill_max_width().clickable(move |_| {
let mut next = todos.value();
next[index].done = !next[index].done;
todos.set(next);
}),
RowSpec::default().horizontal_arrangement(LinearArrangement::spaced_by(8.0)),
move || {
Text(
if todo.done { "[x]" } else { "[ ]" },
Modifier::empty(),
TextStyle::default(),
);
Text(todo.text.clone(), Modifier::empty(), TextStyle::default());
},
);
}
Button(
Modifier::empty().padding(10.0),
ButtonSpec::default(),
move || {
let mut next = todos.value();
let position = next.len() + 1;
next.push(Todo { text: format!("Item {position}"), done: false });
todos.set(next);
},
|| {
Text("Add", Modifier::empty(), TextStyle::default());
},
);
},
);
}
fn main() {
AppLauncher::new()
.with_title("Todo")
.with_size(420, 560)
.try_run(TodoApp)
.expect("launch the app");
}
```
A list that only composes what is on screen uses `LazyColumn` with
`rememberLazyListState()` from `cranpose_foundation::lazy` instead of the
`for` loop above.
## What is in the box
| Crate | What it is |
|---|---|
| `cranpose` | The facade apps depend on: platform runtimes, `AppLauncher`, prelude |
| `cranpose-core` | Slot table, recomposition, snapshot state, effects, coroutines |
| `cranpose-ui` / `cranpose-ui-layout` / `cranpose-ui-graphics` | Widgets, modifiers, measurement, geometry |
| `cranpose-foundation` | Gestures, pointer/rotary input, lazy lists, text buffers |
| `cranpose-animation` | Springs, tweens, transitions, `animate*AsState` |
| `cranpose-liquid` | Glass component library: iOS-26-style materials, spring motion |
| `cranpose-services` | HTTP, clipboard, share, notifications, file picker, haptics, purchases, camera, theme |
| `cranpose-audio` | Real-time audio (AAudio on Android/Wear OS, cpal on desktop) |
| `cranpose-media` | In-process media playback backing `cranpose_services::media` (symphonia, on the audio engine's device) |
| `cranpose-storekit` | StoreKit 2 in-app purchases (iOS/macOS) |
| `cranpose-testing` | The robot harness that drives real windows in tests |
The composition runtime uses a slot table: active groups live in preorder
group, payload, and node tables, and inactive retained branches are explicit
detached subtrees. The invariants it must uphold are documented in
[`docs/slot_table_invariants.md`](docs/slot_table_invariants.md); the design
history behind the current architecture is
[`docs/cranpose_slot_table_v2_design.md`](docs/cranpose_slot_table_v2_design.md)
(historical).
## Platform support
| Platform | Backend | Status |
|---|---|---|
| Linux x86_64 | Vulkan (GLES fallback opt-in) via wgpu | Supported; the GPU end-to-end suite runs here |
| macOS aarch64 | Metal via wgpu | Supported; builds, tests and `.app` bundles run in CI |
| Windows x86_64 | DX12/Vulkan via wgpu | Cross-built and released; not continuously exercised |
| Android / Wear OS | Vulkan/GLES via wgpu | Release APK build is checked in CI |
| iOS | UIKit/CAMetalLayer via `winit-uikit` | Simulator and device builds are checked in CI |
| Web (WASM) | WebGL2 (WebGPU opt-in via `?backend=webgpu`) | Demo build and Pages deploy are checked in CI |
Release binaries for the desktop platforms are attached to each
[release](https://github.com/samoylenkodmitry/Cranpose/releases).
The iOS implementation is built from `apps/desktop-demo`; the standalone
`apps/isolated-demo` template does not include an iOS target.
## Building
### Desktop (Linux/macOS/Windows)
```bash
cd apps/isolated-demo
cargo run --features desktop,renderer-wgpu
```
macOS `.app` bundles come from the workspace task runner:
```bash
cargo xtask bundle-macos \
--package desktop-app \
--bin desktop-app \
--app-name "Cranpose Demo" \
--bundle-id io.cranpose.demo
```
Pass `--resources