Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Augani/kael/llms.txt

Use this file to discover all available pages before exploring further.

The Application type is your entry point into Kael. You construct it once in main, configure it with assets and an HTTP client, then call .run() to hand control to the platform event loop. Inside the run callback — and anywhere you hold a &mut App — you can open windows, manage type-keyed global state, register lifecycle observers, and spawn background tasks.

Application

Application is a thin wrapper around an Rc<AppCell>. You interact with it only during initial setup; all ongoing work happens through App.
use kael::{Application, App};

fn main() {
    Application::new().run(|cx: &mut App| {
        // cx is available for the lifetime of the application
    });
}

Constructors

Application::new
() -> Application
Creates a standard GUI application using the current platform backend. Assets default to an empty source and the HTTP client is a no-op stub. Prefer this in all normal cases.
Application::headless
() -> Application
Creates an application that will not open any windows. Useful for running Kael in SSH sessions or server contexts where a display is unavailable.

Builder methods

These methods return &Self so they can be chained before calling .run().
Application::new()
    .with_assets(MyAssets)
    .with_http_client(Arc::new(my_client))
    .on_open_url(|url, cx| { /* ... */ })
    .run(|cx| { /* ... */ });
.with_assets
(impl AssetSource) -> Self
Registers a custom asset source used for loading images, SVGs, and other bundled resources.
.with_http_client
(Arc<dyn HttpClient>) -> Self
Replaces the default no-op HTTP client with a real implementation. Required for any code that makes network requests through Kael’s HTTP layer.
.on_open_urls
(FnMut(Vec<String>)) -> &Self
Registers a handler that fires when the platform asks the application to open one or more URLs in bulk.
.on_open_url
(FnMut(String, &mut App)) -> &Self
Registers a handler that fires once per URL when the platform asks the application to open it.
Registers a handler scoped to a specific URL scheme (e.g. "myapp"). Only URLs whose scheme matches will invoke this handler.
.on_reopen
(FnMut(&mut App)) -> &Self
Invoked when an already-running application is relaunched, for example by double-clicking its dock icon on macOS. Commonly used to re-open the main window.

Starting the application

pub fn run<F>(self, on_finish_launching: F)
where
    F: 'static + FnOnce(&mut App),
run blocks until the application quits. The callback receives a &mut App and is called exactly once, after the platform’s event loop is ready. This is where you open your first window.
Application::new().run(|cx: &mut App| {
    cx.open_window(WindowOptions::default(), |_, cx| {
        cx.new(|_| MyRootView)
    }).unwrap();
});

App

App is the authoritative owner of all entity state, windows, and globals. You receive a &mut App inside .run() and in every event and observer callback.

Opening windows

pub fn open_window<V: 'static + Render>(
    &mut self,
    options: WindowOptions,
    build_root_view: impl FnOnce(&mut Window, &mut App) -> Entity<V>,
) -> anyhow::Result<WindowHandle<V>>
Opens a platform window with the given options. The closure receives a &mut Window and &mut App and must return an Entity<V> that becomes the root view. The window draws at least one frame before open_window returns.
let handle = cx.open_window(WindowOptions {
    focus: true,
    show: true,
    ..Default::default()
}, |_window, cx| {
    cx.new(|_| MyView::new())
})?;

Reading and updating windows

// AppContext trait
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
where
    F: FnOnce(AnyView, &mut Window, &mut App) -> T;

fn read_window<T, R>(
    &self,
    window: &WindowHandle<T>,
    read: impl FnOnce(Entity<T>, &App) -> R,
) -> Result<R>
where
    T: 'static;
update_window provides mutable access to the window’s root view and its Window. read_window provides read-only access. Both return Err if the window has been closed.
handle.update(cx, |view, window, cx| {
    view.set_title("New Title", window);
})?;

let title = cx.read_window(&handle, |entity, cx| entity.read(cx).title.clone())?;

Quitting

pub fn quit(&self)
Instructs the platform to quit the application. Any callbacks registered with on_app_quit run first (up to SHUTDOWN_TIMEOUT, which is 100 ms) before the process exits.

Global state

Globals are type-keyed singletons stored on App. Any type that implements Global can be stored and retrieved by its TypeId. This is the idiomatic way to share cross-cutting state (settings, registries, service handles) without passing it through every call chain.
Accessing a global that has not been set will panic. Use has_global or try_global when the global may be absent.

Setting and reading

// Set — replaces any existing value of this type
pub fn set_global<G: Global>(&mut self, global: G)

// Read — panics if the global is not set
pub fn global<G: Global>(&self) -> &G

// Read mutably — panics if the global is not set
pub fn global_mut<G: Global>(&mut self) -> &mut G

// Read without panicking
pub fn try_global<G: Global>(&self) -> Option<&G>

// Check presence
pub fn has_global<G: Global>(&self) -> bool
use kael::Global;

#[derive(Default)]
struct MySettings {
    theme: String,
}
impl Global for MySettings {}

// In run:
cx.set_global(MySettings { theme: "dark".into() });

// Anywhere with &App:
let settings = cx.global::<MySettings>();
println!("{}", settings.theme);

BorrowAppContext trait helpers

Any context that implements BorrowMut<App> — which includes App, Context<T>, and async contexts — also implements BorrowAppContext, which adds three convenience methods:
pub trait BorrowAppContext {
    fn set_global<T: Global>(&mut self, global: T);

    fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
    where
        G: Global;

    fn update_default_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
    where
        G: Global + Default;
}
set_global
(G: Global)
Stores a value as the global for type G. Notifies any observers registered via observe_global.
update_global
(FnOnce(&mut G, &mut Self) -> R) -> R
Leases the global mutably, calls the closure, then restores it. The closure receives both the global and the context, allowing you to open windows or mutate entities while holding the global.
update_default_global
(FnOnce(&mut G, &mut Self) -> R) -> R
Like update_global, but creates a Default value first if the global is not yet set.
cx.update_global::<MySettings, _>(|settings, _cx| {
    settings.theme = "light".into();
});

cx.update_default_global::<MySettings, _>(|settings, _cx| {
    settings.theme = "high-contrast".into();
});

Observing global changes

pub fn observe_global<G: Global>(
    &mut self,
    f: impl FnMut(&mut App) + 'static,
) -> Subscription
The callback fires each time the global of type G is mutated. The returned Subscription must be held alive; dropping it unregisters the observer.

Lifecycle hooks

on_app_quit

// On App:
pub fn on_app_quit<Fut>(
    &self,
    on_quit: impl FnMut(&mut App) -> Fut + 'static,
) -> Subscription
where
    Fut: 'static + Future<Output = ()>;

// On Context<T>:
pub fn on_app_quit<Fut>(
    &self,
    on_quit: impl FnMut(&mut T, &mut Context<T>) -> Fut + 'static,
) -> Subscription
where
    Fut: 'static + Future<Output = ()>,
    T: 'static;
Registers an async callback to run when the application is about to quit. The returned future is polled for up to SHUTDOWN_TIMEOUT (100 ms). Use this for flushing writes, releasing locks, or sending a final analytics event.
You cannot cancel the quit at this point. The callback is informational only.
cx.on_app_quit(|cx| async move {
    cx.global::<Database>().flush().await;
});

on_window_closed

pub fn on_window_closed(
    &self,
    on_closed: impl FnMut(&mut App) + 'static,
) -> Subscription
Fires each time any window is closed. The window is no longer accessible when this callback runs.

on_app_restart

pub fn on_app_restart(
    &self,
    on_restart: impl FnMut(&mut App) + 'static,
) -> Subscription
Fires before any on_app_quit callbacks when the application is about to restart. Use it to persist state that must survive the restart.

Executors

pub fn background_executor(&self) -> BackgroundExecutor
pub fn foreground_executor(&self) -> ForegroundExecutor
BackgroundExecutor spawns futures on a thread pool. ForegroundExecutor runs futures on the main thread, interleaved with the event loop. Both are cloneable and can be stored for use in async code.
let executor = cx.background_executor().clone();
cx.background_spawn(async move {
    let result = expensive_computation().await;
    executor.spawn(async move { /* update UI */ }).detach();
});
Prefer cx.background_spawn(future) from AppContext for one-shot background tasks. Reserve background_executor() for cases where you need to hold the executor across an await point.

Build docs developers (and LLMs) love