Files
hemx/docs/recipes/host-capabilities.md
slhx agent a28eb78ded docs(local): describe projections before generated effects
Keep local/offline and host capability recipes on app-owned command/event/projection flow without teaching raw EffectBatch as the authoring boundary.

req: local/001

req: local/002

req: host/002
2026-06-12 08:00:49 +02:00

2.4 KiB

Recipe: typed host capabilities

hemx-host is the boundary between a hemx app and a browser, PWA, WebView, or native shell. It is not a mobile framework and it is not a new UI runtime. A host adapter can perform explicit host side effects or return facts; app code still owns domain decisions and returns normal hemx effects. req: host/001 req: host/002

Contract

Declare the capability shape the app may use:

use hemx_host::{Capability, CapabilityManifest, CapabilityShape, CapabilityUse};

let manifest = CapabilityManifest::new([
    CapabilityUse::new(Capability::Haptics, CapabilityShape::Fire),
    CapabilityUse::new(Capability::Share, CapabilityShape::Request),
]);

Check the manifest against the concrete host profile before executing calls:

use hemx_host::{HostProfile, HostCheckError};

let host = HostProfile::new(
    "web",
    [CapabilityUse::new(Capability::Share, CapabilityShape::Request)],
);

let result: Result<(), HostCheckError> = manifest.check(&host);

Permission-sensitive capabilities such as microphone, camera, notifications, secure storage, file picker, and geolocation need a user-facing reason in the manifest before standard host checks pass. req: host/003 req: host/004

Browser/PWA adapter

hemx-host::BROWSER_HOST_JS is an optional tiny browser adapter. It exposes window.hemxBrowserHost.perform(call), accepts the serde JSON shape of HostCall, calls browser APIs such as navigator.share or navigator.vibrate, and returns the serde JSON shape of HostEvent. It does not query, patch, or own the DOM; the app consumes the host event and returns ordinary hemx effects. req: host/001 req: host/002 req: host/005

Event flow

Host events are facts, not app mutations. Denied, timeout, unavailable, and error cases all use HostEvent::Failed(HostFailure { kind, ... }), so app code handles one typed result shape before producing UI effects:

HostEvent
→ app/domain command
→ domain validation and optional persistence
→ projection/rendering
→ generated UI effects

Adapters must not mutate DOM, append domain events, or write application state on behalf of the app. req: host/002 req: host/005

Mobile

iOS and Android shells are thin host adapters around a WebView. They implement manifest-backed calls such as haptics, share, microphone streams, secure storage, notifications, and explicit custom capabilities; hemx still owns UI effects and the app still owns state. req: host/001 req: host/002