Expand description
Hot update / OTA live updates for Tauri v2 mobile and desktop apps — CodePush-style, self-hosted.
Serves the frontend from a downloaded OTA bundle when one is active,
falling back to the embedded assets compiled from frontendDist. Updates
apply on the next cold launch only, guarded by a three-state rollback
pointer (staged → booting → committed): a bundle that never acks via
HotUpdate::notify_app_ready is blacklisted by archive hash on the next
boot and serving falls back to the last-known-good bundle or the embedded
assets. One bad OTA push can never brick an installed app.
§Integration (two steps)
The assets swap must happen on the Context before Builder::build
consumes it, while path resolution (the app data dir) is only available
once the app is being built — hence two steps sharing one handle:
fn main() {
let mut context = tauri::generate_context!();
// 1. Swap the embedded assets for the hot-update provider.
let hot_update = tauri_plugin_hot_update::install(&mut context);
tauri::Builder::default()
// 2. Register the plugin; its setup hook resolves the bundle
// store and arms/rolls back BEFORE any webview exists.
.plugin(tauri_plugin_hot_update::init(hot_update))
.run(context)
.expect("error while running tauri application");
}Configuration lives in tauri.conf.json (see Config) and is
validated inside the setup hook — a malformed manifest URL or trust
anchor aborts startup on the developer’s machine, never silently in the
field. The five IPC commands (check, download, notify_app_ready,
current_bundle, reset; npm package tauri-plugin-hot-update-api)
must be granted in a capability file, e.g. "permissions": ["hot-update:default"].
Register this plugin before other plugins so nothing observes assets
earlier than the boot resolution. The frontend must call
notifyAppReady() once the app shell has mounted and rendered —
deliberately independent of network reachability or auth, so a backend
outage can never condemn a good bundle fleet-wide.
§Ordering guarantee
Plugin setup hooks run inside Builder::build (tauri 2.10.2
app.rs:2289), strictly before config windows and webviews are created
(app.rs:2373). The staged→booting promotion is therefore persisted
before the provider serves a single byte, on every platform — including
Android, where the app data dir cannot be resolved before the app exists.
Structs§
- Archive
Info - Where the bundle archive lives and what it must hash to.
- Config
plugins.hot-updateintauri.conf.json.- Current
Bundle - Snapshot of what this process is serving.
- Download
Progress - Payload of
PROGRESS_EVENT: archive bytes received so far out of the signed manifest’s total. - HotUpdate
- Runtime API, managed in the app state by
crate::init. IPC commands (WP4) will be thin wrappers over these methods. - HotUpdate
Assets - Assets provider wrapping the embedded
EmbeddedAssetstaken from the generatedContext(via the officialContext::set_assets). - HotUpdate
Handle - Opaque link between
install(which creates the assets provider) andinit(which activates it once paths are resolvable). - Manifest
- The update manifest, exactly as published next to its detached
.minisigsignature. - Update
Config - Where updates come from and who is trusted to sign them. The plugin
setup hook builds this from the validated
crate::Config; Rust-side callers may construct it directly.
Enums§
- AckOutcome
- Result of an ack ([
ack]). - Bundle
Source - Where the currently served frontend comes from.
- Error
- Errors surfaced by the hot-update plugin.
- Extract
Error - Why extraction was refused or failed. Every variant is a hard stop; the caller discards the partial output directory.
- Stage
Error - Why a staging request was refused.
- Update
Outcome - Result of a check or download pass. Refusals are first-class outcomes, not errors: they are the pipeline saying “this manifest is not for us”, with the reason preserved for the app/UI.
Constants§
- PROGRESS_
EVENT - Event emitted while [
download] streams the archive, carrying aDownloadProgresspayload. Emission is throttled to at most one event per 100 ms so the IPC bridge is never flooded by per-chunk callbacks; the final chunk (downloaded == total) is always emitted.
Traits§
- HotUpdate
Ext - Access the
HotUpdateruntime API from anyManager(app handle, window, webview).
Functions§
- init
- Step 2: the plugin. Its setup hook (which tauri runs before any webview
is created) validates the
Configfromtauri.conf.json, resolves{app_data_dir}/hot-update, loadsstate.json, performs rollback/arming, persists, and activates serving. - install
- Step 1: swap the generated context’s embedded assets for the hot-update
provider. Must be called before
tauri::Builder::build/runconsumes the context. Pass the returned handle toinit.