PIRX Docs
Dashboard

Sync Banner

Sync Banner screenshot

Source: components/home/sync-banner.tsx


What You See

A flat row at the very top of the page — no card surface, no rounded panel, no hairline; the banner sits directly on the page background, matching Figma node 2:366 (Sean-Fun file). On the left you see your profile picture (48×48, 1.2px primary-blue ring), your name in Outfit Medium 16px, and a clock-time stamp in Outfit ExtraLight 14px that reads Synced at 9:39 AM once data has been pulled (or Connected / Not synced yet when no sync has completed yet). On the right sit two controls rendered directly on the banner background (no tinted circular chip around them): a 48×48 sync button featuring a custom watch glyph rendered in white with a primary-blue mark centered on the watch face, and a 40×40 notifications bell. The sync button is intentionally larger than the bell so it reads as the primary action. Both glyphs are Figma-exact inline SVGs (components/icons/watch-sync-icon.tsx and components/icons/notification-bell-icon.tsx) rather than generic Lucide icons so they match the PIRX design system. The watch glyph keeps a stable silhouette across every state — only the mark inside the watch face changes: a blue checkmark when synced, a blue X when not synced, and a spinning 3/4-circle progress ring during an active sync (the watch never disappears and is never replaced by a standalone spinner). The bell carries a small primary-blue dot in its top-right corner only when there are unread notifications — tap to open the activity feed.

How the Numbers Work

The sync time is the local clock time of the last successful sync, formatted like 9:39 AM. When you tap the watch button, PIRX asks your wearable provider for any new activities and then recalculates all of your numbers. The progress ring inside the watch face spins while the sync is in flight (implemented as an SVG SMIL animateTransform rather than a CSS animation so WKWebView / installed iOS PWAs render the rotation reliably). While a sync is running, the dashboard listens for completion two ways: a Supabase Realtime channel on task_registry, plus a 5-second polling fallback against /dashboard/init capped at 60 seconds — so the Synced at … clock advances even when the Realtime channel is torn down by the iOS PWA freezer.

Step by Step

Your wearable sends data to PIRX through a service called Terra via webhooks. A Celery background worker picks up each new activity and runs it through the cleaning pipeline: only running types are kept; runs shorter than 1,600 meters or 180 seconds are dropped; pace outside 2:23-15:00 per km is rejected; any run faster than 1.5 times your personal average pace is flagged as suspect. Activities that pass cleaning trigger a full feature recompute (rolling distances over 7, 21, 42, and 90 days; zone percentages; ACWR; efficiency metrics) followed by a projection recompute for all six race distances. The timestamp of the last successful sync is stored in the database and the browser subtracts it from the current time to show '5m ago' or '2h ago.'

On this page