Crux Framework Documentation

repository·master·Indexed 25 days ago

https://github.com/redbadger/crux

A framework for building cross-platform applications by sharing a single Rust-based business logic core across iOS, Android, and Web. Crux uses a managed-effects architecture to keep the core side-effect-free and testable. It includes capabilities for HTTP (crux_http), Key-Value storage (crux_kv), and Time (crux_time), along with a typegen system to generate TypeScript, Swift, and Kotlin code for the bridge between the Core and the Shell.

Tokens
58.1K
Snippets
128
Records
320
Agent score
82%

What's inside Crux

  1. Overview of Crux Architecture

    master

    Crux is a framework for cross-platform app development using Rust. It follows an architecture similar to Elm, strictly separating pure computational logic from side effects.

    Core Components

    • Side-effect-free Core: A Rust-based shared logic layer that manages internal state and performs pure calculations. It is compiled as a static library for iOS/macOS, a dynamic library for Android, or a WebAssembly module for the web.
    • Application Shell: A platform-native layer (SwiftUI, Jetpack Compose, React, etc.) that acts as the runtime environment. It handles all non-pure tasks (side effects) and provides the UI.
    • Managed Effects: Side effects (like API calls) are captured as values by the Core and executed by the Shell. This makes the Core portable and allows for high-speed testing without mocks or stubs.
  2. Overview of the Crux Rustdoc-based type generation system

    master

    The new Crux type generation system moves away from serde-reflection and serde-generate in favor of a system based on rustdoc JSON metadata. This allows for more robust type discovery and better generated code.

    Key Advantages

    • Full Visibility: Sees all types in all used crates (including core and std) and can see macro-generated code.
    • Rich Metadata: Captures generic arguments, trait bounds, and implementors of traits.
    • Reduced Boilerplate: No longer requires a separate shared_types crate or manual registration of types; it automatically discovers entry points by finding implementations of crux_core::App.
    • Improved Output: Supports better generated code (e.g., Swift protocols), generic types, and custom code extensions.

    Execution Model

    Instead of using a build.rs file in a separate crate, type generation is provided as a standalone CLI tool (similar to uniffi-bindgen). This tool is intended to handle both type generation and FFI interface creation in a single build command.

  3. Understand Crux Capability structure

    master

    Crux capabilities define how the Core interacts with the Shell to perform side effects. Every capability follows a three-part pattern:

    1. Request struct: Instructs the Shell on how to perform the side effect on behalf of the Core.
    2. Response struct: Holds the data returned by the Shell once the side effect is complete.
    3. Convenience methods: Methods that create a Command (describing the effect and its continuation) which the Core can then 'execute'.

    Note on Naming: Because Swift lacks namespacing, ensure that Request and Response structs are named unambiguously (e.g., HttpRequest and HttpResponse) to avoid collisions.

  4. Understand the Shell's responsibilities in Crux

    master

    In a Crux application, the Shell is the platform-specific layer (UI and side-effects) that surrounds the side-effect-free core. It has two primary responsibilities:

    1. UI Layout: Rendering the components and view models provided by the core.
    2. Capability Support: Executing the side-effects (capabilities) requested by the core (e.g., HTTP requests, Key-Value storage, etc.).
  5. Understand the Weather App Architecture

    master

    The Weather App is a reference implementation of the Crux framework. It demonstrates a clean separation between business logic (written in Rust) and platform-specific UI shells (such as SwiftUI for iOS/macOS, Jetpack Compose for Android, Leptos, or Next.js for Web).

    Key architectural components include:

    • Rust Core: Contains the business logic, state machine, and model layers.
    • Application Shells: Native UI layers that communicate with the Core via a bridge.
    • Effects System: An abstraction layer that allows the Rust Core to request platform-specific actions (like HTTP calls, location access, or keychain storage) without knowing the underlying implementation.
  6. Architecture of the Notes example

    master

    The example is structured with a Crux core located in the shared directory. Key architectural components include:

    • Text Editing Events: Uses Insert, Replace, MoveCursor, Select, Backspace, and Delete events.
    • Conflict-free Data: A Note type backed by an Automerge document.
    • Custom Capabilities:
      • PubSub (implemented in capabilities/pub_sub.rs): Used for publishing and subscribing to changes. The shell implements this via the browser's BroadcastChannel API.
      • crux_kv: Used for persistent storage.
    • Timed Auto-save: Utilizes crux_time to trigger a debounced save to crux_kv after 1 second of inactivity.
  7. Understand the Counter example architecture

    master

    The shared directory in the Counter example contains the core logic implemented as a Crux core. It defines the following components:

    • Event: An enum with three variants: Increment, Decrement, and Reset.
    • Model: A state structure containing a count field.
    • Tests: Logic to ensure that Event variants update the Model correctly and produce the expected side effects.
  8. Understand the Crux documentation versioning model

    master

    The documentation site maintains two distinct versions:

    • Stable: Matches the currently published crux_core crate on crates.io. It is driven by the docs/STABLE_REF file, which contains the name of the git tag used for the build (e.g., crux_core-v0.17.0).
    • Latest (master): Tracks the master branch and reflects unreleased changes.

    Because the entire repository (including examples/) is checked out at the specific tag, all {{#include}} paths in the documentation automatically resolve against the correct version of the example code for that release.

  9. Supported platforms for Crux

    master

    Crux supports a variety of platforms for cross-platform application development. You can use Crux with the following frameworks and environments:

    • React Router: TypeScript web framework (using WebAssembly)
    • Yew: Rust web framework (using WebAssembly)
    • Dioxus: Rust web framework (using WebAssembly)
    • Tauri: Desktop or mobile applications with a web frontend and a Rust backend
    • Ratatui: Terminal User Interface (TUI) applications written in Rust
  10. Understand the Crux architecture

    master

    Crux is a cross-platform application framework that splits an application into two distinct parts to maximize code reuse and testability:

    1. Core (Rust): Contains the application's behaviour and state management. It is side-effect-free and drives the application logic in response to events.
    2. Shell (Swift, Kotlin, or TypeScript): The platform-native layer that handles presentation (UI) and effects (I/O). The Shell provides interfaces to the external world (user, network, storage, time) and acts as the runtime for the Core.

    The interface between them is a native Foreign Function Interface (FFI) using message-passing semantics with strongly typed data structures.

  11. Understand the Crux Architecture (Elm-inspired)

    master

    Crux applications follow an architecture inspired by Elm, which separates business logic from side-effect execution. The architecture consists of two main components:

    1. The Core: A portable, side-effect-free Rust component containing the application's business logic. It is driven by events and manages the application state.
    2. The Shell: A native component responsible for the 'real world' interactions. It handles:
      • Driving side: Translating user interactions (touches, typing, etc.) into Events sent to the Core.
      • Driven side: Executing Effects requested by the Core (e.g., HTTP requests, storage) and returning their outcomes back to the Core.
      • UI Rendering: Drawing the ViewModel provided by the Core onto the screen.

    This separation allows the Core to remain pure and highly testable, as it only expresses the intent to perform an effect rather than executing it directly.

  12. Initialize State and Commands using the Started pattern

    master

    When entering a new phase like Initializing, you often need to perform side effects (like fetching data) immediately. Instead of just returning a model, use a start() method that returns a Started<Self, Event> type. This pairs the initial model with the Commands required to kick off the necessary asynchronous tasks.

    Example workflow for Initializing:

    1. InitializingModel::start() returns the initial model and a set of commands (e.g., Command::all([fetch_api_key, read_kv_store])).
    2. The shell executes these commands.
    3. As commands complete, they return events that flow back into the update function.
    4. The update function checks if all required data is present (e.g., via a resolve() method) to decide whether to Continue in the current phase or Complete with a transition to Active or Onboard.