Skip to content

Layout & Sidebar

The Layout component is the full app shell — sidebar navigation, session context, mobile drawer, and user dropdown. Every page in an SM product app is a child of Layout.

Usage

jsx
import { Layout } from '@nomadahq/sm-ui'
import '@nomadahq/sm-ui/css'
import '@nomadahq/sm-ui/css/shell'
import '@nomadahq/sm-ui/css/components'
import { BrowserRouter, Routes, Route } from 'react-router-dom'

// Define nav for your product
const NAV = {
  'mode': {
    label: 'Mode',
    items: [
      { to: '/discovery', label: 'Discovery', step: 1 },
      { to: '/scan', label: 'Scan', step: 2 },
      { to: '/results', label: 'Results', step: 3 },
      { to: '/billing', label: 'Billing', icon: 'bill' },
    ]
  }
}

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Layout navConfig={NAV} />}>
          <Route path="discovery" element={<Discovery />} />
          <Route path="scan" element={<Scan />} />
        </Route>
      </Routes>
    </BrowserRouter>
  )
}

Props

PropTypeDefaultDescription
navConfigobject{}Product nav sections. Merged with SM defaults.
logoSrcstringSM logoOverride logo in sidebar header
logoAltstring"Sprint Mode"Logo alt text
onLogoutfunctionclears cookie → /auth/loginCustom logout handler
profilePathstring"/profile"Where profile dropdown links go
js
const NAV = {
  // Key must match the product name in the user's JWT `products[]`
  'your-product': {
    label: 'Your Product',
    items: [
      // Icon-based nav item
      { to: '/dashboard', label: 'Dashboard', icon: 'grid', exact: true },
      { to: '/clients', label: 'Clients', icon: 'users' },

      // Step-based nav item (shows numbered step badge instead of icon)
      { to: '/step-one', label: 'Step One', step: 1 },
      { to: '/step-two', label: 'Step Two', step: 2 },
    ]
  }
}

Available icon names: grid, users, bill, code, trend, portfolio, file, msg, gear, dollar

Default Nav Sections

Layout ships with pre-built nav for SM products. These show automatically when the logged-in user's products[] contains that key:

KeySection
sprint-modeSprint Mode (Dashboard, Team) — always shown if user has any product
studiosStudios (Dashboard, Billing)
modeMode (7 workflow steps + Billing)
investorInvestor (Overview, Portfolio, Documents, Updates)

Products pass navConfig to add or override sections.

Session Context

Layout fetches the user session from SM API on mount and provides it via React context. If no session exists, the user is redirected to /auth/login.

jsx
import { useSession } from '@nomadahq/sm-ui'

function Dashboard() {
  const session = useSession()
  // session: { id, email, name, avatar, products[], iat, exp }
  return <h1>Welcome, {session.name}</h1>
}

useSession() returns null only if called outside of Layout. Since Layout redirects on missing session, any page rendered inside Layout will always have a valid session.

Auth Redirect Flow

  1. Layout mounts → calls fetchSession() (GET /auth/me)
  2. If 401 → navigate('/auth/login?redirect=' + currentPath)
  3. Login page → Google SSO or magic link → SM API sets sm_client cookie
  4. SM API redirects back to redirect param → Layout loads, session exists
  5. Pages render normally

The login page must be at /auth/login in your router and must render the Login component. See Login Component.

Sprint Mode LLC — Internal Platform Documentation