AUDIT
Platform parity
Checkpoints ships a Next.js web app and an Expo mobile app against one shared package. Mobile is behind, and closing that gap is active work — so the gap itself is tracked here rather than described in a doc that goes stale.
- COVERAGE
- 38%
- BOTH PLATFORMS
- 20
- WEB ONLY
- 26
- MOBILE ONLY
- 6
Implemented on both
Missing on mobile
Missing on web
Highest-impact gaps
Web-only components ranked by how many web files import them. A component used in 40 places on web is a bigger mobile hole than one used twice.
Variant drift
Components that exist on both platforms but don't expose the same options. This is the parity gap that's easiest to miss — the import resolves, the types pass, and the mobile screen quietly can't render the variant the design calls for.
- variant
defaultline
Full matrix
Every component, both platforms. Mobile-only rows are just as interesting as web-only ones — they're usually platform primitives (bottom sheets, tab bars) with no web equivalent, but sometimes they're divergence.
| COMPONENT | STATUS | WEB | MOBILE | WEB IMPORTS | MOBILE IMPORTS |
|---|---|---|---|---|---|
| IconSymbol | MOBILE ONLY | Web: NO | Mobile: YES | 0 | 0 |
| TabBarBackground | MOBILE ONLY | Web: NO | Mobile: YES | 0 | 1 |
| alert-dialog | WEB ONLY | Web: YES | Mobile: NO | 2 | 0 |
| animated-sparkle | WEB ONLY | Web: YES | Mobile: NO | 2 | 0 |
| app-tabs | WEB ONLY | Web: YES | Mobile: NO | 0 | 0 |
| avatar | BOTH | Web: YES | Mobile: YES | 0 | 4 |
| back-button | WEB ONLY | Web: YES | Mobile: NO | 16 | 0 |
| badge | BOTH | Web: YES | Mobile: YES | 11 | 9 |
| bottom-sheet | MOBILE ONLY | Web: NO | Mobile: YES | 0 | 16 |
| braille-spinner | WEB ONLY | Web: YES | Mobile: NO | 45 | 0 |
| button | BOTH | Web: YES | Mobile: YES | 86 | 28 |
| card | BOTH | Web: YES | Mobile: YES | 0 | 0 |
| chart | WEB ONLY | Web: YES | Mobile: NO | 1 | 0 |
| command | WEB ONLY | Web: YES | Mobile: NO | 1 | 0 |
| dialog | BOTH | Web: YES | Mobile: YES | 44 | 8 |
| drawer | WEB ONLY | Web: YES | Mobile: NO | 4 | 0 |
| dropdown-menu | WEB ONLY | Web: YES | Mobile: NO | 3 | 0 |
| filter-chips | BOTH | Web: YES | Mobile: YES | 9 | 5 |
| form-field | MOBILE ONLY | Web: NO | Mobile: YES | 0 | 3 |
| fullscreen-modal | BOTH | Web: YES | Mobile: YES | 7 | 4 |
| hours-input | WEB ONLY | Web: YES | Mobile: NO | 2 | 0 |
| input | BOTH | Web: YES | Mobile: YES | 27 | 8 |
| journey-icon | WEB ONLY | Web: YES | Mobile: NO | 6 | 0 |
| label | BOTH | Web: YES | Mobile: YES | 20 | 1 |
| logo-mark | BOTH | Web: YES | Mobile: YES | 2 | 1 |
| mobile-notifications-bell | WEB ONLY | Web: YES | Mobile: NO | 4 | 0 |
| notched-card | BOTH | Web: YES | Mobile: YES | 4 | 3 |
| onboarding-progress | WEB ONLY | Web: YES | Mobile: NO | 1 | 0 |
| page-header | WEB ONLY | Web: YES | Mobile: NO | 22 | 0 |
| pixel-icon | WEB ONLY | Web: YES | Mobile: NO | 17 | 0 |
| popover | WEB ONLY | Web: YES | Mobile: NO | 1 | 0 |
| scroll-row | WEB ONLY | Web: YES | Mobile: NO | 3 | 0 |
| section-card | BOTH | Web: YES | Mobile: YES | 9 | 3 |
| section-tabs | WEB ONLY | Web: YES | Mobile: NO | 3 | 0 |
| select | BOTH | Web: YES | Mobile: YES | 1 | 1 |
| separator | BOTH | Web: YES | Mobile: YES | 3 | 0 |
| skeleton | BOTH | Web: YES | Mobile: YES | 5 | 1 |
| sonner | WEB ONLY | Web: YES | Mobile: NO | 1 | 0 |
| sparkle-filled | WEB ONLY | Web: YES | Mobile: NO | 3 | 0 |
| stepper | WEB ONLY | Web: YES | Mobile: NO | 2 | 0 |
| switch | BOTH | Web: YES | Mobile: YES | 12 | 3 |
| table | WEB ONLY | Web: YES | Mobile: NO | 1 | 0 |
| tabs | BOTH | Web: YES | Mobile: YES | 5 | 1 |
| terminal-boot-lines | WEB ONLY | Web: YES | Mobile: NO | 1 | 0 |
| text | MOBILE ONLY | Web: NO | Mobile: YES | 0 | 113 |
| textarea | BOTH | Web: YES | Mobile: YES | 13 | 4 |
| themed-input | WEB ONLY | Web: YES | Mobile: NO | 1 | 0 |
| toast | MOBILE ONLY | Web: NO | Mobile: YES | 0 | 1 |
| toggle | BOTH | Web: YES | Mobile: YES | 1 | 1 |
| toggle-group | BOTH | Web: YES | Mobile: YES | 1 | 2 |
| tooltip | WEB ONLY | Web: YES | Mobile: NO | 1 | 0 |
| typewriter | WEB ONLY | Web: YES | Mobile: NO | 9 | 0 |
What this measures — and what it doesn't
Worth stating plainly, because a coverage number invites over-reading.
- It compares module presence, not visual fidelity. A component present on both platforms can still look wrong on one of them.
- It compares CVA variant options, which catches API drift but not styling drift inside a shared variant name.
- 6 mobile-only components are counted against coverage even though most are platform primitives with no meaningful web equivalent. The honest number is somewhere above 38%.
- Visual comparison is the missing half. Live mobile rendering via react-native-web is the next step — every preview on this site already has the mobile tab stubbed in.