feat(home): flag-gated user-interview invite card in the carousel - #2654
Conversation
Ask our most active users for a 15-min founder call (TASK-21189). The cohort lives in the PostHog flag user-interviews-invite (release condition on username), never in code - list edits and the kill switch are one click in PostHog and no usernames ship in the bundle. The card leads the carousel for targeted users, opens the shared cal.com event via the Capacitor-safe helper, and inherits the standard 7-day X-dismissal. Temporary campaign: delete the card, flag, and i18n keys when it ends.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds a feature-flagged user-interview CTA to the home carousel. The CTA uses localized copy and mascot branding, records click analytics, and opens a shared Cal.com booking URL. A development preview is also added. ChangesUser interview CTA
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant HomeCarousel as Home carousel
participant useHomeCarouselCTAs
participant PostHog
participant Analytics as Analytics registry
participant CalCom as Cal.com
HomeCarousel->>useHomeCarouselCTAs: Request carousel CTAs
useHomeCarouselCTAs->>PostHog: Check user-interviews-invite flag
PostHog-->>useHomeCarouselCTAs: Return campaign eligibility
useHomeCarouselCTAs-->>HomeCarousel: Return user-interview CTA
HomeCarousel->>useHomeCarouselCTAs: Handle CTA click
useHomeCarouselCTAs->>Analytics: Record USER_INTERVIEW_CTA_CLICKED
useHomeCarouselCTAs->>CalCom: Open USER_INTERVIEW_CAL_URL
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Code-analysis diffPainscore total: 7141.32 → 7143.02 (+1.7) 🆕 New findings (12)
✅ Resolved (12)
📈 Painscore deltas (top movers)
|
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
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/constants/general.consts.ts`:
- Line 251: Update the USER_INTERVIEW_CAL_URL constant to use the active Cal.com
15-minute event URL at hugo0/15min instead of the dead aleks-n-hugo/15min link.
In `@src/hooks/useHomeCarouselCTAs.tsx`:
- Around line 167-168: Update the openExternalUrl call in CarouselCTA to attach
a catch handler that displays a localized toast using the
userInterview.openError translation key, while preserving the existing
fire-and-forget behavior. Add userInterview.openError to every locale 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
Run ID: 2a16eb68-244e-4f5a-a737-a34318b18d49
📒 Files selected for processing (8)
src/app/(mobile-ui)/dev/home-ctas/page.tsxsrc/constants/analytics.consts.tssrc/constants/general.consts.tssrc/hooks/useHomeCarouselCTAs.tsxsrc/i18n/app/messages/en.jsonsrc/i18n/app/messages/es-419.jsonsrc/i18n/app/messages/es-AR.jsonsrc/i18n/app/messages/pt-BR.json
…rdown checklist Applied from the automated review pass: (1) await openExternalUrl so a native Browser.open failure surfaces in CarouselCTA's onClick catch instead of a detached rejection; (2) the analytics comment no longer claims flag exposures equal impressions (they fire per evaluation, prod-only, dismissed users included) and points readers at cal.com bookings + a $host filter; (3) the delete-together checklist now names the dev/home-ctas preview entry so teardown removes all three copies.
The committed aleks-n-hugo/15min event 404s (CodeRabbit catch, verified). Replaced with the hugo0+abalinda dynamic group link, which resolves and books both hosts' mutual availability.
Aleks isn't a founder; only Hugo is. All four locales, the dev preview, and the code comments now say team.
ui: render the waving mascot at 44px (follow-up to #2654)
Summary
Ask our most active users for a 15-min call with the team ("help shape the app") — one new card in the home carousel, shown only to a hand-picked cohort. The cohort lives in the PostHog flag
user-interviews-invite(release condition onusername), never in code: list edits and the kill switch are one click in PostHog, and no usernames ship in the JS bundle. The card opens the shared cal.com event (https://cal.com/hugo0+abalinda/dynamic) via the Capacitor-safeopenExternalUrlhelper and inherits the carousel's standard 7-day X-dismissal.Temporary campaign (feature-gates doctrine: flags are scaffolding) — delete the card block, flag, and i18n keys when the interview round ends.
Task
TASK-21189 — user interviews PR (add cal./hugo+alex in carousel for quali users)
Behavior
nonProdBypass: true→ card always visible for QA.user_interview_cta_clickedPostHog event, then cal.com in a new tab (web) / in-app browser (native).$feature_flag_calledis only a rough impression proxy (fires per flag evaluation, prod only, dismissed users included). Bookings on cal.com are the campaign's real success metric; filter click insights by$host = peanut.meto exclude preview taps.Risks / breaking changes
None. FE-only, additive, flag-gated off on prod by default. No backend, no migrations. Hotfix to
main→ back-merge main→dev owed after merge.Design notes / accepted trade-offs
user_interview_cta_clickedalso fires from previews/staging, where the card is always on via the nonProd bypass. Deliberately not gated in code: the cohort is ~25 users and we read the metric once — filter by$host = peanut.me. Bookings on cal.com are ground truth.Launch steps (post-merge, not in this PR)
user-interviews-invitein PostHog (EU, project 138913): boolean, release conditionusername is one of [curated list]— Notion engaged-user list minus exclusions; cross-check spellings against prod DB first.$feature_flag_called(impressions) anduser_interview_cta_clicked(clicks); bookings land on cal.com.QA
tsc --noEmit✅ ·npm test225 suites / 2886 tests ✅ (i18n parity test covers the new keys in en/es-419/pt-BR + es-AR voseo delta) ·npm run build✅/dev/home-ctasrenders the new card variant with no auth or flag needed.Screenshots
From
/dev/home-ctas(the home-CTA visual catalogue — exactCarouselCTArender, no gating):/homeshot: the local sandbox has no FE-activated seeded user (activation = one completed spend intent), direct DB seeding is permission-blocked for agents, andPOST /dev/seed-scenariocurrently 500s (Cannot read properties of undefined (reading 'query')). The card mounts through the same singleifgate as every carousel card; any Vercel preview shows it on/homefor an activated user via the nonProd bypass. Assets branchpr-assets-2654— delete after merge.