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-uiOr pin to a commit:
bash
npm install nomadahq/sprint-mode-ui#abc1234Package 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 stylesImport 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 stylesMinimal 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' }
})