Skip to content

feat(landing): homepage rebuild — persona manifesto, card beat high, /lp/card retired - #2686

Closed
0xkkonrad wants to merge 12 commits into
devfrom
feat/lp-refresh
Closed

feat(landing): homepage rebuild — persona manifesto, card beat high, /lp/card retired#2686
0xkkonrad wants to merge 12 commits into
devfrom
feat/lp-refresh

Conversation

@0xkkonrad

@0xkkonrad 0xkkonrad commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Rebuild of the peanut.me homepage per mockup v3.1 (mono projects/lp-refresh/mockups/mockup.html, Konrad-approved 2026-08-13). Doctrine: reuse the live page heavily — the homepage is the live sections reordered, plus two new folds. The earlier v1 implementation on this branch was rejected as too busy and is fully unwound (additive commits, no force-push).

New fold order (bg): live hero (pink) → ShhhhhFold (black, NEW) → ProblemFold (cream, NEW) → NoFees (blue) → yourMoney (yellow) → TweetCarousel (pink) → RegulatedRails (cream) → Manteca (blue ← was cream) → securityBuiltIn (pink) → sendInSeconds (yellow) → FAQs → footer. Yellow marquee strips between every fold as on live; the strip after ShhhhhFold carries the /shhhhh words (IYKYK · WORD TRAVELS · …).

  • ShhhhhFold — distills /shhhhh §1 onto black: wordmark, tagline, body with shared ScarcityCounter (51→50), TRY THE DOOR + waitlist link, blurred PixelatedCardFace at −12°. Every click routes to /shhhhh — no inline join logic. Copy comes from the existing shhhhh.* next-intl catalog (already localized, 4 locales). Pink drop shadows on this fold only (black shadows vanish on black).
  • ProblemFold — "You already know the problem." + three named cards (Living across borders / Sending money home / Paid from abroad) with inline line icons. Landing i18n keys added EN-first in all catalogs.
  • Restored verbatim from dev (v1 had deleted/edited them): TweetCarousel + tweets.consts, hero, noFees, StickyMobileCTA, ExchangeRateWidget, landingStrings/types/content, all src/i18n catalogs. sendInSeconds keeps the full scroll-freeze grow-button machinery.
  • Kept from v1: /lp/card retired (redirect → /shhhhh in redirects.json, route deleted, sitemap + robots cleaned), shared ScarcityCounter, 20→50/week admission copy across /shhhhh + metadata per product/card.md ruling 2026-08-12.
  • Deleted v1 beats: CardBeat, Manifesto, ProblemProse, WorksToday, NotForYou, Sparkle. CardPioneers + PioneerCard3D stay deleted (no longer rendered anywhere).
  • Kill switch: disableLandingCardFold (default off) hides ShhhhhFold + its marquee strip in one flip, mirroring the old disableCardPioneers gating.
  • Manteca background is now a prop (default cream) — only the homepage passes blue; /quests unchanged.

Design source: mockup v3.1 + decisions in mono projects/lp-refresh/README.md.

Task

TASK-21424 — https://app.notion.com/p/3ba83811757981dd8b7cd252044265e5

Risks / notes for review

  • ⚠️ Rain marketing compliance: the homepage card fold is a public card surface → needs Rain pre-publication review (14 days) before PROD merge. Preview/staging is fine.
  • ProblemFold copy ships EN-first in all landing catalogs; es-419 / es-AR / pt-BR translations are a follow-up before prod merge (PT-BR framing rules apply). ShhhhhFold needs no new translation (reuses the shhhhh catalog).
  • ShhhhhFold copy is app-locale (next-intl), not landing-locale: SSR renders EN, client swaps to the user's locale — same behavior as /shhhhh itself.
  • Pre-existing dev bug left in place (restored file): noFees "See the markup on" links point at /compare/wise|paypal|western-union, which 404 (only peanut-vs-* slugs are generated). Worth a separate one-line PR.
  • npm run build could not run locally (sandbox OOM, environmental); typecheck + 231 suites / 2939 tests green locally — CI + Vercel preview are the build verification.

QA

  • Local gate: prettier ✅ · typecheck ✅ · jest 231 suites / 2939 tests ✅ · eslint ✅.
  • Visual QA vs mockup v3.1 AND vs live peanut.me (reused folds must match live) runs against the Vercel preview — results in a follow-up comment.

🤖 Generated with Claude Code

…, 11 sections diet to 5 beats

Locked plan (mono projects/lp-refresh): card beat imports /shhhhh straight
after the hero, manifesto + problem prose follow, works-today grid carries
the surviving proof (live FX widget, compare links), exclusion ending
closes. /lp/card retired via permanent redirect to /shhhhh; sitemap and
robots entries removed. Sticky bar splits by audience (SIGN UP NOW +
TRY THE DOOR). Weekly admission copy moves 20 -> 50 per product/card.md
ruling 2026-08-12. New landing copy ships EN-first in all catalogs;
localization follows before prod merge.
@vercel

vercel Bot commented Aug 12, 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 Aug 13, 2026 4:17pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 43435453-86ec-4424-aa66-5ff22a168ad5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR replaces the legacy card landing page with new localized landing sections, updates CTA and balance-aware routing, removes the old /lp/card route, redirects it to /shhhhh, and changes closed-beta admission messaging from 20 to 50 people per week.

Changes

Landing page update

Layer / File(s) Summary
Landing content contracts and localization
src/components/LandingPage/landing.types.ts, src/components/LandingPage/landingStrings.ts, src/i18n/types.ts, src/i18n/*.json
Added typed localized content for the new landing sections, CTAs, statistics, and marquee text.
New landing-page sections
src/components/LandingPage/CardBeat.tsx, src/components/LandingPage/Manifesto.tsx, src/components/LandingPage/ProblemProse.tsx, src/components/LandingPage/WorksToday.tsx, src/components/LandingPage/NotForYou.tsx
Added localized sections for card beta access, product positioning, cross-border problems, available capabilities, and user eligibility.
Landing composition and mobile CTA behavior
src/components/LandingPage/LandingPageClient.tsx, src/components/LandingPage/LandingPageContent.tsx, src/components/LandingPage/StickyMobileCTA.tsx
Replaced slot-based legacy content with direct section rendering and updated the sticky CTA visibility and links.
Card route retirement and redirect
src/app/lp/card/CardLandingPage.tsx, src/app/lp/card/page.tsx, src/components/LandingPage/CardPioneers.tsx, src/components/LandingPage/PioneerCard3D.tsx, src/components/LandingPage/index.ts, redirects.json, src/app/sitemap.ts, src/app/robots.ts
Removed the old card landing page and related components, redirected /lp/card to /shhhhh, and removed the route from crawler indexes.
Closed-beta admission messaging
src/app/shhhhh/ShhhhhLandingPage.tsx, src/app/shhhhh/page.tsx, src/i18n/app/messages/*.json
Changed the displayed and localized weekly admission count from 20 to 50.

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

Sequence Diagram(s)

sequenceDiagram
  participant LandingPageClient
  participant CardBeat
  participant WorksToday
  participant AuthAndWallet
  participant Router
  LandingPageClient->>CardBeat: render localized card beta section
  CardBeat->>Router: track door CTA and navigate to /shhhhh
  LandingPageClient->>WorksToday: render product capability section
  WorksToday->>AuthAndWallet: read authentication and balance
  AuthAndWallet-->>WorksToday: return account state
  WorksToday->>Router: navigate exchange CTA by account state
``

</details>

<!-- walkthrough_end -->
<!-- pre_merge_checks_walkthrough_start -->

<details>
<summary>🚥 Pre-merge checks | ✅ 4 | ❌ 1</summary>

### ❌ 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. |

<details>
<summary>✅ Passed checks (4 passed)</summary>

|         Check name         | Status   | Explanation                                                                                                   |
| :------------------------: | :------- | :------------------------------------------------------------------------------------------------------------ |
|     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.                                      |
|      Description Check     | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled.                                                   |
|         Title check        | ✅ Passed | The title clearly summarizes the homepage rebuild, new persona and card sections, and retirement of /lp/card. |

</details>

</details>

<!-- pre_merge_checks_walkthrough_end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches 💡 1</summary>

<!-- finishing_touch_suggestion:docstrings -->
<details>
<summary>📝 Generate docstrings 💡</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> Create stacked PR
- [ ] <!-- {"checkboxId": "3e1879ae-f29b-4d0d-8e06-d12b7ba33d98"} --> Commit on current branch

</details>
<details>
<summary>🧪 Generate unit tests (beta)</summary>

- [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-5268456290"} -->   Create PR with unit tests
- [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-5268456290"} -->   Commit unit tests in branch `feat/lp-refresh`

</details>

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=peanutprotocol/peanut-ui&utm_content=2686)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>


<sub>Comment `@coderabbitai help` to get the list of available commands.</sub>

<!-- tips_end -->
Loading

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 7148.37 → 7152.85 (+4.48)
Findings: -1 net (+62 new, -63 resolved)

🆕 New findings (62)

  • critical complexity — src/components/LandingPage/LandingPageClient.tsx — CC 54, MI 55.94, SLOC 215
  • high complexity — src/app/shhhhh/ShhhhhLandingPage.tsx — CC 44, MI 55.87, SLOC 286
  • high hotspot — src/components/LandingPage/hero.tsx — 35 commits, +312/-223 lines since 6 months ago
  • high hotspot — src/app/shhhhh/ShhhhhLandingPage.tsx — 31 commits, +1087/-472 lines since 6 months ago
  • medium react-long-component — src/app/shhhhh/ShhhhhLandingPage.tsx:123 — ShhhhhLandingPage is 459 lines — split it
  • medium high-mdd — src/app/shhhhh/ShhhhhLandingPage.tsx:123 — ShhhhhLandingPage: MDD 176.6 (uses across many lines from declarations)
  • medium high-mdd — src/components/LandingPage/LandingPageClient.tsx:50 — LandingPageClient: MDD 66.8 (uses across many lines from declarations)
  • medium high-mdd — src/components/LandingPage/Manteca.tsx:24 — Manteca: MDD 47.8 (uses across many lines from declarations)
  • medium high-mdd — src/components/LandingPage/ProblemFold.tsx:21 — ProblemFold: MDD 37.0 (uses across many lines from declarations)
  • medium complexity — src/components/Card/share-asset/PixelatedCardFace.tsx — CC 29, MI 58.49, SLOC 146
  • medium high-mdd — src/components/LandingPage/securityBuiltIn.tsx:54 — SecurityBuiltIn: MDD 24.6 (uses across many lines from declarations)
  • medium high-mdd — src/components/LandingPage/ShhhhhFold.tsx:27 — ShhhhhFold: MDD 23.2 (uses across many lines from declarations)
  • medium high-mdd — src/components/LandingPage/RegulatedRails.tsx:52 — RegulatedRails: MDD 22.2 (uses across many lines from declarations)
  • medium high-mdd — src/components/LandingPage/landingStrings.ts:45 — landingStrings: MDD 20.9 (uses across many lines from declarations)
  • medium method-complexity — src/components/LandingPage/LandingPageClient.tsx:171 — CC 17 SLOC 39
  • medium complexity — src/components/Global/FAQs/index.tsx — CC 13, MI 62.66, SLOC 29
  • medium complexity — src/components/LandingPage/landingLinks.utils.ts — CC 7, MI 57.12, SLOC 35
  • medium complexity — src/components/LandingPage/RegulatedRails.tsx — CC 5, MI 55.44, SLOC 49
  • medium complexity — src/app/robots.ts — CC 4, MI 60.34, SLOC 32
  • medium complexity — src/components/LandingPage/Manteca.tsx — CC 3, MI 62.47, SLOC 26

…and 42 more.

✅ Resolved (63)

  • src/app/shhhhh/ShhhhhLandingPage.tsx — CC 48, MI 56.68, SLOC 304
  • src/components/LandingPage/LandingPageClient.tsx — CC 48, MI 55.67, SLOC 172
  • src/components/LandingPage/hero.tsx — 33 commits, +294/-205 lines since 6 months ago
  • src/components/LandingPage/PioneerCard3D.tsx — CC 31, MI 62.84, SLOC 153
  • src/app/lp/card/CardLandingPage.tsx — CC 15, MI 45.15, SLOC 308
  • src/app/shhhhh/ShhhhhLandingPage.tsx:140 — ShhhhhLandingPage is 457 lines — split it
  • src/app/lp/card/CardLandingPage.tsx:44 — CardLandingPage: MDD 318.2 (uses across many lines from declarations)
  • src/app/shhhhh/ShhhhhLandingPage.tsx:140 — ShhhhhLandingPage: MDD 175.8 (uses across many lines from declarations)
  • src/components/LandingPage/LandingPageClient.tsx:48 — LandingPageClient: MDD 48.3 (uses across many lines from declarations)
  • src/components/LandingPage/Manteca.tsx:20 — Manteca: MDD 47.8 (uses across many lines from declarations)
  • src/components/LandingPage/PioneerCard3D.tsx:14 — PioneerCard3D: MDD 39.7 (uses across many lines from declarations)
  • src/components/Card/share-asset/PixelatedCardFace.tsx — CC 29, MI 58.5, SLOC 146
  • src/app/shhhhh/ShhhhhLandingPage.tsx — 28 commits, +1078/-448 lines since 6 months ago
  • src/components/LandingPage/RegulatedRails.tsx:37 — RegulatedRails: MDD 26.8 (uses across many lines from declarations)
  • src/components/LandingPage/securityBuiltIn.tsx:54 — SecurityBuiltIn: MDD 23.2 (uses across many lines from declarations)
  • src/components/LandingPage/LandingPageClient.tsx:149 — CC 17 SLOC 39
  • src/components/Global/FAQs/index.tsx — CC 12, MI 63.28, SLOC 28
  • src/components/LandingPage/CardPioneers.tsx — CC 8, MI 63.74, SLOC 58
  • src/app/robots.ts — CC 4, MI 60.33, SLOC 32
  • src/components/LandingPage/Manteca.tsx — CC 3, MI 62.94, SLOC 25

…and 43 more.

📈 Painscore deltas (top movers)

File Before After Δ
src/components/LandingPage/ProblemFold.tsx 0.0 6.6 +6.6
src/components/LandingPage/landingLinks.utils.ts 0.0 5.7 +5.7
src/components/LandingPage/ShhhhhFold.tsx 0.0 5.5 +5.5
src/components/LandingPage/ScarcityCounter.tsx 0.0 4.9 +4.9
src/components/LandingPage/landingStrings.ts 7.4 8.7 +1.2
src/components/LandingPage/yourMoney.tsx 5.4 6.2 +0.8
src/components/LandingPage/LandingPageContent.tsx 5.1 6.0 +0.8
src/components/LandingPage/RegulatedRails.tsx 7.6 8.3 +0.8
src/components/LandingPage/LandingPageClient.tsx 11.5 12.1 +0.6
src/app/lp/card/page.tsx 2.9 0.0 -2.9
src/components/LandingPage/CardPioneers.tsx 6.5 0.0 -6.5
src/components/LandingPage/PioneerCard3D.tsx 6.6 0.0 -6.6
src/app/lp/card/CardLandingPage.tsx 11.9 0.0 -11.9

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 2990 ran, 0 failed, 0 skipped, 54.0s

📊 Coverage (unit)

metric %
statements 66.5%
branches 51.7%
functions 56.8%
lines 67.3%
⏱ 10 slowest test cases
time test
3.9s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
1.0s src/utils/__tests__/demo-api.test.ts › isDemoMode() is false when not running under Capacitor
0.4s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.4s src/utils/__tests__/auth-token.test.ts › authReady does not park — hydrates the plain token without an unlock
0.4s src/utils/__tests__/auth-token.test.ts › writes the guarded copy and marker but keeps the plain token until round-trip proof
0.4s src/utils/__tests__/auth-token.test.ts › ignores the guarded marker and falls back to the plain token
0.3s src/utils/__tests__/sentry.utils.test.ts › defaults to the client budget under a browser global
0.3s src/utils/__tests__/auth-token.test.ts › is none — never guarded — when only the guarded marker is present
0.3s src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx › Bank withdrawal keeps the $1 minimum for sub-$1 amounts
0.3s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in validateInviteCode
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@0xkkonrad

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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

🤖 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/components/LandingPage/NotForYou.tsx`:
- Around line 36-43: Replace all four nested Link/Button CTA pairs in
src/components/LandingPage/NotForYou.tsx (lines 36-43) and
src/components/LandingPage/StickyMobileCTA.tsx (lines 80-93) with styled Link
elements, preserving each CTA’s href, text, styling, and behavior while ensuring
each uses a single semantic navigation control.

In `@src/i18n/es-ar.json`:
- Around line 120-159: Translate all newly added landing-page entries in
src/i18n/es-ar.json lines 120-159 into natural Argentine Spanish, preserving
placeholders, punctuation, and key names. Apply the same localization to
src/i18n/pt-br.json lines 120-159 in Brazilian Portuguese, including CTA,
eligibility, card, fee, security, and waitlist text; do not leave English copy
in either catalog.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5cea8541-5975-430f-ba42-c8be181e735c

📥 Commits

Reviewing files that changed from the base of the PR and between 6e14a49 and c160a7a.

📒 Files selected for processing (29)
  • redirects.json
  • src/app/lp/card/CardLandingPage.tsx
  • src/app/lp/card/page.tsx
  • src/app/robots.ts
  • src/app/shhhhh/ShhhhhLandingPage.tsx
  • src/app/shhhhh/page.tsx
  • src/app/sitemap.ts
  • src/components/LandingPage/CardBeat.tsx
  • src/components/LandingPage/CardPioneers.tsx
  • src/components/LandingPage/LandingPageClient.tsx
  • src/components/LandingPage/LandingPageContent.tsx
  • src/components/LandingPage/Manifesto.tsx
  • src/components/LandingPage/NotForYou.tsx
  • src/components/LandingPage/PioneerCard3D.tsx
  • src/components/LandingPage/ProblemProse.tsx
  • src/components/LandingPage/StickyMobileCTA.tsx
  • src/components/LandingPage/WorksToday.tsx
  • src/components/LandingPage/index.ts
  • src/components/LandingPage/landing.types.ts
  • src/components/LandingPage/landingStrings.ts
  • src/i18n/app/messages/en.json
  • src/i18n/app/messages/es-419.json
  • src/i18n/app/messages/es-AR.json
  • src/i18n/app/messages/pt-BR.json
  • src/i18n/en.json
  • src/i18n/es-419.json
  • src/i18n/es-ar.json
  • src/i18n/pt-br.json
  • src/i18n/types.ts
💤 Files with no reviewable changes (8)
  • src/components/LandingPage/PioneerCard3D.tsx
  • src/components/LandingPage/CardPioneers.tsx
  • src/app/lp/card/page.tsx
  • src/components/LandingPage/LandingPageContent.tsx
  • src/app/robots.ts
  • src/app/lp/card/CardLandingPage.tsx
  • src/components/LandingPage/index.ts
  • src/app/sitemap.ts

Comment thread src/components/LandingPage/NotForYou.tsx Outdated
Comment thread src/i18n/es-ar.json Outdated
… FX widget landing mode, sticky-bar migration branch + robust suppression, card kill switch, shared ScarcityCounter, dead code out

17-item consolidated fix from 7 review angles + visual/copy QA:
zero-fee claim now appears exactly once; ExchangeRateWidget gains
hideCta/hideFees/default corridor props (USD->BRL — widget enforces a
USD leg); StickyMobileCTA regains the pwa-sunset store branch and
suppresses via data-own-cta + MutationObserver instead of one-shot id
lookup; disableCardBeat kill switch; DOOR_TRY gains surface on /shhhhh;
/lp/card purged from build scripts, /shhhhh added to the sitemap;
ScarcityCounter shared by homepage + /shhhhh with ADMISSIONS_PER_WEEK=50
in doorTally.utils; TweetCarousel + 10 orphaned i18n keys deleted;
static beats back to server slots; card face ssr:false behind a
reserved box; content submodule bumped to the Sumsub FAQ fix.
@0xkkonrad
0xkkonrad marked this pull request as ready for review August 13, 2026 07:23
@0xkkonrad
0xkkonrad requested a review from Hugo0 August 13, 2026 07:24
@0xkkonrad
0xkkonrad marked this pull request as draft August 13, 2026 09:44
The manifesto rebuild rewrote sections that already earn their keep. Most
of the approved v3 page is the live folds in a new order, so restore them
and re-sequence instead of writing new ones.

Two folds are new. A black door fold distils the /shhhhh hero — same
catalog, same scarcity counter — and every click in it goes to /shhhhh, so
the fold makes the offer and the page does the work. A cream problem fold
names the three people we built peanut for, right before the product folds
answer them.

Restored from dev: the tweet wall, the hero, NoFees, the sticky mobile bar,
the exchange-rate widget, the landing string bag, and the marquee words
from the content system. Dropped with the rebuild: CardBeat, Manifesto,
ProblemProse, WorksToday, NotForYou. The DropLink fold leaves the homepage
because v3 has no slot for it; the component stays for /exchange.

Manteca turns blue: it now follows RegulatedRails, which is cream. On the
black fold the button and the card carry pink drop shadows, because a black
shadow is invisible there. disableCardBeat becomes disableLandingCardFold
and hides the door fold together with the closed-beta strip under it.
A transform is ignored on a non-replaced inline element, and next/link
renders an inline anchor, so the card sat straight instead of at -12deg.
@0xkkonrad

Copy link
Copy Markdown
Contributor Author

Visual QA — v3.1 rebuild (commit 26fb7dd)

Two independent verification passes against the Vercel preview, both green:

1. vs mockup v3.1 — PASS, no blockers. All 12 folds in the approved order with exact background colours (computed styles): pink → black door → cream problem → blue → yellow → pink → cream → blue → pink → yellow → cream FAQ → black. Scarcity counter pops only 51only 50 at ~2.5s. All 5 clickables in the door fold resolve to /shhhhh (zero leaks). /lp/card 308-redirects to /shhhhh in one hop. Zero horizontal overflow at 375px and 1280px. Post-shhh marquee carries the IYKYK/WORD TRAVELS/CLOSED BETA/SHHHH/PEANUT CLUB words.

2. vs live peanut.me — zero genuine divergences. Every reused fold is innerText-identical to live with matching section backgrounds and widget inventories (exchange widget, 9 partner logos, tweet carousel, FAQ question-for-question, footer links). Only deliberate deltas: fold order, Manteca cream→blue, DropLink removed, two new folds. Zero React hydration warnings; console set identical to live.

Notes on record (non-blockers):

  • FAQ bg is cream and has 8 questions — matches live exactly (mockup was rough there); live itself has a 7-vs-8 FAQ data-source mismatch (RSC props vs rendered/JSON-LD) that predates this PR.
  • Pre-existing dev bug intentionally left: NoFees "See the markup on" links → /compare/wise|paypal|western-union 404 (only peanut-vs-* slugs generate). One-line follow-up PR candidate.
  • Preview points at api.staging.peanut.me (normal for branch deploys).

Merge gates unchanged: Rain 14-day marketing review · es-419/es-AR/pt-BR for the new ProblemFold keys · human review. Stays draft until then.

🤖 Generated with Claude Code

The three placeholder line icons were generic stock shapes that belonged to
no other Peanut surface. Each card now carries art the site already uses, so
the fold reads as ours.

"Living across borders" takes the marquee's thumbs-up turned over — the
verdict every neobank hands these people. "Sending money home" is a Knerd
percent, outline rather than filled: at this size the filled cut closes its
counters and reads as a blob. "Paid from abroad" is the pinch hand cut out of
the no-hidden-fees art into its own asset, so the card pulls 11KB of paths
instead of the whole 34KB banner.

One 44px-tall slot holds all three, because the glyph and the drawings need
different type sizes to carry the same optical weight.
The landing page names cities and repeats product claims that all have a real
article behind them, and none of it was reachable. This links the ones with a
genuine destination and leaves the rest alone — "Instant" has no article, so
it stays plain text.

MarqueeComp now takes {label, href} items alongside plain strings, so a strip
can link some words and not others. Every existing caller passes strings and
is untouched. The strip under the door fold links all five words to /shhhhh,
since the whole strip is the door. Marquee thumbs lose their "Marquee Image"
alt: now that the strips carry links, a screen reader would read that filler
between every one.

The city line stays one translated string per locale. A helper splits it on
the city names — aliases cover "New York", "Nueva York" and "Nova York" — and
wraps the matches. A locale whose wording drops a city loses that link and
keeps its sentence, which is why the helper matches rather than interpolates.
@0xkkonrad

Copy link
Copy Markdown
Contributor Author

Round 2 QA — brand icons + article links (54c1c97, 9e1d308)

Verified on the redeployed preview:

  • Problem cards now carry brand marks: marquee thumbs-up hand rotated 180° (reads thumbs-down) · Knerd-outline % · the gloved pinch-hand cut from the no-hidden-fees art into no-hidden-fees-hand.svg (11KB). All three aligned in one icon slot.
  • Link audit (all resolve 200): marquee words → No transfer fees /pricing · USD /help/what-are-digital-dollars · EUR /help/send-euros-argentina · USDT/USDC /blog/stablecoin-balance-visa-merchants · GLOBAL /help/supported-geographies · SELF-CUSTODIAL /help/security-custody · 24/7 /support; door-strip words (IYKYK/WORD TRAVELS/CLOSED BETA/SHHHH/PEANUT CLUB) all → /shhhhh; cities New York /united-states · Madrid /spain · Mexico City /mexico — translations preserved (render-time wrapping, aliases per locale).
  • MarqueeComp extended non-breaking; all six other call sites byte-identical to dev. CI fully green, 232 suites / 2973 tests.

Known trade-off on record: react-fast-marquee's autoFill clones linked words, so each is multiple tab stops (library gives no clone hook). Accepted for now; alternative is aria-hidden strip + visually-hidden link list.

🤖 Generated with Claude Code

Konrad drew a peace hand and a coin stack for the problem cards, so the
placeholder marks go: the turned-over thumbs-up and the pinch hand cropped
out of the no-hidden-fees banner last round. That crop had exactly one
consumer, so the asset goes with it. Card 2 keeps the Knerd percent, and all
three still share one 44px slot so the card tops line up.

The door fold loses its body paragraph. It was the /shhhhh pitch repeated a
click early, scarcity count and all — the fold only has to make the offer.
Wordmark, tagline, door, card. The shared ScarcityCounter stays; /shhhhh is
still its caller.
The works-with strip named nine partners and answered nothing about any of
them. Each logo now opens the page that honestly explains what it does with
Peanut: Wise and Revolut their compare pages, Mercado Pago the QR explainer,
PIX the Brazil page, and the SEPA/ACH banks the bank-deposit article. Brubank
and Stripe stay unlinked — no article covers their rail, and a logo that
lands somewhere vague is worse than one that does nothing.

Mercado Pago and PIX are the only two marks in the set that aren't a heavy
wordmark, and both were disappearing into the pink tile, so those two get a
white card behind them.

Round-2 links also stop underlining at rest. Eight underlined words in a
scrolling strip read as clutter; the underline now waits for the cursor.
…more

Six of the seven landing FAQs have a help article that answers the question
properly, and none of them said so. The FAQ panel takes an optional
learnMoreHref per question and the landing page supplies it from a map keyed
on the content system's question ids — the content file stays free of code
concerns, and a question with no honest article simply has no entry. "Why
Peanut?" has none; "My question is not here" already links the help centre.
Both other FAQsPanel callers pass nothing and are unchanged.

Konrad asked for the learn-more links right-aligned, remembering they used to
be. Git says otherwise: neither has ever carried an alignment class. The
securityBuiltIn one only looks centred on a phone because it inherits
text-center from the feature card while the paragraph beside it opts out with
text-left. Right-aligning all three is the change he actually wants; there was
nothing to revert.

The 24/7 card also drops "real humans" — we shouldn't promise a person picks
up. Spanish and Portuguese first sentences follow; second sentences untouched.
@0xkkonrad

Copy link
Copy Markdown
Contributor Author

Round 3 QA (2f60cbf, c73c6d4, 3b2ae4e)

Verified on the redeployed preview, CI fully green:

  • Problem cards: hands-peace.png / Knerd-outline % / stack-coin.png — new brand art in place, aligned.
  • Door fold: "A card accepted at over 150 million…" paragraph removed (counter with it); fold is wordmark → tagline → CTAs → card.
  • Link styling: marquee words + cities no underline at rest, underline on hover.
  • Partner logos clickable, targets all 200: Wise → compare/peanut-vs-wise · Revolut → compare/peanut-vs-revolut · Mercado Pago → help/mercadopago-qr · PIX → /brazil · BBVA/N26/Santander → help/deposit-bank · Brubank + Stripe deliberately unlinked (no honest article). MP + PIX in white pills for contrast; pink logo tiles confirmed pre-existing live styling.
  • Learn more links right-aligned (rails, security, FAQ). History dig: no commit ever centered them — securityBuiltIn's mobile centering was inherited text-center; now explicitly right at all widths.
  • 24/7 HELP copy: "One tap and support is always available. …" — "real humans" gone; es-419/es-ar/pt-br first sentences machine-drafted, flag at localization gate.
  • FAQ: right-aligned "Learn more →" per item — what-are-digital-dollars / verification / passkeys / security-custody / fees-pricing / supported-geographies; "Why Peanut?" + "My question is not here" deliberately skipped. Content files untouched (code-side map keyed on FAQ id); other FAQsPanel callers byte-identical to dev.

🤖 Generated with Claude Code

Both cards were carrying raster art at 44px. The peace hand already existed as
a vector — the same hand-peace.svg the footer and the security fold use, so the
homepage now draws from the same file instead of a near-duplicate PNG. Konrad
supplied the coin stack as an SVG too.

Ratios differ from the PNGs (37x57 and 197x173), but the shared 44px slot sizes
on height, so the row still lines up.
react-fast-marquee sets overflow-x:hidden on its container. A visible Y axis
against a hidden X axis computes to auto, so the strip clips vertically too —
and the tiles carried mb-2 with no top margin, sitting flush against that edge.
Hovering lifted a tile 2px into it and sheared off its top border.

my-2 gives the tile 8px above to move into. Measured under a real hover: the
tile top sat 2px past the clip edge before, and 6px clear of it after.
@0xkkonrad

Copy link
Copy Markdown
Contributor Author

Round 4 QA (ad7a9e4, e7a97d5)

Verified on the redeployed preview, CI green:

  • Works-with hover clip fixed: root cause was react-fast-marquee's overflow-x: hidden computing overflow-y to auto (spec behavior), with tiles flush against the clip edge; mb-2my-2 gives the 2px hover lift 8px of slack. Hover-render on the deployed strip shows complete borders on the lifted tile. Fix is local to the RegulatedRails tile class — the shared MarqueeWrapper is untouched.
  • Problem-card marks are now vector: existing hand-peace.svg (resolves the near-duplicate flag) + Konrad's stack-coin.svg (byte-for-byte as supplied). Both PNGs removed; no dangling references.

🤖 Generated with Claude Code

@0xkkonrad

Copy link
Copy Markdown
Contributor Author

Superseded by #2690 — same commits on branch lp-refresh (Konrad's call to drop the feat/ prefix; org ruleset blocks renaming in place, and it also blocks deleting this branch, so feat/lp-refresh stays behind as a stale pointer). All future work lands on #2690.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant