Skip to content

Product app UI

When to update: App shell, navigation, shared components, breakpoints, or accent usage changes.

Both product SPAs (apps/personal-web, apps/business-web) share a common UI foundation in packages/ui. The goal is a calm, Apple-like experience: clear hierarchy, grouped content, predictable navigation, and layouts optimized for mobile and desktop.

ExportRole
tokens.cssCSS variables — surfaces, accents, spacing, radii, motion
AppShellPage frame: sidebar (desktop), header + bottom nav (mobile)
SidebarNav / BottomNavReact Router NavLink navigation
PageHeaderTitle, description, optional actions
Card, Button, EmptyState, SpinnerCore primitives

Apps import components from @keepintracks/ui and bridge tokens in src/styles/global.css via Tailwind @theme inline. tokens.css includes @source so Tailwind scans shared component classes in the monorepo.

AppAccent tokenUse
Personal--color-personalNav active state, primary buttons, empty-state icons
Business--color-businessSame pattern for business plane

Do not mix accents across apps.

BreakpointNavigationContent
< md (mobile)Fixed bottom tab bar + compact top headerFull width, bottom padding for safe area
≥ md (desktop)Fixed left sidebar (~15rem)Centered column, max ~48rem

Navigation items are defined per app in src/nav.ts.

Every route should follow:

  1. PageHeader — title, one-line description, optional primary CTA
  2. Primary content — cards, lists, or EmptyState with a single obvious next step
  3. Forms — open via header CTA, FAB, or empty-state button (not as a permanent top section)

Production builds use VITE_API_URL (see DEPLOYMENT.md). Local dev uses Vite proxy for /health.

AppLayoutRoutes (foundation)
Personalsrc/layouts/AppLayout.tsx/, /activity, /journal, /settings
Businesssrc/layouts/AppLayout.tsx/, /employees, /schedule, /invoices, /settings

Each app includes public/_redirects:

/* /index.html 200

Required for client-side routes after deploy.