Skip to content

dev/ds: live DS consolidation audit page (preview for design review)#2319

Open
0xkkonrad wants to merge 5 commits into
devfrom
feat/ds-audit-inventory
Open

dev/ds: live DS consolidation audit page (preview for design review)#2319
0xkkonrad wants to merge 5 commits into
devfrom
feat/ds-audit-inventory

Conversation

@0xkkonrad

Copy link
Copy Markdown
Contributor

Adds /dev/ds/audit — a live, filterable inventory of all 428 token/component/pattern implementations with real grep usage counts + dead-flags + 104 merge clusters, from the DS consolidation giga-sweep. Also makes /dev tooling routes public on non-prod deploys so the showcase is viewable on the Vercel preview without login (matching dev/layout intent; peanut.me stays gated).

Purpose: hand design (Vlad) a live URL to review the design-system consolidation. Not necessarily for merge — primarily for the preview deploy.

🤖 Generated with Claude Code

Adds /dev/ds/audit — a filterable inventory of all 428 token/style/component/
pattern implementations with real grep usage counts and dead/never-used flags,
plus the 104 proposed merge clusters. Data generated by the consolidation
giga-sweep (report in mono inbox/ds-consolidation-audit). Wires an Audit card
into the /dev/ds index and updates its stats to the audited numbers.
The (mobile-ui) auth guard redirected /dev/ds (and other DEV_ONLY_PUBLIC_ROUTES)
to /setup on any production build, even though dev/layout.tsx documents that all
/dev routes are meant to be accessible on localhost, staging, and Vercel previews.
Gate the public exemption on !peanut.me instead of IS_DEV so the design-system
showcase is viewable (no login) on preview deploys, while staying gated on peanut.me.
@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview, Comment Jul 1, 2026 11:36am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds a new design-system audit experience with reusable audit UI, generated usage datasets, and page shells for audit views. It also updates design-system navigation, related catalog pages, and dev-route exposure, plus expands mobile-ui public-route gating for additional dev tooling paths.

Changes

Design System Audit and Navigation

Layer / File(s) Summary
Audit UI and generated datasets
src/app/(mobile-ui)/dev/ds/_components/UsageAudit.tsx, src/app/(mobile-ui)/dev/ds/audit/app/audit-app-data.ts, src/app/(mobile-ui)/dev/ds/audit/components/audit-components-data.ts, src/app/(mobile-ui)/dev/ds/audit/app/page.tsx, src/app/(mobile-ui)/dev/ds/audit/components/page.tsx
Defines shared usage audit types and status metadata, renders the reusable usage audit UI, and adds the generated divergence and big-component dataset modules plus their page wrappers.
Audit page shell and section wiring
src/app/(mobile-ui)/dev/ds/audit/page.tsx, src/app/(mobile-ui)/dev/ds/_components/DocSidebar.tsx, src/app/(mobile-ui)/dev/ds/_components/nav-config.ts, src/app/(mobile-ui)/dev/ds/page.tsx
Builds the audit page chrome with tabs, filters, counts, inventory and cluster rendering, adds the audit sidebar and tier entries, and links the new audit page from the design-system index.
Related design-system pages and route exposure
.gitignore, src/app/(mobile-ui)/dev/ds/playground/page.tsx, src/app/(mobile-ui)/dev/ds/foundations/colors/page.tsx, src/app/(mobile-ui)/dev/ds/primitives/page.tsx, src/app/(mobile-ui)/dev/ds/primitives/title/page.tsx, src/constants/routes.ts
Updates the playground and primitives pages, marks dead background patterns in colors, exposes the standalone playground route in gitignore and nav config, and broadens dev-only public route matching.

Public Route Gating Update

Layer / File(s) Summary
devToolingPublic gating logic
src/app/(mobile-ui)/layout.tsx
Imports BASE_URL alongside IS_DEV and computes devToolingPublic from IS_DEV or a non-production BASE_URL before passing it into isPublicRoute with updated comments.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested labels: enhancement

Suggested reviewers: Hugo0

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly names the new DS audit page and its preview/design-review purpose.
Description check ✅ Passed The description matches the changes by describing the audit page, public dev routes, and preview deployment purpose.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch feat/ds-audit-inventory

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 5838.65 → 5062.69 (-775.96)
Findings: +20 net (+33 new, -13 resolved)

🆕 New findings (33)

  • critical complexity — src/app/(mobile-ui)/layout.tsx — CC 56, MI 55.92, SLOC 95
  • critical complexity — src/app/(mobile-ui)/dev/ds/_components/UsageAudit.tsx — CC 52, MI 65.91, SLOC 150
  • critical complexity — src/app/(mobile-ui)/dev/ds/audit/page.tsx — CC 52, MI 65.14, SLOC 141
  • critical complexity — src/app/(mobile-ui)/dev/ds/audit/app/audit-app-data.ts — CC 1, MI 17.99, SLOC 472
  • critical complexity — src/app/(mobile-ui)/dev/ds/audit/audit-data.ts — CC 1, MI 0, SLOC 4601
  • critical complexity — src/app/(mobile-ui)/dev/ds/audit/components/audit-components-data.ts — CC 1, MI 14.66, SLOC 612
  • high method-complexity — src/app/(mobile-ui)/layout.tsx:35 — CC 39 SLOC 65
  • high complexity — src/app/(mobile-ui)/dev/ds/_components/nav-config.ts — CC 1, MI 35.86, SLOC 109
  • medium high-mdd — src/app/(mobile-ui)/dev/ds/audit/page.tsx:28 — DesignSystemAuditPage: MDD 79.8 (uses across many lines from declarations)
  • medium high-mdd — src/app/(mobile-ui)/layout.tsx:35 — Layout: MDD 67.0 (uses across many lines from declarations)
  • medium high-mdd — src/app/(mobile-ui)/dev/ds/foundations/colors/page.tsx:31 — ColorsPage: MDD 57.0 (uses across many lines from declarations)
  • medium fan-in-high — src/app/(mobile-ui)/dev/ds/_components/DocPage.tsx — Imported by 30 files (high coupling)
  • medium high-mdd — src/app/(mobile-ui)/dev/ds/_components/UsageAudit.tsx:64 — UsageAudit: MDD 26.2 (uses across many lines from declarations)
  • medium high-mdd — src/app/(mobile-ui)/dev/ds/_components/DocSidebar.tsx:9 — DocSidebar: MDD 24.4 (uses across many lines from declarations)
  • medium complexity — src/app/(mobile-ui)/dev/ds/_components/DocSidebar.tsx — CC 19, MI 72.64, SLOC 32
  • medium complexity — src/app/(mobile-ui)/dev/ds/foundations/colors/page.tsx — CC 9, MI 59.78, SLOC 93
  • medium complexity — src/app/(mobile-ui)/dev/ds/page.tsx — CC 4, MI 62.03, SLOC 41
  • medium nextjs-missing-use-client — src/app/(mobile-ui)/dev/ds/audit/audit-data.ts:1 — Hooks used without use client directive
  • medium nextjs-raw-anchor — src/app/(mobile-ui)/dev/ds/audit/page.tsx:94 — Use next/link
  • medium nextjs-raw-anchor — src/app/(mobile-ui)/dev/ds/foundations/colors/page.tsx:118 — Use next/link

…and 13 more.

✅ Resolved (13)

  • src/app/(mobile-ui)/layout.tsx — CC 55, MI 56.06, SLOC 94
  • src/app/(mobile-ui)/layout.tsx:35 — CC 38 SLOC 64
  • src/app/(mobile-ui)/dev/ds/_components/nav-config.ts — CC 1, MI 37.42, SLOC 96
  • src/app/(mobile-ui)/layout.tsx:35 — Layout: MDD 68.0 (uses across many lines from declarations)
  • src/app/(mobile-ui)/dev/ds/foundations/colors/page.tsx:31 — ColorsPage: MDD 52.0 (uses across many lines from declarations)
  • src/app/(mobile-ui)/dev/ds/_components/DocPage.tsx — Imported by 28 files (high coupling)
  • src/app/(mobile-ui)/dev/ds/_components/DocSidebar.tsx:9 — DocSidebar: MDD 24.2 (uses across many lines from declarations)
  • src/app/(mobile-ui)/dev/ds/_components/DocSidebar.tsx — CC 18, MI 72.76, SLOC 32
  • src/app/(mobile-ui)/dev/ds/foundations/colors/page.tsx — CC 9, MI 59.87, SLOC 93
  • src/app/(mobile-ui)/dev/ds/page.tsx — CC 4, MI 63.51, SLOC 36
  • src/app/(mobile-ui)/layout.tsx:60 — useEffect with empty deps + setState — derived state anti-pattern
  • src/app/(mobile-ui)/layout.tsx:74 — direct DOM: document.querySelector
  • src/app/(mobile-ui)/dev/ds/page.tsx:40 — DesignSystemPage: exported fn missing return type annotation

📈 Painscore deltas (top movers)

File Before After Δ
src/app/(mobile-ui)/dev/ds/audit/audit-data.ts 0.0 13.0 +13.0
src/app/(mobile-ui)/dev/ds/audit/components/audit-components-data.ts 0.0 7.6 +7.6
src/app/(mobile-ui)/dev/ds/audit/app/audit-app-data.ts 0.0 7.2 +7.2
src/app/(mobile-ui)/dev/ds/audit/page.tsx 0.0 6.8 +6.8
src/app/(mobile-ui)/dev/ds/_components/UsageAudit.tsx 0.0 5.8 +5.8
src/app/(mobile-ui)/dev/ds/audit/app/page.tsx 0.0 1.8 +1.8
src/app/(mobile-ui)/dev/ds/audit/components/page.tsx 0.0 1.5 +1.5
src/components/AddMoney/components/SupportedNetworksModal.tsx 3.2 2.7 -0.5
src/components/LandingPage/marquee.tsx 2.4 1.9 -0.5
src/components/Kyc/KycFailedContent.tsx 2.4 1.9 -0.5
src/app/(mobile-ui)/badges/page.tsx 2.1 1.6 -0.5
src/app/(mobile-ui)/profile/page.tsx 2.1 1.6 -0.5
src/features/limits/components/FiatLimitsLockedCard.tsx 4.1 3.6 -0.5
src/components/LandingPage/Footer.tsx 4.1 3.6 -0.5
src/hooks/useDebounce.ts 4.0 3.5 -0.5
src/app/(mobile-ui)/dev/ds/foundations/spacing/page.tsx 3.3 2.8 -0.5
src/redux/hooks.ts 3.2 2.7 -0.5
src/components/Global/ErrorAlert/index.tsx 2.7 2.2 -0.5
src/app/kyc/success/page.tsx 2.7 2.2 -0.5
src/components/0_Bruddle/Checkbox.tsx 2.4 1.9 -0.5

@coderabbitai coderabbitai Bot added the enhancement New feature or request label Jul 1, 2026
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 1596 ran, 0 failed, 0 skipped, 25.3s

📊 Coverage (unit)

metric %
statements 54.2%
branches 36.7%
functions 41.6%
lines 54.0%
⏱ 10 slowest test cases
time test
3.6s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
0.5s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.4s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in updateUserById
0.3s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in updateUserById body
0.2s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Manteca PIX form ready shows merchant card + amount input + pay button
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid 9-digit US account
0.1s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Perk claim in progress shows disabled button + progress
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid German IBAN
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle too long for US account
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid UK IBAN with spaces
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/app/(mobile-ui)/dev/ds/audit/page.tsx (2)

7-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

STATUS_ORDER can silently drift from STATUS_META/AuditStatus.

STATUS_META is a Record<AuditStatus, …> so the compiler forces every status to be present, but STATUS_ORDER is a hand-written array with no such guarantee — if AuditStatus gains a new member later, STATUS_META will fail to compile (good), but STATUS_ORDER will happily stay stale and the new status simply won't get a filter chip (Line 156).

♻️ Derive order from the exhaustive map
-const STATUS_ORDER: AuditStatus[] = ['canonical', 'variant', 'duplicate', 'adhoc', 'dead']
+const STATUS_ORDER = Object.keys(STATUS_META) as AuditStatus[]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/dev/ds/audit/page.tsx around lines 7 - 14,
`STATUS_ORDER` is manually duplicated from `STATUS_META`/`AuditStatus` and can
go stale when statuses change. Update the audit page’s ordering logic in
`page.tsx` so the filter order is derived from the exhaustive `STATUS_META` map
(or otherwise tied to `AuditStatus`) instead of maintaining a separate
hard-coded array. Keep the existing `STATUS_META` keys as the single source of
truth and use them where the chips are rendered.

15-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the layer filter in sync with the generated data
LAYERS is hardcoded while audit-data.ts still types layer as string, so a new layer value can disappear from the filter chips without any type signal. Export a shared Layer union there (or derive the list from the data) and reuse it here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/dev/ds/audit/page.tsx at line 15, The layer filter in
the audit page is hardcoded and can drift from the generated audit data, so
update the shared layer source instead of keeping a local string list. Add or
reuse a exported Layer union from audit-data.ts, make the data and filter chips
use that type, and have the page’s LAYERS constant derive from the shared typed
source or reuse it directly so new layers can’t be added without compiler
coverage.
src/app/(mobile-ui)/dev/ds/page.tsx (2)

54-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hero subtitle omits the new Audit section.

The breadcrumb-style flow Foundations → Primitives → Patterns → Playground wasn't updated to include the newly added "Audit" section.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/dev/ds/page.tsx at line 54, The hero subtitle breadcrumb
in the dev DS page still uses Foundations → Primitives → Patterns → Playground
and needs to include the new Audit section. Update the subtitle text in the page
component that renders this breadcrumb so the flow reflects the added section,
keeping the existing ordering consistent with the new navigation structure.

31-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded audit stats can drift from the live totals.

These counts (428, 68, 104) are duplicated by hand here, while /dev/ds/audit computes the same values dynamically: const totals = useMemo(() => {... return { items: AUDIT_ITEMS.length, dead, clusters: AUDIT_CLUSTERS.length } }, []). Since this PR's stated goal is a "live" inventory that stays in sync, hardcoding these numbers on the index page defeats that purpose — any future edit to AUDIT_ITEMS/AUDIT_CLUSTERS will silently make this page's stats stale.

Consider extracting AUDIT_ITEMS/AUDIT_CLUSTERS (or the totals) to a shared module so both pages derive counts from the same source.

Based on the provided context, the audit page computes totals as "export default function DesignSystemAuditPage() { const [tab, setTab] = useState<'inventory' | 'clusters'>('inventory')" with totals derived from AUDIT_ITEMS.length, dead, and AUDIT_CLUSTERS.length, so keeping this index page's numbers in sync manually is fragile.

Also applies to: 60-62

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/dev/ds/page.tsx around lines 31 - 37, The Audit card
stats are hardcoded and can drift from the live data. Update the `Audit` entry
in the DS index page to derive its count, dead count, and cluster count from the
same source used by `DesignSystemAuditPage` (or a shared totals helper/module),
instead of duplicating `428`, `68`, and `104` by hand. Use the existing
`AUDIT_ITEMS` and `AUDIT_CLUSTERS` data flow or extract the `totals` calculation
so both pages stay synchronized automatically.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(mobile-ui)/dev/ds/audit/page.tsx:
- Around line 1-24: The Prettier check is failing for this component, so update
the formatting in the audit page module to match the repository style. Re-run
Prettier on the file containing STATUS_META, STATUS_ORDER, LAYERS, and
StatusChip, and make any whitespace, indentation, or wrapping changes needed so
pnpm prettier --check passes.

In `@src/app/`(mobile-ui)/layout.tsx:
- Around line 39-45: The dev-tooling public-path check in the mobile layout is
comparing the raw BASE_URL string, so a production URL variant like a trailing
slash can incorrectly make dev routes public. Update the devToolingPublic logic
in the layout component to use a normalized production-host check or existing
environment flag instead of direct string inequality, then pass that stable
boolean into isPublicRoute.

---

Nitpick comments:
In `@src/app/`(mobile-ui)/dev/ds/audit/page.tsx:
- Around line 7-14: `STATUS_ORDER` is manually duplicated from
`STATUS_META`/`AuditStatus` and can go stale when statuses change. Update the
audit page’s ordering logic in `page.tsx` so the filter order is derived from
the exhaustive `STATUS_META` map (or otherwise tied to `AuditStatus`) instead of
maintaining a separate hard-coded array. Keep the existing `STATUS_META` keys as
the single source of truth and use them where the chips are rendered.
- Line 15: The layer filter in the audit page is hardcoded and can drift from
the generated audit data, so update the shared layer source instead of keeping a
local string list. Add or reuse a exported Layer union from audit-data.ts, make
the data and filter chips use that type, and have the page’s LAYERS constant
derive from the shared typed source or reuse it directly so new layers can’t be
added without compiler coverage.

In `@src/app/`(mobile-ui)/dev/ds/page.tsx:
- Line 54: The hero subtitle breadcrumb in the dev DS page still uses
Foundations → Primitives → Patterns → Playground and needs to include the new
Audit section. Update the subtitle text in the page component that renders this
breadcrumb so the flow reflects the added section, keeping the existing ordering
consistent with the new navigation structure.
- Around line 31-37: The Audit card stats are hardcoded and can drift from the
live data. Update the `Audit` entry in the DS index page to derive its count,
dead count, and cluster count from the same source used by
`DesignSystemAuditPage` (or a shared totals helper/module), instead of
duplicating `428`, `68`, and `104` by hand. Use the existing `AUDIT_ITEMS` and
`AUDIT_CLUSTERS` data flow or extract the `totals` calculation so both pages
stay synchronized automatically.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6ecfb401-451e-412d-9ecc-fac4cdb95091

📥 Commits

Reviewing files that changed from the base of the PR and between efbb2bd and 6dcd896.

📒 Files selected for processing (4)
  • src/app/(mobile-ui)/dev/ds/audit/audit-data.ts
  • src/app/(mobile-ui)/dev/ds/audit/page.tsx
  • src/app/(mobile-ui)/dev/ds/page.tsx
  • src/app/(mobile-ui)/layout.tsx

Comment thread src/app/(mobile-ui)/dev/ds/audit/page.tsx
Comment on lines +39 to +45
// Allow access to public paths without authentication.
// Dev tooling routes (/dev/ds, /dev/components, gift-test, shake-test, …) are public
// on any non-production deploy — localhost, staging, Vercel previews — matching the
// intent documented in dev/layout.tsx. On peanut.me they stay gated (dev/layout 404s
// them anyway), so this only opens them where they're meant to be viewable.
const devToolingPublic = IS_DEV || BASE_URL !== 'https://peanut.me'
const isPublicPath = isPublicRoute(pathName, devToolingPublic)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Normalize the production host before making dev tooling public.

BASE_URL is env-driven, so a production value like https://peanut.me/ would make BASE_URL !== 'https://peanut.me' true and pass true into isPublicRoute, making dev-only routes public. Compare a parsed hostname or central production-environment flag instead of the raw full URL.

Suggested fix
-    const devToolingPublic = IS_DEV || BASE_URL !== 'https://peanut.me'
+    const baseHostname = (() => {
+        try {
+            return new URL(BASE_URL).hostname
+        } catch {
+            return BASE_URL
+        }
+    })()
+    const devToolingPublic = IS_DEV || baseHostname !== 'peanut.me'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Allow access to public paths without authentication.
// Dev tooling routes (/dev/ds, /dev/components, gift-test, shake-test, …) are public
// on any non-production deploy — localhost, staging, Vercel previews — matching the
// intent documented in dev/layout.tsx. On peanut.me they stay gated (dev/layout 404s
// them anyway), so this only opens them where they're meant to be viewable.
const devToolingPublic = IS_DEV || BASE_URL !== 'https://peanut.me'
const isPublicPath = isPublicRoute(pathName, devToolingPublic)
// Allow access to public paths without authentication.
// Dev tooling routes (/dev/ds, /dev/components, gift-test, shake-test, …) are public
// on any non-production deploy — localhost, staging, Vercel previews — matching the
// intent documented in dev/layout.tsx. On peanut.me they stay gated (dev/layout 404s
// them anyway), so this only opens them where they’re meant to be viewable.
const baseHostname = (() => {
try {
return new URL(BASE_URL).hostname
} catch {
return BASE_URL
}
})()
const devToolingPublic = IS_DEV || baseHostname !== 'peanut.me'
const isPublicPath = isPublicRoute(pathName, devToolingPublic)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/layout.tsx around lines 39 - 45, The dev-tooling
public-path check in the mobile layout is comparing the raw BASE_URL string, so
a production URL variant like a trailing slash can incorrectly make dev routes
public. Update the devToolingPublic logic in the layout component to use a
normalized production-host check or existing environment flag instead of direct
string inequality, then pass that stable boolean into isPublicRoute.

…usage relabels

Adds a second, real-usage-verified lens to the DS doc site so designers can see
what the live product actually renders vs. what only exists in code/showcase.

Nav
- Audit is now a top-level tier with a sub-nav: Code Audit / App Divergences /
  Big Components (everything reachable from the navbar, incl. the audits).

Relabels (the old audit conflated code call-sites with app usage)
- /dev/ds/audit reframed as a CODE audit (DRY consolidation); adds a caveat that
  its counts include /dev showcase + tests and cross-links to App Divergences.
- Title primitive marked unused ("dead in product" — MarketingHero is its only
  real call-site) in the primitives index + detail page.
- bg-peanut-repeat-* flagged DEAD-IN-PRODUCT (0 real usages) in Foundations/Colors.

New pages (data grep-verified, dead claims adversarially re-verified)
- /dev/ds/audit/app  — App Divergences: 65 items across primitives, buttons,
  pills, tokens; real vs dev usage; 8 showcase-only, 13 dead.
- /dev/ds/audit/components — Big Components: 85 items across modals (36), drawers,
  lists, composite cards; each with real usage + how it diverges from siblings.
- Shared UsageAudit explorer (live/showcase-only/dead legend, filters, counts).
…nesses

The Playground nav pointed at /dev/ds/playground/* routes that never existed
(the whole tier 404'd). Fix:
- add /dev/ds/playground index page listing the real harnesses
- repoint sub-nav to the standalone pages: /dev/shake-test, /dev/perk-success-test,
  /dev/share-builder
- allow perk-success-test + share-builder in DEV_ONLY_PUBLIC_ROUTES_REGEX so they
  don't bounce to /setup on non-prod deploys
- .gitignore: exempt the ds playground route from the broad 'playground/' ignore

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/app/(mobile-ui)/dev/ds/_components/UsageAudit.tsx (2)

160-185: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Filter toggle buttons could expose selected state via aria-pressed.

Selection is currently conveyed only through color/border styling; adding aria-pressed={cat === c} / aria-pressed={status === s} would help assistive tech users perceive the active filter.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/dev/ds/_components/UsageAudit.tsx around lines 160 -
185, The filter toggle buttons in UsageAudit currently indicate selection only
through styling; update the category and status button groups so the buttons
expose their active state with aria-pressed. Add aria-pressed based on cat === c
and status === s in the mapped button elements, keeping the existing setCat and
setStatus handlers unchanged.

154-159: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Search input lacks an accessible label.

Only a placeholder is provided; screen-reader users have no accessible name for this control once text is entered (placeholders aren't a reliable substitute for labels).

♿ Proposed fix
                 <input
+                    aria-label="Search name / divergence / file"
                     value={q}
                     onChange={(e) => setQ(e.target.value)}
                     placeholder="Search name / divergence / file…"
                     className="w-full rounded-sm border border-n-1 bg-white px-3 py-2 text-sm outline-none focus:border-primary-1"
                 />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/dev/ds/_components/UsageAudit.tsx around lines 154 -
159, The search field in UsageAudit’s input control is missing an accessible
name because it only uses a placeholder. Update the input in UsageAudit to
include a proper label association or an equivalent accessible name (for example
via a visible label, aria-label, or aria-labelledby) while keeping the existing
search behavior and styling intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(mobile-ui)/dev/ds/audit/page.tsx:
- Around line 94-96: The internal navigation link in the audit page uses a plain
anchor tag, which triggers the Next.js no-html-link-for-pages rule. Update the
App Divergences link in page.tsx to use Next.js Link from next/link instead of
<a>, keeping the same href and styling so client-side routing is used. Locate
the change in the component rendering the App Divergences navigation.

In `@src/app/`(mobile-ui)/dev/ds/foundations/colors/page.tsx:
- Around line 112-121: Replace the raw internal anchor in the colors page with
Next.js navigation by using the existing link component import pattern in the
page component. Update the `DesignNote` content that links to
`/dev/ds/audit/app` so it uses `next/link` instead of `<a>`, keeping the same
text and underline styling while preserving internal routing behavior.

In `@src/constants/routes.ts`:
- Around line 111-115: The DEV_ONLY_PUBLIC_ROUTES_REGEX in routes constants is
too permissive for the dev/ds and dev/components branches and matches partial
segments like /dev/dsfoo. Tighten the regex in DEV_ONLY_PUBLIC_ROUTES_REGEX by
adding a path boundary/end anchor for those dev-only routes so only the exact
intended public paths match when devToolingPublic is enabled.

---

Nitpick comments:
In `@src/app/`(mobile-ui)/dev/ds/_components/UsageAudit.tsx:
- Around line 160-185: The filter toggle buttons in UsageAudit currently
indicate selection only through styling; update the category and status button
groups so the buttons expose their active state with aria-pressed. Add
aria-pressed based on cat === c and status === s in the mapped button elements,
keeping the existing setCat and setStatus handlers unchanged.
- Around line 154-159: The search field in UsageAudit’s input control is missing
an accessible name because it only uses a placeholder. Update the input in
UsageAudit to include a proper label association or an equivalent accessible
name (for example via a visible label, aria-label, or aria-labelledby) while
keeping the existing search behavior and styling intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 18f8454b-2e05-468e-950c-4be677894720

📥 Commits

Reviewing files that changed from the base of the PR and between 6dcd896 and ea99e97.

📒 Files selected for processing (16)
  • .gitignore
  • src/app/(mobile-ui)/dev/ds/_components/DocSidebar.tsx
  • src/app/(mobile-ui)/dev/ds/_components/UsageAudit.tsx
  • src/app/(mobile-ui)/dev/ds/_components/nav-config.ts
  • src/app/(mobile-ui)/dev/ds/audit/app/audit-app-data.ts
  • src/app/(mobile-ui)/dev/ds/audit/app/page.tsx
  • src/app/(mobile-ui)/dev/ds/audit/audit-data.ts
  • src/app/(mobile-ui)/dev/ds/audit/components/audit-components-data.ts
  • src/app/(mobile-ui)/dev/ds/audit/components/page.tsx
  • src/app/(mobile-ui)/dev/ds/audit/page.tsx
  • src/app/(mobile-ui)/dev/ds/foundations/colors/page.tsx
  • src/app/(mobile-ui)/dev/ds/page.tsx
  • src/app/(mobile-ui)/dev/ds/playground/page.tsx
  • src/app/(mobile-ui)/dev/ds/primitives/page.tsx
  • src/app/(mobile-ui)/dev/ds/primitives/title/page.tsx
  • src/constants/routes.ts
✅ Files skipped from review due to trivial changes (2)
  • src/app/(mobile-ui)/dev/ds/audit/components/audit-components-data.ts
  • src/app/(mobile-ui)/dev/ds/audit/app/audit-app-data.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/(mobile-ui)/dev/ds/page.tsx

Comment on lines +94 to +96
<a href="/dev/ds/audit/app" className="font-bold underline">
App Divergences →
</a>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use next/link instead of <a> for internal navigation.

Static analysis flags this as a Next.js no-html-link-for-pages violation for internal route /dev/ds/audit/app.

🔧 Proposed fix
+import Link from 'next/link'
...
-                <a href="/dev/ds/audit/app" className="font-bold underline">
+                <Link href="/dev/ds/audit/app" className="font-bold underline">
                     App Divergences →
-                </a>
+                </Link>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<a href="/dev/ds/audit/app" className="font-bold underline">
App Divergences
</a>
<Link href="/dev/ds/audit/app" className="font-bold underline">
App Divergences
</Link>
🧰 Tools
🪛 ESLint

[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 94-94: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/dev/ds/audit/page.tsx around lines 94 - 96, The internal
navigation link in the audit page uses a plain anchor tag, which triggers the
Next.js no-html-link-for-pages rule. Update the App Divergences link in page.tsx
to use Next.js Link from next/link instead of <a>, keeping the same href and
styling so client-side routing is used. Locate the change in the component
rendering the App Divergences navigation.

Source: Linters/SAST tools

Comment on lines +112 to +121
<DesignNote type="warning">
DEAD IN PRODUCT —{' '}
<code className="rounded bg-white px-1 font-mono text-[10px]">bg-peanut-repeat-*</code> (normal /
large / small) are defined in the Tailwind theme but rendered on{' '}
<span className="underline">zero</span> real app screens (0 non-dev, non-test call-sites).
Don&rsquo;t treat these as design-system tokens — they&rsquo;re delete-candidates. See{' '}
<a href="/dev/ds/audit/app" className="underline">
App Divergences →
</a>
</DesignNote>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use next/link instead of raw <a> for internal navigation.

ESLint's @next/next/no-html-link-for-pages flags this anchor to /dev/ds/audit/app, an internal route.

🔧 Proposed fix
+import Link from 'next/link'
...
-                    <a href="/dev/ds/audit/app" className="underline">
+                    <Link href="/dev/ds/audit/app" className="underline">
                         App Divergences →
-                    </a>
+                    </Link>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<DesignNote type="warning">
DEAD IN PRODUCT {' '}
<code className="rounded bg-white px-1 font-mono text-[10px]">bg-peanut-repeat-*</code> (normal /
large / small) are defined in the Tailwind theme but rendered on{' '}
<span className="underline">zero</span> real app screens (0 non-dev, non-test call-sites).
Don&rsquo;t treat these as design-system tokens they&rsquo;re delete-candidates. See{' '}
<a href="/dev/ds/audit/app" className="underline">
App Divergences
</a>
</DesignNote>
import Link from 'next/link'
<DesignNote type="warning">
DEAD IN PRODUCT {' '}
<code className="rounded bg-white px-1 font-mono text-[10px]">bg-peanut-repeat-*</code> (normal /
large / small) are defined in the Tailwind theme but rendered on{' '}
<span className="underline">zero</span> real app screens (0 non-dev, non-test call-sites).
Don&rsquo;t treat these as design-system tokens they&rsquo;re delete-candidates. See{' '}
<Link href="/dev/ds/audit/app" className="underline">
App Divergences
</Link>
</DesignNote>
🧰 Tools
🪛 ESLint

[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)


[error] 118-118: Do not use an <a> element to navigate to /dev/ds/audit/app/. Use <Link /> from next/link instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages

(@next/next/no-html-link-for-pages)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/dev/ds/foundations/colors/page.tsx around lines 112 -
121, Replace the raw internal anchor in the colors page with Next.js navigation
by using the existing link component import pattern in the page component.
Update the `DesignNote` content that links to `/dev/ds/audit/app` so it uses
`next/link` instead of `<a>`, keeping the same text and underline styling while
preserving internal routing behavior.

Source: Linters/SAST tools

Comment thread src/constants/routes.ts
Comment on lines +111 to +115
* Regex for dev-only public routes (dev index, gift-test, shake-test, ds playground harnesses)
* Only matched when IS_DEV is true (or on non-production deploys)
*/
export const DEV_ONLY_PUBLIC_ROUTES_REGEX = /^\/(dev$|dev\/gift-test|dev\/shake-test|dev\/ds|dev\/components)/
export const DEV_ONLY_PUBLIC_ROUTES_REGEX =
/^\/(dev$|dev\/gift-test|dev\/shake-test|dev\/perk-success-test|dev\/share-builder|dev\/ds|dev\/components)/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Regex allows partial-segment matches for dev/ds and dev/components.

Without a trailing boundary, paths like /dev/dsfoo or /dev/componentsHidden would also match and become public whenever devToolingPublic is true. Low risk since this only applies on non-production deploys, but worth tightening.

🔒 Proposed fix
-export const DEV_ONLY_PUBLIC_ROUTES_REGEX =
-    /^\/(dev$|dev\/gift-test|dev\/shake-test|dev\/perk-success-test|dev\/share-builder|dev\/ds|dev\/components)/
+export const DEV_ONLY_PUBLIC_ROUTES_REGEX =
+    /^\/(dev$|dev\/gift-test|dev\/shake-test|dev\/perk-success-test|dev\/share-builder|dev\/ds(\/|$)|dev\/components(\/|$))/
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* Regex for dev-only public routes (dev index, gift-test, shake-test, ds playground harnesses)
* Only matched when IS_DEV is true (or on non-production deploys)
*/
export const DEV_ONLY_PUBLIC_ROUTES_REGEX = /^\/(dev$|dev\/gift-test|dev\/shake-test|dev\/ds|dev\/components)/
export const DEV_ONLY_PUBLIC_ROUTES_REGEX =
/^\/(dev$|dev\/gift-test|dev\/shake-test|dev\/perk-success-test|dev\/share-builder|dev\/ds|dev\/components)/
* Regex for dev-only public routes (dev index, gift-test, shake-test, ds playground harnesses)
* Only matched when IS_DEV is true (or on non-production deploys)
*/
export const DEV_ONLY_PUBLIC_ROUTES_REGEX =
/^\/(dev$|dev\/gift-test|dev\/shake-test|dev\/perk-success-test|dev\/share-builder|dev\/ds(\/|$)|dev\/components(\/|$))/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/constants/routes.ts` around lines 111 - 115, The
DEV_ONLY_PUBLIC_ROUTES_REGEX in routes constants is too permissive for the
dev/ds and dev/components branches and matches partial segments like /dev/dsfoo.
Tighten the regex in DEV_ONLY_PUBLIC_ROUTES_REGEX by adding a path boundary/end
anchor for those dev-only routes so only the exact intended public paths match
when devToolingPublic is enabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant