Repository navigation
TASK-23054: Home onboarding is one checklist until the first spend - #3474
Conversation
Home told users holding money to add money. The step read only the API milestone, which needs a posted ledger credit, and ignored card collateral; the wallet balance counted only for the card upgrade. One rule now decides funded for the step and the checklist: milestone funded, or any wallet USDC or card collateral. The activation_step_viewed event follows the same step.
Hugo approved option A: new users saw a checklist, then a large card step, then a spend card, with rules that disagreed about money ($0.17 by crypto stayed on Add money). Home now shows one checklist — Create account, Verify identity, Add money, Make the first payment — and the carousel only after it. Add money is done on any money received or held (wallet or card collateral). The payment row exists only for users who can make an activating spend and completes on the API activation, so Lexicon v2 and Rewards gating are unchanged. A closed carousel card stays closed (app install excepted), and Pay with QR needs a QR rail.
…add-money # Conflicts: # src/features/home/HomePage.tsx
…ure opens the chooser The first-payment row no longer draws a hand-rolled arrow, so its icon exemption goes.
|
/chip review |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository: peanutprotocol/peanut-ui/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
Code-analysis diffPainscore total: 8912.33 → 8935.2 (+22.87) 🆕 New findings (50)
…and 30 more. ✅ Resolved (38)
…and 18 more. 📈 Painscore deltas (top movers)
|
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
There was a problem hiding this comment.
Chip review — no blocking findings — this is not an approval
The review found two Home handoff defects, a PR-caused screen-test failure, and stale canonical funnel documentation.
Findings
-
MAJOR · src/hooks/useActivationStatus.ts:55 · Do not treat an unresolved card path as no spend path
For a verified, funded, not-yet-activated account with no QR rail, useCardInfo initially has no data, so canSpendPathViaCard is false and this selector returns none. resolveOnboarding then marks the three-row list completed and Home shows the carousel; when card info loads and permits a card, Home swaps back to the first-payment checklist. If the card-info request fails, the payment row never appears. Keep card eligibility unknown until the query resolves and avoid completing onboarding from that unknown state; cover this loading/error transition in Home tests. -
MAJOR · src/features/home/HomePage.tsx:71 · Preserve provider-rejection override after three-row completion
A verified account that has received crypto, has no card or QR spend path, and has a blocked bank rail is marked onboarding-complete once Add money is done. This branch renders the carousel and never mounts ActivationCTAs, where the provider-rejection card and its support/retry action are selected. The old funded outbound path showed that rejection. Evaluate the rejection override before handing this cohort to the carousel, or move the override into the Home arbiter; add a funded-and-rejected case. -
MAJOR · src/i18n/app/messages/es-419.json:106 · Repair the capture-copy lookup after deleting the outbound CTA key
The screen-tests check fails at this head: capture-copy.mjs still maps Start Spending to home.activation.steps.outbound.cta, which this deletion removes. In es-419 the lookup now returns the English fallback instead of Empezar a gastar (the same stale path affects the other locales). Update the capture-copy mapping and its expected checkpoint to a live string, or remove the obsolete checkpoint, so pnpm screens:test passes. -
MINOR · src/features/home/HomePage.tsx:28 · Update the canonical activation-funnel description
This new Home rule keeps the checklist through first spend and removes the standalone post-funding card/outbound cards. The canonical mono product/activation-funnel.md still says the checklist is pre-funding only and a funded account sees a separate spend card. Coordinate that source-of-truth update so future implementation and analytics work do not follow the superseded flow.
Checked clean
- Confirmed exact head and merge-base diff; the supplied base SHA is newer than the merge base, so unrelated withdraw changes were excluded.
- Read the trusted PR description, Home/activation/card access/verification/carousel paths, relevant tests, and the canonical funnel context.
- The screen-tests failure is the deleted outbound CTA translation path; typecheck, lint, format and wordiness checks were green when inspected.
- No earlier review findings were supplied; issue and review comments were not read.
Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short.
Third opinion: did not run — claude-api_error. This review is one reviewer short.
Exact head: 2f0d93c53a3f · Context: repo, product, lexicon · Took 10m
The surface capture now opens the chooser from the checklist row by test id, so the translated button label it keyed on no longer exists.
There was a problem hiding this comment.
Chip review — no blocking findings — this is not an approval
The capture-copy failure is fixed. Two Home handoff defects and the canonical funnel documentation drift remain.
Findings
-
MAJOR · src/hooks/useActivationStatus.ts:55 · Do not treat an unresolved card path as no spend path
For a verified, funded, not-yet-activated account with no QR rail, useCardInfo initially has no data, so canSpendPathViaCard is false and this selector returns none. resolveOnboarding marks the three-row list completed and Home shows the carousel; when card info loads and permits a card, Home swaps back to the first-payment checklist. If the card-info request fails, that payment row never appears. Keep card eligibility unknown until the query resolves and avoid completing onboarding from that unknown state; cover the loading/error transition in Home tests. -
MAJOR · src/features/home/HomePage.tsx:71 · Preserve provider-rejection override after three-row completion
A verified account that has received crypto, has no card or QR spend path, and has a blocked bank rail is marked onboarding-complete once Add money is done. This branch renders the carousel and never mounts ActivationCTAs, where the provider-rejection card and its support/retry action are selected. The old funded outbound path showed that rejection. Evaluate the rejection override before handing this cohort to the carousel, or move the override into the Home arbiter; add a funded-and-rejected case. -
MINOR · src/features/home/HomePage.tsx:28 · Update the canonical activation-funnel description
This new Home rule keeps the checklist through first spend and removes the standalone post-funding card/outbound cards. The canonical mono product/activation-funnel.md still says the checklist is pre-funding only and a funded account sees a separate spend card. Coordinate that source-of-truth update so future implementation and analytics work do not follow the superseded flow.
Checked clean
- Confirmed the exact new head, trusted PR metadata and merge-base diff; only capture-copy mapping and test changed since the prior review.
- P1 and P2 remain reachable in the current Home, card-access, and rejection paths; their diff anchors remain valid.
- P3 is fixed: the removed outbound copy lookup and its stale expected checkpoint are gone; node --test scripts/screens/capture-copy.test.mjs passed (3 tests).
- P4 remains unaddressed by this PR head. Exact-head CI checks had not yet registered when inspected.
- No issue or review comments were read.
Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short.
Third opinion: did not run — it reads only the first review of a pull request; the first reviewer checks later rounds. This review is one reviewer short.
Exact head: a71c3ee2e994 · Context: repo, product, lexicon · Took 6m
…ected rail outranks the carousel Chip review: a user with no QR rail read as 'no spend path' while card info was loading, so Home flashed the carousel and then swapped back. And a funded, verified user with no card or QR and a blocked bank rail lost the rejection card to the carousel. The rejection logic moves into useProviderRejection so HomePage and ActivationCTAs read one answer.
There was a problem hiding this comment.
Chip review — no blocking findings — this is not an approval
The provider-rejection handoff and capture-copy failure are fixed. Card-route uncertainty and canonical funnel documentation drift remain.
Findings
-
MAJOR · src/hooks/useActivationStatus.ts:68 · Keep an unknown or failed card route distinct from no card route
For a verified, funded account with no QR rail and an uncached card-info request, this computes route none while the query loads. resolveOnboarding keeps Home on the checklist, but GettingStartedChecklist renders only the three completed rows, showing 100% progress and no action; an eligible response then drops it to 75% and adds the card row. If the request fails, isLoading becomes false with cardInfo still absent, so this marks the route settled and switches to the carousel even though card eligibility is unknown. Represent pending/error separately, with a loading or retry affordance, and complete the three-row list only after a confirmed no-card result. -
MINOR · src/features/home/HomePage.tsx:29 · Update the canonical activation-funnel description
This new Home rule keeps the checklist through first spend and removes the standalone post-funding card/outbound cards. The canonical mono product/activation-funnel.md still says the checklist is pre-funding only and a funded account sees a separate spend card. Coordinate that source-of-truth update so future implementation and analytics work do not follow the superseded flow.
Checked clean
- Confirmed the exact new head, trusted PR metadata, and merge-base diff; reviewed all nine files changed since the prior head.
- P1/P5: the premature carousel during card-info loading is fixed, but the 100%-with-no-action loading state and failed-query handoff remain; P5 is a duplicate of P1.
- P2/P6: Home now evaluates the shared provider-rejection predicate before carousel handoff, and ActivationCTAs renders the rejection for a funded three-row account; fixed.
- P3: the obsolete capture-copy lookup is absent; focused capture-copy tests passed and exact-head screen-tests CI succeeded.
- P4/P7: this PR head does not update the previously verified canonical funnel description; P7 is a duplicate of P4.
- Exact-head eslint succeeded; unit and typecheck were still running when inspected. No issue or review comments were read.
Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short.
Third opinion: did not run — it reads only the first review of a pull request; the first reviewer checks later rounds. This review is one reviewer short.
Exact head: d17d4ab17333 · Context: repo, product, lexicon · Took 6m
|
English · Español · Español (Argentina) · Português (Brasil) After merge: f2cf582 → 3198989. Incomplete capture; unavailable states are listed in the report. |
🖼 Visual diff — 12 screens moved21 of 166 shots changed · 145 identical · baseline
new screens (13)
job summary · before/after/diff images — artifact Fixture screenshots, no backend. Advisory — this check never blocks a merge. Posted from the default branch by ds-shots-comment.yml; the report it renders is untrusted data. |
…known card eligibility Hugo: every checklist row is title plus one subtitle line in every state, sized to fit 320px in all four locales (done and in-review status moves to icon chips; the words sit on the subtitle line). Make the first payment offers QR or card to anyone who can reach either, including a new user in a QR country before verifying. Chip: loading or failed card info is not 'no card' — the payment row holds its place and the list cannot complete.
…add-money # Conflicts: # src/app/(mobile-ui)/dev/journey/journeyData.ts # src/components/Home/ActivationCTAs.tsx
Chip review — no blocking findings — this is not an approvalThe prior findings are fixed at this head. Two new issues remain: a known QR route is hidden when card lookup fails, and route analytics can be frozen at pending. Findings
Inline anchors unavailable for 2 finding(s); the findings remain in this summary. Checked clean
Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short. Third opinion: did not run — it reads only the first review of a pull request; the first reviewer checks later rounds. This review is one reviewer short. Exact head: |
TASK-23054. Hugo approved option A from the onboarding review (2026-09-25): one checklist on Home until the first spend, then the carousel. This replaces the narrower "any balance ticks Add money" fix.
What changes
Home shows one CTA class at a time. Until every checklist row is done, the slot shows the getting-started checklist. After that, it shows the carousel. The large deposit, card ("Spend anywhere Visa is accepted" / "Maybe later") and outbound ("Spend with Peanut" / "Start Spending") cards are gone. A due verification task card (#3467's
PendingVerificationTasksarbiter) still replaces both. This PR extends that arbiter and adds no second one.The checklist (
GettingStartedChecklist, rules insrc/utils/activation-step.utils.ts):verified. Whileprocessing, the subtitle says "In review" and a status chip shows/profile/accounts)funded/activated) or any money held: wallet USDC, card collateral, or a collateral top-up in transit. $0.17 by crypto countsisActivated(card spend or QR pay, Lexicon v2)FirstPaymentChooser(card / QR). Card only →/card. QR only → QR scannerselectFirstPaymentRoute({ canSpendViaCard, canPayQr })returnscard_qr,card,qr,noneorpending.payop that is notblocked, or, with no such rail yet, a residence in AR or BR (canReachQrPay). So a new card-eligible user in Brazil sees both options before verifying.none(no card, no QR), the payment row is not shown. The list ends at Add money, and Home hands over to the carousel once all three rows are done.pendingmeans card eligibility is unknown (loading, or a failed request). The row keeps its place with a pulse placeholder, no tap and no outline, and the list cannot complete.useProviderRejection, so HomePage and ActivationCTAs read one answer. A verified, funded user with no card and no QR and a blocked bank rail keeps the rejection card.The activation definition is unchanged. API
isActivated(card spend or Manteca QR pay) still drives the Lexicon metric and Rewards gating:showRewards, invite and bug-bounty slides, and the receipt referral. No API PR is needed.PostHog:
activation_step_viewednow reportsverify/add_money/first_payment, once per step per session. The old values wereverify/deposit/card/outbound, on every Home visit.home_checklist_viewednow sendsfirst_payment_routeinstead ofthird_item. Dashboards that read the old values need an update.Carousel (Konrad's QR banner rule,
src/utils/home-carousel.utils.ts):app-install, which returns after 7 days, with its reason inRECURRING_CAROUSEL_CTAS. A document request with a due date has no × (from TASK-23054: a future-dated document request never interrupts a bank transfer #3467).hasQrPayRail, moved out of ActivationCTAs), and never shows after a QR pay.Also:
home.activation.steps.*,spendWithPeanut,getCard*,firstPaymentNoteandaddMoneyRoutesKyckeys. The full old/new string table for Hugo's copy review is in the review page (section 2b).CONCEPT_ICONS. The hand-rolledarrow-upexemption is removed./dev/home-ctas, the dev surfaces and/dev/journeyare updated.home-new-user,home-verify-processing,home-verified-unfunded(-no-card),home-verified-crypto-dust,home-money-before-verify,home-collateral-only,home-funded(card + QR),home-funded-qr,home-funded-no-spend-path,home-provider-rejection,home-region-restricted,home-activated. A fixture can now declare its walletbalance(the demo overlay, set per tab and not persisted).Screens (375×667, local dev with the fixtures above)
The Screen Library captures every fixture on this PR. The mono review page
local/scratch/home-viz/onboarding.htmlhas all 13 captures at full size, a contact sheet (checklist-sheet.jpg), the before states, and the copy table.Tests
activation-step.utils.test.tscovers each state: new user, in review, needs action, verified $0, $0.17 crypto, collateral only, bank top-up spent, money before verify, activated. It also covers what completes the checklist for each route, the route selector for all four cases, andhasQrPayRail, whose cases moved from the ActivationCTAs suite.home-carousel.utils.test.ts: a closed card stays closed, app-install comes back after 7 days, the legacy shape, an unreadable date, and the QR slide gate (no rail, already paid, loading).HomePage.test.tsxchecks that the two never show together: checklist or carousel, and a due task card replaces the checklist.useActivationStatustests the wiring.GettingStartedChecklisttests rows, the outline, the in-review state, percentages, every route's copy and tap, the pending row, three rows fornone, and one title plus one subtitle line per row in every state.ActivationCTAskeeps its override suites and adds a test thatactivation_step_viewedfires once per step.tscclean, full Jest green,node --test scripts/screens/*.test.mjsgreen.product/activation-funnel.md).Notes for review
/card, where they can use the card. The copy could say "Pay with the Peanut Card" for holders. Left as specified.