Skip to content

Getting Started

@sprintmode/ui is the Sprint Mode platform UI package — shared React components, design tokens, auth helpers, and the login page. All SM products import from this package.

Installation

Install from the GitHub repo (no npm publish needed):

bash
npm install github:nomadahq/sprint-mode-ui

Or pin to a commit:

bash
npm install nomadahq/sprint-mode-ui#abc1234

Package Structure

@nomadahq/sm-ui
├── src/index.js          ← Main barrel (components, layout, icons, API helpers)
├── src/auth.js           ← Worker-side auth (verifyJWT, signJWT, requireAuth)
├── src/Login.jsx         ← Login page component (SSO + magic link)
├── src/Layout.jsx        ← App shell with collapsible sidebar + session context
├── src/components.jsx    ← Card, Button, Badge, Tabs, Table, StatCard, etc.
├── src/Icons.jsx         ← All SM icons + product logos
├── src/api.js            ← Client-side API helpers (fetchSession, api(), format*)
├── src/tokens.css        ← SM design tokens (CSS custom properties)
├── src/shell.css         ← Sidebar/layout styles
└── src/components.css    ← Component styles

Import Map

js
// Components, Layout, Icons, API helpers — all from the main export
import {
  Layout, useSession,
  Card, CardBody, Button, Badge, Pill,
  StatCard, Stats, Progress, Tabs,
  PageHeader, Table, Empty, Spinner, ScoreRing,
  IconGrid, IconUsers, IconDollar, // ... all icons
  LogoStudios, ProductIcon,
  fetchSession, clearSession, api,
  formatCurrency, formatDate, formatRelative,
} from '@nomadahq/sm-ui'

// Worker-side auth (in _worker.js / CF Worker files — NOT in browser code)
import { verifyJWT, signJWT, requireAuth, generateToken, getSession } from '@nomadahq/sm-ui/auth'

// CSS — import in your root component or layout
import '@nomadahq/sm-ui/css'               // Design tokens
import '@nomadahq/sm-ui/css/shell'         // Sidebar + layout styles
import '@nomadahq/sm-ui/css/components'    // Component styles

Minimal App Setup

jsx
// main.jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import { Layout } from '@nomadahq/sm-ui'
import '@nomadahq/sm-ui/css'
import '@nomadahq/sm-ui/css/shell'
import '@nomadahq/sm-ui/css/components'
import Dashboard from './pages/Dashboard.jsx'
import Projects from './pages/Projects.jsx'

const NAV = {
  'mode': {
    label: 'Mode',
    items: [
      { to: '/dashboard', label: 'Dashboard', exact: true },
      { to: '/projects', label: 'Projects' },
      { to: '/settings', label: 'Settings' },
    ]
  }
}

ReactDOM.createRoot(document.getElementById('root')).render(
  <BrowserRouter>
    <Routes>
      <Route path="/" element={<Layout product="mode" navConfig={NAV} />}>
        <Route path="dashboard" element={<Dashboard />} />
        <Route path="projects" element={<Projects />} />
      </Route>
    </Routes>
  </BrowserRouter>
)

SM API URL

Always call SM API at https://api.sprintmode.ai using the api() helper:

js
import { api } from '@nomadahq/sm-ui'

// GET with query params
const { data } = await api('/api/companies', { product: 'mode' })

// POST
const result = await api('/api/activities', null, {
  method: 'POST',
  body: { activity_type: 'note', contact_id: 'ct_abc', title: 'Call logged' }
})

Sprint Mode LLC — Internal Platform Documentation