App Shell (Navigation, Search, Assistant Sidebar)
This document defines the shared application shell used across authenticated ConversionIQ surfaces.
Scope:
- Layout regions common to most in-app pages (left navigation, top bar, profile menu)
- Shared footer region for authenticated app pages
- Global platform search behavior (contract-level, UI details may evolve)
- Chatti Live assistant sidebar behavior (show/hide rules)
Out of scope:
- Page-specific business logic (belongs in
docs/domains/**) - Route-specific composition details (belongs in
docs/routes/**)
References:
- Platform Overview (ConversionIQ MVP)
- Roles & Permissions Model
- Security & Compliance
- Analytics Events (MVP)
- Dashboard surface: Account – Dashboard
Purpose
Section titled “Purpose”Provide a consistent enterprise-grade shell that:
- Preserves org/workspace context and isolation cues
- Offers predictable navigation across apps
- Enables global search without permission leakage
- Provides an assistant entry point (Chatti Live sidebar) without disrupting primary workflows
Layout structure
Section titled “Layout structure”1) Left navigation rail (persistent)
Section titled “1) Left navigation rail (persistent)”Responsibilities:
- Primary navigation between top-level app sections.
- Secondary navigation for the selected section.
Presentation states:
- Default (expanded): icons + labels + section group headings.
- Narrowed: icon-only rail (labels hidden; discovery behavior is TBD such as tooltips).
Expected groups (sitemap-aligned):
- Get started
- Account
- Comment Responder
- Chatti Live
Account menu order (main nav):
- Dashboard
- Workspaces
- Knowledge bases
- Channels
- Agents
- My profile
- Settings
Note: Agents is presented under the Account group in the left nav menu.
Node view sheet (Workspace detail)
Section titled “Node view sheet (Workspace detail)”The Workspace detail page (/account/workspaces/[workspaceId]) opens a full-screen bottom sheet for the node view — a visual graph of the workspace’s resource structure. The sheet header contains:
- Workspace selector —
DropdownMenuat the leading edge of the sheet header (before connection toggles). With 2+ workspaces, choosing an item updates the in-sheet workspace without closing the sheet; with one workspace, shows a non-interactive label + avatar. - KB connections toggle —
Switchlabeled “KB connections”. Toggles visibility of all dashed KB-connection edges (agent→KB and channel→KB) in the graph. Default: on. Session-local (not persisted).
See Workspace – Node View for the full node view specification.
Get Started progress indicator (onboarding)
Section titled “Get Started progress indicator (onboarding)”The Get started navigation item includes a 3-segment circular progress indicator representing onboarding progress:
- Segment 1: Step 1 — Select channels
- Segment 2: Step 2 — Connect channels
- Segment 3: Step 3 — Train ConversionIQ AI
Visual rule:
- Completed segment: solid (white)
- Incomplete segment: semi-transparent
Visibility:
- The progress indicator is shown in both left-nav presentation states:
- Default (expanded)
- Narrowed (icon-only)
- The entire
Get startednavigation item is shown only while onboarding is incomplete AND not persistently hidden.- The nav item is hidden/removed when any of these is true:
- Step 3 is completed (onboarding complete).
persistentlyHiddenistrue(user toggled “Don’t show Get Started automatically” in the overlay header).
- The nav item is hidden/removed when any of these is true:
Source of truth:
- Segment completion must be derived from onboarding progress state (see Get Started – Stepper (3 steps)), not a client-only flag.
- Onboarding is complete only after Step 3 is completed.
Notes:
- Navigation must remain consistent with Sitemap (ConversionIQ) and
docs/routes/**/README.md. - Items must be hidden/disabled if the user lacks required permissions (TBD exact gating rules per route doc).
2) Top bar (persistent)
Section titled “2) Top bar (persistent)”Required elements:
- Breadcrumbs (reflect current active page)
- Purpose: communicate the current location within the app hierarchy.
- Format:
{Top-level section} > {Active page}- Example:
Account > Dashboard - Example:
Account > Channels - Example:
Account > Profile
- Example:
- Rules:
- Breadcrumbs must always reflect the current active page.
- The active page crumb must match the route’s page title (sitemap-aligned).
- Color rule (required for consistency):
- All breadcrumb levels except the last (current) use the muted text color (same as the 1st level; e.g.
#999). - Only the last (current) breadcrumb item uses the dark text color (e.g.
#0d0d0dor#333). - Example:
Account(muted)>Workspaces(muted when there is a 3rd level)>Acme Workspace(dark/current).
- All breadcrumb levels except the last (current) use the muted text color (same as the 1st level; e.g.
- Workspace detail (top bar):
- On
/account/workspaces/[workspaceId], the breadcrumb trail is:Account>Workspaces(link to the workspaces list)>workspace name (last/current crumb). - The workspace name crumb is a dropdown/select when the account has more than one workspace (lists all workspaces; selection navigates to
/account/workspaces/[id]). - The workspace name crumb is a plain (non-interactive) label when there is only one workspace.
- The workspace name crumb uses the dark/foreground text color (it is the last/current crumb).
AccountandWorkspacesuse muted color per the standard color rule. - There is no workspace switcher placed before the section label — the workspace name lives only at the end of the breadcrumb trail.
- On
- Knowledge base detail breadcrumb (workspace-scoped entry):
- When opening a KB detail from a workspace KB list, breadcrumb must be:
Account > Workspaces > [Workspace name] > [KB name]
[Workspace name]links back to/account/workspaces/[workspaceId].[KB name]is the active crumb and becomes a dropdown/select when the workspace has 2+ KBs:- Trigger label shows the current KB name (truncated if needed).
- Dropdown lists KBs from that workspace only.
- Selecting a KB navigates to
/account/knowledge-bases/[kbId]while preserving workspace breadcrumb context.
- When opening a KB detail from a workspace KB list, breadcrumb must be:
- The My profile surface (including Billing and Activity log tabs) is part of the Account section for breadcrumbs (e.g.,
Account > My profile). - Separator style (e.g., chevrons) is UI-level; semantics must be clear for accessibility.
- A toggle control (icon) in the breadcrumb area toggles the left navigation rail between Default and Narrowed states. This control is shown for all top-level sections (Account, Comment Responder, Chatti Live), not only Account.
- The last breadcrumb item (active page) is a dropdown when the current section has 2 or more pages:
- Clicking it opens that section’s submenu (secondary navigation for the current section).
- Selecting an item navigates within the section and updates breadcrumbs accordingly.
- If the section has only 1 page, the last breadcrumb item is rendered as a plain, non-interactive span.
- Global platform search input
- Conditional assistant toggle (see Chatti Live section)
3) Primary content canvas
Section titled “3) Primary content canvas”- Page title and page-specific content region.
- The shell does not add padding around the main content area; each page is responsible for its own layout.
- Account-section pages use a standard top section with
px-6 py-5and a single outerborder-b. - For simple pages, this top section may contain only the page title / supporting copy.
- For list pages with filters, the title/meta row and the filter toolbar live inside the same bordered top section with internal spacing between them and no divider between header and filters.
- Count rule for list pages:
- The page-level title badge shows the total number of entities on that page and must not change when table/list filters are applied.
- Any table/list section header count inside the page shows the currently visible filtered dataset for that section.
- Overview/dashboard checklist for Account-style operator pages:
- Lead with the most decision-critical information first; detail belongs below summary.
- Keep the initial screen scannable; avoid equally loud competing metrics.
- Tab or category label counts show stable totals for that category and do not change with filters.
- Filters should refine or prioritize the content below without destroying the high-level overview.
- Reuse shared top-section, filter, tabs, section-header, and table-control patterns across sibling pages.
- Use keyboard-only visible focus states for controls; mouse selection should not leave prominent focus halos.
- Scrollbars and supporting chrome must inherit the active light/dark theme.
- When local/context data already exists, prefer immediate render with background refresh over blocking the page behind loading skeletons.
- The shell must not impose domain rules; it provides composition only.
4) Right sidebar: Chatti Live assistant (conditional)
Section titled “4) Right sidebar: Chatti Live assistant (conditional)”When shown:
- Docked sidebar on the right
- Header:
Chatti Livewith overflow actions and close control - Content area (assistant messages + recommended actions)
- Input dock: “Ask your question”
When hidden:
- Sidebar is absent
- A
Chatti Livetoggle button appears next to the global search input
5) Footer (persistent)
Section titled “5) Footer (persistent)”- A shared footer is pinned below the main content area in the authenticated shell.
- The footer provides lightweight secondary navigation and support/legal entry points.
- Current footer actions:
SecurityHelpContactComponentsLegal
Componentslinks to/account/components.- The footer is not part of the primary left navigation and should be treated as secondary utility navigation.
Chatti Live sidebar: visibility rules
Section titled “Chatti Live sidebar: visibility rules”Toggle behavior (required)
Section titled “Toggle behavior (required)”- Hidden state: show
Chatti Livebutton in the top bar (next to search). - Shown state: hide the top-bar button (sidebar header provides controls).
- Closing the sidebar returns to hidden state.
Availability gating
Section titled “Availability gating”The assistant sidebar may be gated by:
- Feature flag / plan entitlement (TBD)
- Role/permission checks (TBD)
If not available:
- Do not show the top-bar toggle
- Do not render the sidebar
Implementation note (contract-level)
Section titled “Implementation note (contract-level)”The assistant is intended to be a Gemini-backed assistant in a Chrome browser context. Details (auth, data access, tool boundaries) must comply with Security & Compliance and must be documented before implementation.
Global platform search
Section titled “Global platform search”Search is global across the platform, but must respect:
- org scope (
org_id) - workspace scope (
workspace_id) where applicable - RBAC permissions for each result type
Required security invariant
Section titled “Required security invariant”Search must not leak:
- existence of entities the user cannot access
- cross-workspace or cross-org data
All result rendering must be permission-filtered (no “UI-only security”).
UX expectations (TBD)
Section titled “UX expectations (TBD)”- Result grouping by entity type (routes, KBs, channels, conversations, etc.) is TBD.
- Keyboard navigation and accessibility requirements are required (TBD component contracts).
Profile-only user menu (bottom-left)
Section titled “Profile-only user menu (bottom-left)”This control is profile-only (not a workspace switcher).
Expected menu items (sitemap-aligned):
- My profile — links to
/account/my-profile?tab=profile - Billing — links to
/account/my-profile?tab=billing - Activity log — links to
/account/my-profile?tab=activity - Log out
The menu may display user identity summary (name/email). My profile, Billing, and Activity log all target the same My profile page with the appropriate tab selected via the tab query parameter.
States
Section titled “States”Shell-level UI states that must be supported across pages:
- Left nav: default (expanded) / narrowed
- Profile menu: closed / open
- Global search: idle / querying / empty / error (TBD)
- Assistant sidebar: hidden / shown
- Get Started onboarding overlay: inactive / active (fullscreen overlay; see Get Started – Stepper (3 steps))
Overlay interaction expectations (MVP):
- When onboarding overlay is active, it covers the shell (navigation/search/assistant are not the primary surface) (TBD exact interaction lock).
- Closing/dismissing the overlay navigation rule:
- If the user was on
/get-started(i.e. they navigated there directly): redirect to Account → Dashboard after dismissal. - If the user was on any other account page (e.g.
/account/channels,/account/workspaces): do not navigate. Simply dismiss the overlay and refresh setup state. The user stays on the page they were already viewing. - Rationale: the overlay is a layer on top of the shell; closing it should not disrupt the user’s current context unless they have no underlying page to return to.
- If the user was on
- The overlay is shown on every authenticated entry until onboarding is complete or persistently hidden.
- Onboarding is considered complete only after the user completes Step 3: Train ConversionIQ AI.
- Persistent hide: When
persistentlyHiddenistrue, the overlay never auto-opens and theGet startednav item is removed. Restore path: Chatti Live only.
UI component standards
Section titled “UI component standards”Filter / select triggers
Section titled “Filter / select triggers”Filter triggers and select-like controls that use the shared SELECT_TRIGGER_BASE_CLASSNAME contract must follow a single state model across the app:
- Use the violet ring for focus-visible only.
- Do not reuse that ring as an “open” indicator on click.
- Open-state affordance, when needed, should be subtle and consistent across controls (for example chevron direction, border tint, or surface tint), but must not conflict with the accessibility focus treatment.
This applies to toolbar filters such as All workspaces, All groups, status selects, and similar trigger controls on other pages.
Tabs (TabsTrigger padding)
Section titled “Tabs (TabsTrigger padding)”All tab triggers across the app must use the shared TabsTrigger component from @/components/ui/tabs (Radix TabsPrimitive.Trigger wrapper).
Standard padding: py-1 px-2 (4 px vertical, 8 px horizontal)
- This is baked into the shared component’s default
classNameand must not be overridden at the call site. - Do not pass
px-*orpy-*overrides to<TabsTrigger className="...">— doing so breaks visual consistency across all tab instances. - If a page needs a visually distinct tab style, discuss and update the shared component; do not patch it locally.
Reference implementation: src/components/ui/tabs.tsx
Permissions & data access
Section titled “Permissions & data access”- Navigation items must be gated by route permissions (see each route doc).
- Search must filter results to the user’s authorized scope.
- Assistant must not access cross-workspace data unless explicitly authorized and documented.
Reference: Roles & Permissions Model
Security & compliance considerations
Section titled “Security & compliance considerations”- Do not emit/store PII or message content in analytics.
- Mask secrets in all UI surfaces (including assistant).
- Prevent cross-tenant leakage via navigation, search, or assistant context.
Reference: Security & Compliance
Analytics events (if applicable)
Section titled “Analytics events (if applicable)”Minimum expectations:
- Shell load / route view events remain page-owned (e.g.,
account.dashboard.viewed) - Search/assistant interaction events are TBD and must not include PII or message content
Reference: Analytics Events (MVP)