← All Reports

SPIKE-007: Dashboard UX Research

Spike 2026-02-22 Dashboard UX, Competitive Analysis, Design Specs Complete
13
Deliverables
10
Apps Analyzed
6
Researchers
1
Day

Overview

This spike researched 10 health and productivity apps, defined the information architecture, visual design system, data visualization strategy, interaction patterns, and technical stack for the Data Hub personal health dashboard. The dashboard will serve a single user (Taps) training for Race to the Sun (30 May 2026) with data from Strava, Google Fit, Garmin Index S2, food logging, and Ozempic tracking.

Deliverables

ID Title Owner Status
D-1Competitive analysis (10 app teardowns)UX ResearcherComplete
D-2Common patterns and best practicesUX ResearcherComplete
D-3Dashboard layout recommendationUI DesignerComplete
D-4Information hierarchy and progressive disclosureUX ResearcherComplete
D-5Color, typography, dark mode specsUI DesignerComplete
D-6Data visualization recommendationsUI DesignerComplete
D-7Interaction patterns catalogUX ResearcherComplete
D-8Race countdown and goal tracking UIUX ResearcherComplete
D-9Mobile-first responsive considerationsFrontend DeveloperComplete
D-10Chart library and tech stackFrontend DeveloperComplete
D-11MVP metrics and acceptance criteriaProduct OwnerComplete
D-12Technical feasibility reviewFrontend DeveloperComplete
D-13Final report (this document)Business AnalystComplete

Key Decisions

Executive Summary

This spike researched 10 health and productivity apps to extract proven UX patterns for the Data Hub dashboard. The findings shaped a comprehensive design specification covering layout, typography, color, data visualization, interaction patterns, and technology choices.

The recommended dashboard follows a three-layer progressive disclosure model. Layer 1 (Glance) shows the race countdown, daily scores, and a training load overview. Layer 2 (Domain) provides full charts with time range controls for each data source. Layer 3 (Detail) surfaces all data for a single activity or entry.

The technical stack is deliberately lightweight: uPlot for time series (~48 KB gz) and Chart.js for categorical charts (~70 KB gz), with vanilla CSS custom properties and static data builds. Total JavaScript payload is under 120 KB gzipped, targeting sub-second loads on 3G.

Six must-have MVP sections were defined with 39 testable acceptance criteria. Three open issues require resolution before implementation: the Garmin Index S2 connector (weight data), the CTL/ATL/TSB computation model (FEAT-004), and data freshness indicators.

App-by-App Competitive Teardown

Ten apps were analyzed across health, fitness, nutrition, and productivity categories. Each teardown identifies key patterns to adopt and anti-patterns to avoid.

1. Apple Health

Customizable Summary tab with favorite cards is the gold standard for letting users choose what matters. Progressive disclosure with three clean layers: Summary > Browse > Detail. Data card pattern combines value, sparkline, and drill-down in a single component. Trend notifications alert users to meaningful changes.

Adopt: data card pattern, three-layer disclosure, customizable summary

Avoid: information overload from aggregating too many sources without hierarchy

2. Garmin Connect

Training Status system translates complex physiological data into a single actionable word (Productive, Maintaining, Peaking, and others). Load Focus uses a three-segment bar to show training distribution across aerobic, anaerobic, and low intensity. Performance Dashboard offers 120+ premade charts. Deep cycling-specific features including power curves and FTP tracking.

Adopt: training status summarization, load focus visualization, cycling depth

Avoid: cluttered navigation, removing customization in redesigns

3. Strava

Fitness and Freshness chart (CTL/ATL/TSB) is directly relevant to Data Hub. Best-in-class activity detail pages with map, stats grid, and HR/power charts. PR badges provide motivation without being overbearing.

Adopt: CTL/ATL/TSB chart, activity detail layout, PR badge system

Avoid: social feed overwhelming personal data, gating key features behind paywall

4. WHOOP

Three-score framework (Recovery, Strain, Sleep) is the best example of distilling biometrics into an actionable system. Traffic light color coding is reserved exclusively for recovery scores, maintaining strong signal clarity. Ring and dial visualizations communicate at a glance. Progressive disclosure is executed cleanly.

Adopt: score-based summarization, disciplined color coding, ring visualization

Avoid: rigid framework with no customization options

5. Oura Ring

Three-tab temporal hierarchy (Today, Vitals, My Health) is the cleanest information architecture in the space. "One Big Thing" approach surfaces a single priority insight each day. Cumulative Stress tracking uses a 31-day rolling window for context.

Adopt: temporal tab hierarchy, single priority insight, rolling window context

Avoid: major navigation changes that disorient existing users, generic AI advice

6. Fitbit / Google Fit

Customizable Today tab is based on user-defined goals. Consistent chart design with clear headers across all data types. Compassionate design language frames data positively. Time range consistency (Day, Month, Year) across all views.

Adopt: goal-based customization, consistent chart headers, time range consistency

Avoid: brand confusion during transitions, messy data migration paths

7. Cronometer

Micronutrient target bars (horizontal progress with three-state color coding) are the best nutritional visualization in any app. Dashboard widgets include Report Summary and Streaks. Strong scientific accuracy positioning appeals to data-focused users.

Adopt: micronutrient target bars, three-state color coding, scientific framing

Avoid: overwhelming data density, weak mobile experience

8. MyFitnessPal

Streamlined food logging with barcode scanner and fast search reduces friction. Macro ring visualization is immediately readable. "Remaining" framing (calories left) is more actionable than "consumed" framing.

Adopt: streamlined logging, macro ring, "remaining" framing

Avoid: ad clutter degrading experience, false calorie precision

9. Superhuman

100ms rule for interaction response creates a feeling of instantaneousness. Command palette (Cmd+K) with passive shortcut learning teaches power features without blocking novice use. Split Inbox pattern for domain separation. Keyboard-first navigation with gamification of productivity metrics.

Adopt: 100ms interaction target, command palette, keyboard navigation

Avoid: steep learning curve for mouse-oriented users

10. Linear

Composable dashboard with charts, metric blocks, and tables. Global dashboard-level filters apply consistently. Project graph with forecasting capabilities. Keyboard shortcuts with command palette. Monochrome base with selective color accents for emphasis.

Adopt: composable widgets, global filters, monochrome with selective color

Avoid: cold or unapproachable aesthetic, enterprise-only complexity

Common Patterns and Best Practices

Ten reusable UX patterns were identified across all 10 apps, prioritized by importance to the Data Hub MVP.

1
Rule of Three Organize primary navigation and content into three top-level sections. Every app studied uses some variant of this. Critical for MVP.
2
Score-Based Summarization Condense complex data into single scores or status words (WHOOP Recovery, Garmin Training Status). High priority.
3
Progressive Disclosure Two models observed: card drill-down (Apple Health) and temporal tabs (Oura). Data Hub uses card drill-down. Critical for MVP.
4
Color Discipline Reserve red, yellow, and green exclusively for scores and status. Never use red for neutral data. High priority.
5
"One Big Thing" and Actionable Framing Surface a single priority insight. Frame data as "remaining" not "consumed." High priority.
6
Consistent Time Range Controls Same 6-preset segmented control (1W/1M/3M/6M/1Y/All) across all charts. High priority.
7
Command Palette and Keyboard Navigation Cmd+K with passive shortcut learning. Stretch goal for MVP.
8
Chart Headers and Contextual Annotations Every chart gets a title, subtitle with current value, and time range control. High priority.
9
Widget/Card Composition Cards as the universal building block. Each card has value, visualization, and drill-down. Critical for MVP.
10
Speed as a Feature Sub-100ms interaction target. Static data builds. Performance budget of ~155 KB. Critical for MVP.

Recommended Dashboard Layout

Single-page dashboard using a 12-column CSS Grid (1200px max width), dark mode default. The layout is organized into two zones: above the fold (hero zone, ~700px viewport) and below the fold (domain sections).

Above the Fold (Hero Zone)

"Data Hub" wordmark on the left. Date navigation strip in the center. Race countdown chip on the right showing days remaining until Race to the Sun.

Five stat cards in a 1fr grid: Weight, Body Fat, Steps, Resting HR, and Form (TSB). Each card shows the current value with a delta indicator and optional sparkline.

Full-width CTL/ATL/TSB area chart with a race day marker line. This is the primary chart the user sees on load.

Below the Fold

Reverse-chronological Strava activities as cards. Each card shows activity type, distance, duration, and key metrics.

Body composition: weight trend chart with body comp breakdown bar. Sleep: last night's summary card, sleep stages horizontal bar, and 7-day trend.

Heart rate: today's HR timeline with HR zone distribution bars. Nutrition: today's food log entries with Ozempic tracker card.

Seven-column mini heatmap calendar showing activity, compliance, and key metrics for the week at a glance.

Grid specification: repeat(12, 1fr) on desktop, single column on mobile. 16px gap between cards, 24px gap between sections.

Information Hierarchy

The dashboard uses a three-layer progressive disclosure architecture. Each layer increases data density and time-on-task.

Layer 1: Glance (under 10 seconds)

The hero insight, 3 to 4 score cards, and race countdown. Low data density. Answers "How am I doing right now?" at a glance.

Layer 2: Domain (1 to 3 minutes)

Full charts with time range controls and chart headers for each data source. Medium data density. Answers "What are the trends?" with interactive exploration.

Layer 3: Detail (deep exploration)

All data for a single entry, activity, or day. High data density. Answers "What exactly happened?" Accessed via card drill-down (slide-over on desktop, full page on mobile).

Disclosure Mechanisms

Priority Order

Race countdown > Weight > Training > Nutrition > Medication. This order determines default sort, visual prominence, and loading priority.

Color Palette, Typography, and Dark Mode

Core Palette

Extends the existing Data Hub CSS variables with additional surface and accent tones.

--bg
#0f0f0f
--surface
#1a1a1a
--surface2
#242424
--surface3
#2e2e2e
--accent
#6C63FF
--green
#4ECDC4
--yellow
#FFE66D
--red
#FF6B6B

Extended Data Visualization Colors

Typography Scale

System font stack with Major Third ratio (1.25). Seven sizes from 11px (--text-xs) to 32px (--text-3xl). Five weights from 400 (regular) to 800 (extra bold). All metric values use font-variant-numeric: tabular-nums for alignment.

TokenSizeUsage
--text-3xl32pxPage titles, hero numbers
--text-2xl26pxSection headers
--text-xl20pxCard titles, stat values
--text-lg16pxBody text
--text-md14pxSecondary text, labels
--text-sm12pxCaptions, metadata
--text-xs11pxAxis labels, fine print

Dark Mode Specification

Dark mode is the only mode. No light mode toggle. Four-level surface elevation creates depth without box shadows:

  1. #0f0f0f (page background)
  2. #1a1a1a (card surfaces)
  3. #242424 (elevated elements, inputs)
  4. #2e2e2e (hover states, active elements)

Depth is communicated through 1px borders, not shadows. All text/background combinations meet WCAG AA+ contrast ratios.

Data Visualization Matrix

Complete mapping of every metric to its optimal chart type, organized by data source.

Source / MetricChart TypeLibrary
Strava: Distance/ElevationBars with goal lineChart.js
Strava: Watts/HRLine + dotsuPlot
Strava: Suffer ScoreLollipopChart.js
Strava: CTL (Fitness)AreauPlot
Strava: ATL (Fatigue)LineuPlot
Strava: TSB (Form)Diverging areauPlot
Google Fit: StepsBars + goal line, radial gauge (today)Chart.js
Google Fit: Daily HRZone-colored areauPlot
Google Fit: Resting HRLine (trend)uPlot
Google Fit: HR ZonesHorizontal stacked barChart.js
Google Fit: Sleep StagesHorizontal stacked barChart.js
Google Fit: HypnogramStepped areauPlot
Google Fit: Sleep DurationStacked bars (trend)Chart.js
Garmin: WeightLine + goal line + Ozempic markersuPlot
Garmin: Body FatSecondary lineuPlot
Food: EntriesCard listHTML
Food: CaloriesBarsChart.js
Food: MacrosDonutChart.js
Ozempic: DosesTimeline dot plotuPlot
Ozempic: + WeightDual-axis overlayuPlot
Computed: CTL/ATL/TSBMulti-layer area + lineuPlot
Computed: Form LabelBadgeHTML
Computed: ProjectionAnnotated projection lineuPlot

Anti-Patterns

Interaction Patterns Catalog

MVP Patterns

Date Range Selection

Six-preset segmented control: 1W, 1M, 3M, 6M, 1Y, All. Instant chart update on selection. Consistent position (top-right of every chart). Active state uses --accent background.

Drill-Down Navigation

Card-to-page: route-based, each domain view has its own URL. List-to-detail: slide-over panel on desktop (400px wide), full page on mobile. Back navigation via breadcrumb: Today > Domain > Detail.

Tooltips

Three-line format: date on line one, primary value on line two, contextual comparison on line three. Hover-triggered on desktop, tap-triggered on mobile. 150ms appearance delay to prevent flicker.

Crosshair

Vertical line snapping to the nearest data point on time series charts. Shows tooltip anchored to the crosshair. Synced across charts in the same domain view.

Navigation

Persistent sidebar on desktop with domain icons and labels. Hamburger menu on mobile collapsing to a bottom sheet. Current domain highlighted with --accent indicator.

Stretch Patterns

Race Countdown and Goal Tracking UI

Hero Countdown

Large day count (using --text-3xl) with race name and a dynamic status line showing the current training phase. A horizontal training phase bar visualizes progression through Base > Build > Peak > Taper > Race phases. The current phase is highlighted with --accent. Compact version appears in the top bar on all other views.

Goal System

Progress cards for each key target:

Each card shows: current value, target value, progress bar, and a status label (on track, behind, at risk, or achieved). Status labels use color discipline: green for on track/achieved, yellow for behind, red for at risk.

Additional Patterns

Mobile-First Responsive Strategy

Small Phone (< 480px)

  • Single column layout
  • 200-250px chart height
  • Bottom tab bar (56px)
  • 2-column KPI grid
  • Legends below charts

Tablet (480-768px)

  • 2-column chart layout
  • 4-column KPI grid
  • Top tab bar navigation
  • Side-by-side domain sections

Desktop (1024px+)

  • 3-column chart layout
  • Auto-fit KPI grid
  • Persistent sidebar nav
  • Max-width 1200px
  • Slide-over detail panels

Mobile-Specific Considerations

Performance Budget

AssetSize (gzipped)
HTML + CSS~15 KB
uPlot~50 KB
Chart.js~70 KB
Dashboard data (JSON)~20 KB
Total~155 KB

Target: under 1 second load on 3G connections.

Tech Recommendations

Charting Libraries

LibraryRoleSize (gz)Rationale
uPlotPrimary: all time series~48 KBFastest Canvas renderer. Handles CTL/ATL/TSB, HR, weight, sleep hypnogram. Gradient fills for diverging and zone-colored areas (~15 lines each).
Chart.jsSecondary: categorical~70 KBMature ecosystem. Handles bars, doughnuts, lollipops, stacked bars. Required for chart types uPlot does not support natively.

Evaluated and Rejected

CSS Strategy

Vanilla CSS with custom properties. No framework (Tailwind, Bootstrap, etc.). Extends the existing Data Hub design system variables. Grid layout via native CSS Grid.

Data Loading

Static build step: scripts/build-dashboard-data.js pre-computes a single dashboard-data.json file at deploy time. No client-side API calls or data processing. Charts initialize from pre-shaped arrays.

Integration

Script tags with CDN or local copies. No bundler (Webpack, Vite, etc.) needed. Canvas does not read CSS variables directly; resolve variable values at chart initialization time via getComputedStyle().

Outcomes

Open Issues