Scan complete · 3286ms · 3,999 code files

Design System Diagnosis

dubinc/dub · scanned 2026-08-12
Health score
15/100
nextTypeScriptTailwind CSSCVAmonorepo
Summary
621 arbitrary values like [400px] punched through the Tailwind scale. 22 components implemented more than once. 59 off-scale spacing values where a dozen would do. Messier than the median of 30 scanned repos on 6 of 6 core metrics. And the median repo is already a mess.

Where to start

Three tweaks · 15 → 45

01
Collapse the 14 near-identical colours
+10
#ffffff and #fafafa are the same colour to any eye, and they are used 9 times between them. Nobody chose to have both. Pick the one that is already a token, point the other at it, and the pair stops multiplying.
02
Tokenise the 55 stray colours
+10
They are hardcoded where no token names them; apps/web/ui/partners/payouts/stablecoin-payout-modal.tsx alone carries 15. Every one is a value your agent will happily copy.
03
Decide about the 16 components nobody imports
+10
<Alert>, <AlertDescription>, <AlertTitle> and others sit in the system with no callers. Adopt them or delete them: either answer is better than a system with rooms nobody enters.

You sat through the roast

so you get a present.

104
distinct colours
Ideal Design System~24
Avg Design System96
Reputable systems24
15
shades of grey
Ideal Design System~13
Avg Design System14
Reputable systems5
59
off-scale spacing values
Ideal Design System~12
Avg Design System27 · messier than 77%
Reputable systems6
22
duplicated components
Ideal Design System0
Avg Design System14 · messier than 63%
Reputable systems10
47
inline style blocks
Ideal Design System0
Avg Design System45
Reputable systems12
14
near-identical colour pairs
Ideal Design System0
Avg Design System3 · messier than 63%
Reputable systems1
1
!important declarations
Ideal Design System0
Avg Design System5
Reputable systems3
16
components never imported
Ideal Design System0
Avg Design System13 · messier than 77%
Reputable systems0
621
arbitrary bracket values
Ideal Design System~20
Avg Design System91 · messier than 90%
Reputable systems0

Package by package

2 packages with enough UI to judge · the repo score above is the whole thing blended, and 7 packages were too small or too backend to score

packagescoreworst findingsize
apps/web 40 38 inline style blocks 3,274 files
packages/ui 80 16 components nobody imports 475 files

A repo scores below its own packages by arithmetic, not by accident: distinct values add up across packages, so the whole always carries more than any part. Read the package scores for where each team stands, and the repo score for what your agent sees when it looks at everything at once.

What your AI agent sees today

No CLAUDE.md, no AGENTS.md, no .cursorrules. Every time your AI builds UI here, it guesses, from everything below. This is why its output looks almost-but-not-quite right.

Palette
104colours

A healthy product palette is up to ~24 colours: one brand hue with a few tints, one accent, up to 13 greys, and status colours.

49 tokens55 strays
Colour usage
Sized by how often each is used
token stray
+44
Grey ramp · sorted dark → light · how many can you tell apart?
14 nearly identical pairs · copy-paste, not decisions
#ffffff ×7 #fafafa ×2#d4d4d4 ×3 #d1d5db ×2#f5f5f5 ×3 #f0f0f0 ×2#eab308 ×2 #efb100 ×1#db2777 ×2 #da2778 ×1#ede8fd ×1 #f5edff ×1#ede8fd ×1 #ede9fe ×1#ede8fd ×1 #f3e8ff ×1+6 more

59 off-scale spacing values

a disciplined repo keeps these around a dozen · on-scale Tailwind steps (·) shown for context · off-scale in coral

·2
2,698
·4
1,924
·3
1,482
·1
1,106
·6
1,034
·0
798
·1.5
582
·2.5
395
·5
373
·0.5
269
·8
249
·10
217
·px
177
·16
89
·12
86
·3.5
33
·7
33
·20
22
621 arbitrary values punched through the scale, one bracket at a time
[400px] ×24[0.625rem] ×20[300px] ×19[200px] ×17[10px] ×17[180px] ×16[1200px] ×14[50px] ×12[18px] ×11[360px] ×11+169 more

Typography & shape

3
typefaces
Ideal Design System~3 =
Avg Design System2
Reputable systems1
39
font sizes
Ideal Design System~10
Avg Design System16 · messier than 87%
Reputable systems6
25
border radii
Ideal Design System~10
Avg Design System12 · messier than 77%
Reputable systems2
the font sizes, by use
·sm ×2234·xs ×804·lg ×268·base ×230·xl ×69·3xl ×14·2xl ×14·[0.625rem] ×12·4xl ×10·[13px] ×10·5xl ×8·[0.8125rem] ×7·[0.7rem] ×6·[11px] ×5
the corners, drawn · 25 radii in one interface
999px ×3
50% ×2
10px ×1

3 typefaces, declared 5 different ways

every distinct declaration is a chance for the next one to be wrong

system-ui×2
Inter×1
satoshi×1
Geist×1
ui-monospace×1

Where it hurts most

the 5 files carrying the most off-system styling

Duplicated components

every duplicate is a place where your agent has to guess which one is canonical, and it picks wrong half the time. Paths open in VS Code

two icon sets collide on 11 names · one problem, not 11
<Lock><Users><Download><CursorRays><Hyperlink><User><Gear><Eye><LinesY><ConnectedDots4><Heart>

apps/web/ui/shared/icons/lock.tsx vs packages/ui/src/icons/nucleo/lock.tsx

<EmptyState> · defined twice, one wraps the other
dropdown family · 8 variants
<FolderDropdown>
apps/web/ui/folders/folder-dropdown.tsx
used 3×
<PartnerProgramDropdown>
apps/web/ui/layout/sidebar/partner-program-dropdown.tsx
used 3×
<UserDropdown>
apps/web/ui/layout/sidebar/user-dropdown.tsx
used 2×
<MoreDropdown>
apps/web/ui/links/link-builder/more-dropdown.tsx
used 1×
<PayoutMethodDropdown>
apps/web/ui/partners/payouts/payout-method-dropdown.tsx
used 1×
<SubmittedLeadStatusDropdown>
apps/web/ui/submitted-leads/submitted-lead-status-dropdown.tsx
used 1×
…and 2 more
header family · 8 variants
<InviteSheetHeader>
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/invite-sheet-ui.tsx
used 2×
<LinkBuilderHeader>
apps/web/ui/links/link-builder/link-builder-header.tsx
used 2×
<PageContentHeader>
apps/web/ui/layout/page-content/page-content-header.tsx
used 2×
<BountyHeaderTitle>
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/[bountyId]/bounty-header.tsx
used 1×
<GroupHeaderTabs>
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/groups/[groupSlug]/group-header.tsx
used 1×
<GroupHeaderTitle>
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/groups/[groupSlug]/group-header.tsx
used 1×
…and 2 more
avatar family · 7 variants
<PartnerAvatar>
apps/web/ui/partners/partner-avatar.tsx
used 74×
<UserAvatar>
apps/web/ui/users/user-avatar.tsx
used 34×
<CustomerAvatar>
apps/web/ui/customers/customer-avatar.tsx
used 9×
<TokenAvatar>
apps/web/ui/token-avatar.tsx
used 9×
<Avatar>
packages/ui/src/avatar.tsx
used 3×
<ActivityLogUserAvatar>
apps/web/ui/activity-logs/activity-entry-chips.tsx
used 2×
…and 1 more
alert family · 7 variants
<AlertCircleFill>
apps/web/ui/shared/icons/alert-circle-fill.tsx
used 12×
<ShieldAlert>
packages/ui/src/icons/nucleo/shield-alert.tsx
used 2×
<ReviewFraudAlertSheet>
apps/web/app/(ee)/admin.dub.co/(dashboard)/partners/fraud/review-fraud-alert-sheet.tsx
used 1×
<Alert>
packages/ui/src/alert.tsx
<AlertDescription>
packages/ui/src/alert.tsx
<AlertTitle>
packages/ui/src/alert.tsx
…and 1 more
progress family · 6 variants
<ProgressCircle>
packages/ui/src/progress-circle.tsx
used 6×
<StepProgressBar>
apps/web/ui/partners/merge-accounts/step-progress-bar.tsx
used 4×
<BountyProgressBarRow>
apps/web/ui/partners/bounties/bounty-progress-bar-row.tsx
used 3×
<PerformanceBountyProgress>
apps/web/ui/partners/bounties/bounty-performance.tsx
used 3×
<SubmissionBountyProgress>
apps/web/ui/partners/bounties/bounty-performance.tsx
used 3×
<ProgressBar>
packages/ui/src/progress-bar.tsx
sidebar family · 6 variants
<LayoutSidebar>
packages/ui/src/icons/nucleo/layout-sidebar.tsx
used 1×
<MarketplaceSidebarFilters>
apps/web/ui/program-marketplace/marketplace-sidebar-filters.tsx
used 1×
<ProgramSidebar>
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/apply/program-sidebar.tsx
used 1×
<SidebarProvider>
apps/web/app/(ee)/app.dub.co/(new-program)/sidebar-context.tsx
used 1×
<SidebarUsage>
apps/web/ui/layout/sidebar/sidebar-usage.tsx
used 1×
<FilterSidebar>
packages/ui/src/filter/filter-sidebar.tsx

What you actually use

1,555 components defined · top by adoption · the real system, buried in here

componentuseddefined inprops
<Button> 963× packages/ui/src/button.tsx text variant textWrapperClassName shortcutClassName loading
<Link> 615× apps/web/ui/shared/icons/link.tsx none
<Modal> 183× packages/ui/src/modal.tsx showModal setShowModal onClose desktopOnly preventDefaultClose
<Tooltip> 145× packages/ui/src/tooltip.tsx content contentClassName disabled side disableHoverableContent
<LoadingSpinner> 110× packages/ui/src/icons/loading-spinner.tsx none
<Footer> 106× packages/email/src/components/footer.tsx email marketing unsubscribeUrl https notificationSettingsUrl
<Footer> 106× packages/ui/src/footer.tsx staticDomain
<Popover> 100× packages/ui/src/popover.tsx content align side openPopover setOpenPopover
<InfoTooltip> 97× packages/ui/src/tooltip.tsx none
<AnimatedSizeContainer> 88× packages/ui/src/animated-size-container.tsx none
16 components defined but never imported · candidates for deletion, or the system nobody found
<Alert><AlertDescription><AlertTitle><CardContext><CardListCard><CompositeLogo><DubWireframeGraphic><FilterList>+8 more

Routers, dynamic imports and barrel files can hide real usage, so treat this as a shortlist to check, not a demolition order.