Oxide
Oxide is a high-performance state management library bridging Rust and Flutter, designed for cross-platform apps (Windows, Linux, macOS, iOS, Android, Web). It provides robust state handling, powerful Flutter-Rust integration, and example apps demonstrating benchmarks, persistent state, and real-time tasks.
Install / Use
/learn @Oxide-Stack/OxideREADME
Oxide
Oxide is a Rust ↔ Flutter workflow for building apps where:
- Rust owns state and business logic (reducers).
- Flutter stays UI-first and consumes typed bindings plus generated adapters.
This repository is structured so package code stays usage-agnostic, and complete runnable usage lives under examples/.
Architecture overview: docs/ARCHITECTURE.md
Acknowledgements
Oxide is powered by Flutter Rust Bridge (FRB). Huge thanks to the FRB maintainers and contributors for making Rust ↔ Dart interoperability approachable and productive.
✨ Why Oxide
- Keep business logic and state invariants in Rust.
- Stream revisioned snapshots to Flutter for reactive UI updates.
- Generate the boring wiring code (InheritedWidget / Riverpod / BLoC adapters) from a small annotation.
- Preserve a key invariant: failed reducer calls must not partially mutate live state.
🧠 Mental Model
Oxide implements a Redux-like unidirectional flow:
UI event -> Action -> dispatch(Action) -> reducer(&mut State, Action)
-> if success: state updated + revision++ + snapshot emitted
-> Flutter observes snapshot stream -> rebuilds UI
Snapshots are revisioned:
pub struct StateSnapshot<T> {
pub revision: u64,
pub state: T,
pub slices: Vec<StateSlice>,
}
🧩 Sliced Updates (Optional)
Sliced updates let Flutter stores rebuild only when specific top-level parts of state changed.
- Rust: opt in on your state with
#[state(sliced = true)]. This generates a slice enum named<StateName>Slice(for example,AppStateSlice). - Rust reducer: return
StateChange::Infer(engine infers slices by comparing top-level fields) orStateChange::Slices(&[...])(explicit slices). - Snapshots:
snapshot.slicesis empty for full updates (StateChange::Full/ legacyFullUpdate). Non-empty slices indicate which segments changed. - Flutter: use
@OxideStore(slices: [...])to filter snapshots before they hit your chosen backend (InheritedWidget/Riverpod/BLoC).
📦 Packages
Rust
- oxide_core — store/engine primitives, snapshot streams, error model, optional persistence
- oxide_generator_rs — ergonomic macros for state/actions/reducers (
#[state],#[actions],#[reducer])
Flutter
- oxide_annotations —
@OxideStore(...)annotation +OxideBackendenum - oxide_generator — build_runner generator that produces backend glue (
*.oxide.g.dart) - oxide_runtime — small runtime used by generated code (includes Riverpod helpers)
🚀 Examples (Start Here)
- counter_app — smallest end-to-end store (counter reducer + snapshot stream)
- todos_app — CRUD list state + errors + persistence
- ticker_app — periodic tick dispatch + snapshot stream into Flutter
- benchmark_app — performance comparison against Dart-only approaches
- api_browser_app — browse a JSON API with multiple reducers
🎬 Example Demos
Add your recordings under docs/media/:

📈 Benchmark Results
Full write-up and more charts: docs/BENCHMARKS.md

🧪 Quickstart (Run An Example)
From the repo root:
cd examples/counter_app
flutter pub get
dart run build_runner build -d
flutter run
If you change the Rust API surface, regenerate Flutter Rust Bridge (FRB) bindings (still from the example directory):
flutter_rust_bridge_codegen generate --config-file flutter_rust_bridge.yaml
📚 Documentation
- Usage / integration guide: docs/usage/README.md
- Contributing guide: CONTRIBUTING.md
🛠️ Development
Run Tests
- Rust crates:
cargo test(from./rust) - Flutter runtime package:
flutter test(from./flutter/oxide_runtime) - Web/WASM compatibility (Rust): see
rust/oxide_corefor target builds and test compilation instructions
Repo Scripts
The repo keeps a single VERSION file and syncs versions via scripts under tools/scripts/.
- Version sync:
tools/scripts/version_sync.ps1/tools/scripts/version_sync.sh - Tests:
tools/scripts/qa.ps1/tools/scripts/qa.sh - Builds (platform required):
tools/scripts/build.ps1 -Platform windows/tools/scripts/build.sh linux(add-NoExamples/--no-examplesto skip building examples) - Disk cleanup:
tools/scripts/clean.ps1/tools/scripts/clean.sh(add-DryRun/--dry-runto preview) - Git flow helpers:
tools/scripts/git_flow.ps1,tools/scripts/git_flow.sh
Versioning
- VERSION is the single source of truth.
- Scripts apply it to the Rust workspace, Flutter packages, and example apps.
Non-Goals (Deferred)
- Offline-first behavior
- State replay/time-travel debugging
Migration Notes
- Example apps previously named/split differently; use the current
examples/*apps as the canonical references. @OxideStore.actionssupports both enum actions and union-class actions (depending on your FRB mapping).- Rust-side persistence is feature-gated; enable
state-persistenceon the relevant crates to use it.
🤝 Contributing
Issues and PRs are welcome — especially from first-time contributors. If you’re not sure where to start, pick an example app and try adding a small feature or polishing the docs.
- Read: CONTRIBUTING.md
- Keep package code usage-agnostic; put runnable usage under
examples/ - Add or update tests when you change core behavior
📜 License
Dual-licensed under MIT OR Apache-2.0. See LICENSE.
Some packages may also include their own license file (for example, flutter/oxide_runtime/LICENSE).
