# Embedded mode

Detection helper for when a mini-app is loaded inside an iOS / Android / desktop host container. The host signals via `?host=<value>`; the web persists it in sessionStorage and exposes it to layouts via `useIsEmbedded()` so chrome (`<AppHeader>`, `<AppFooter>`) can be hidden in favor of the host's native nav.

[View examples](https://marsam.rahhal.app/components/embedded-mode) · [Agent index](https://marsam.rahhal.app/llms.txt)

**Import:** `@rahhal/app-chrome/react`

**Category:** `nav`

## URL contract

| ?host= value | container |
| --- | --- |
| ios | official Rahhal iOS app (WKWebView) |
| android | official Rahhal Android app (WebView) |
| mobile | generic mobile container (Capacitor, RN-WebView) |
| desktop | Electron / Tauri-style desktop wrapper |

Values are case-insensitive. Unknown values are ignored (treated as standalone). The host only needs to pass the param **once**: the web persists the resolved value in `sessionStorage["rahhal-host"]` for the tab/WebView lifetime, then strips `?host=` from the visible URL via `history.replaceState`.

## API

| symbol | purpose |
| --- | --- |
| <EmbeddedProvider> | mount once at the app root, after the router. Accepts `hostOverride?: Host | null` for tests / stories. |
| useHost(): Host | null | raw host value · `null` when standalone |
| useIsEmbedded(): boolean | true iff useHost() is non-null · the 90% question |
| useIsMobileHost(): boolean | true only for ios / android / mobile · use for phone-only UX |
| [data-host="ios"] | CSS hook mirrored on <html>; gone when standalone |

All hooks throw if used outside an `<EmbeddedProvider>` — the mounting requirement is enforced.

## What to hide

In embedded mode, hide `<AppHeader>` and `<AppFooter>` only. **Don't** hide `<AppSidebar>` (the host can't replicate section nav) or `<LoginScreen>` (transient auth step). Pair `{!isEmbedded && <Header />}` with `<AppShell noHeader={isEmbedded}>` so the shell doesn't reserve top padding for a header you aren't rendering.

## Composition

- **Auth:** `@rahhal/auth` uses the URL **fragment** (`#access_token=…`). `?host=` is a query parameter — no collision. The provider intentionally never touches `window.location.hash`.
- **i18n:** `@rahhal/i18n` uses the same `history.replaceState` strip pattern for `?lang=`. Mounting both providers is order-independent.
- **SEO:** Unaffected. Viewport and manifest metadata apply the same way whether embedded or not.
