The modern SaaS/admin frame: persistent left navigation, a sticky top bar with the collapse toggle, and a ROUTED main workspace — nav links swap only the main slot, so the shell, sidebar state, and scroll survive every navigation. Collapse persists via a cookie the server reads, so first paint is always correct.
<div class="app-shell" data-sidebar="open">
<aside class="app-sidebar" id="app-sidebar">
<div class="sidebar">
<div class="sidebar-brand"><span class="sidebar-brand-text">Acme Ops</span></div>
<nav class="sidebar-nav" aria-label="Primary">
<ul class="sidebar-nav-list">
<li><a class="sidebar-nav-link" aria-current="page" href="#" hx-get="/mock/shell/dashboard" hx-target="#main-content" hx-swap="innerHTML"><span class="sidebar-nav-icon"><svg class="icon" aria-hidden="true"><use href="#i-layout-dashboard"/></svg></span><span class="sidebar-nav-label">Dashboard</span></a></li>
<li><a class="sidebar-nav-link" href="#" hx-get="/mock/shell/invoices" hx-target="#main-content" hx-swap="innerHTML"><span class="sidebar-nav-icon"><svg class="icon" aria-hidden="true"><use href="#i-receipt"/></svg></span><span class="sidebar-nav-label">Invoices</span></a></li>
<li><a class="sidebar-nav-link" href="#"><span class="sidebar-nav-icon"><svg class="icon" aria-hidden="true"><use href="#i-users"/></svg></span><span class="sidebar-nav-label">Customers</span></a></li>
</ul>
</nav>
<div class="sidebar-footer">
<div class="sidebar-user-block"><span class="sidebar-user-name">Ada Lovelace</span></div>
</div>
</div>
</aside>
<div class="app-content">
<header class="app-header">
<div class="topbar">
<div class="topbar-leading"><button type="button" class="sidebar-toggle" data-sidebar-toggle aria-expanded="true" aria-controls="app-sidebar" aria-label="Toggle navigation"><span class="sidebar-toggle__icon" aria-hidden="true"></span></button></div>
<div class="topbar-title"><span class="topbar-title-text">Acme Ops</span></div>
<div class="topbar-trailing"><button type="button" class="button" data-variant="primary">New invoice</button></div>
</div>
</header>
<main class="app-main" id="main-content">
<div class="stack" data-gap="md">
<h1>Dashboard</h1>
<div class="auto-grid" style="--grid-min: 10rem">
<div class="card card-body">
<div class="card-label">Outstanding</div>
<div class="card-value">£12,450</div>
</div>
<div class="card card-body">
<div class="card-label">Paid</div>
<div class="card-value">£48,900</div>
</div>
</div>
</div>
</main>
</div>
</div>hx-get the page fragment, hx-target="#main-content" — the server returns only the workspace body, and everything else (shell, sidebar collapse state, focus, scroll) persists. In Dazzle this is the workspace pattern: every example app's views render inside this shell. The collapse toggle writes the dz_sidebar cookie so the SERVER renders data-sidebar correctly on the next full page load — state-in-DOM at SSR, no client hydration flash.