AppShell
The platform’s outermost frame — global top bar, product rail, and the content surface products mount into, with an optional AppShellAside panel docked to its right. There is exactly one, at the app root, and it persists while the content swaps. Do not wrap a page in it: a single product screen renders RemoteShell and its own content, blind to the shell. In-product navigation is NavPanel, and laying out a page’s insides is Stack and Flex. The gray surround — header bar plus rail, everything that is not the canvas — is the Frame. It carries Ambient, a faint still layer of soft blooms, grain and a dot cluster pooled bottom-left, painted under everything. Ambient is on by default; ambient={false} leaves the flat Frame fill. The Frame comes in two styles, Neutral and Branded: a user preference next to light/dark, set with useTheme().setFrameStyle (from ThemeProvider) and written on <html> so every micro-frontend follows it. Branded warms the Frame and turns active navigation to the brand colour; try it from the account item → Appearance.
Usage
Examples
Loading
How the shell looks while the platform loads. The header actions and the product rail hold skeletons that sit exactly where the real items land, so nothing jumps when they arrive. Turn loading off in Controls to watch the swap. Opening a product also shows its own panel and content loading.
With aside
AppShellAside docks a panel right of the content surface — the real WallyAssistant here, driven by the useMockWally streaming mock and toggled from the header's ChatTrigger — that slides in as the canvas narrows, while closing widens the canvas back and hides the region without unmounting what is inside, so the conversation and text typed into the panel survive a close and reopen.
Reveal flow
reveal animates the chrome in on the first application load only. Leave it unset for an ordinary screen; this exists for prototyping the boot moment itself.
Login flow
The whole entrance: the splash hands off, the content surface expands from the sign-in card into the full shell. onRevealed fires when it has settled.
With tan stack router
AppShell and a RemoteShell per product on one TanStack Router: the root route is
the shell (rail → navigate, AppShellRemote → <Outlet />), /$product is the
remote (RemoteShell with pathname + onNavigate, content → <Outlet />), and
/$product/$ is the page. Every way of moving — the rail, the nav panel, the
breadcrumbs, links in the page — goes through the router, and the active items follow.