Skip to content

feat(shared): add streak progression system and milestone claim UX#5613

Open
tomeredlich wants to merge 52 commits intomainfrom
feat/streak-progression-system
Open

feat(shared): add streak progression system and milestone claim UX#5613
tomeredlich wants to merge 52 commits intomainfrom
feat/streak-progression-system

Conversation

@tomeredlich
Copy link
Contributor

@tomeredlich tomeredlich commented Feb 27, 2026

Summary

  • add the new streak progression experience, including timeline milestones, claim actions, claim animations, and supporting popovers/calendar UI
  • polish streak debug and drawer/tooltip behaviors, including reset handling for claimed milestones and claim-state defaults
  • include related shared UI refinements that are already part of this branch history (social repost metadata consistency and supporting component/test updates)

Test plan

  • open the streak popup in tooltip mode and verify milestone rows default to Claim until clicked
  • claim a cores milestone and verify the icon flies to wallet without snapping back
  • verify no post-claim share popover appears for cores claims
  • click debug Reset and verify claimed milestones are reset
  • run shared lint/tests as needed for touched areas

Made with Cursor

Preview domain

https://feat-streak-progression-system.preview.app.daily.dev

tomeredlich and others added 30 commits February 17, 2026 10:17
Align social Twitter repost cards across grid and list by moving repost identity to metadata, improving embedded tweet presentation, and standardizing the Read on X CTA for clearer feed UX.

Co-authored-by: Cursor <cursoragent@cursor.com>
Align social X repost presentation across grid, list, and modal so author metadata, embed typography, and CTA behavior are consistent and clearer. This also improves embedded avatar handling with better fallbacks and repost labeling to reduce confusing placeholders.

Co-authored-by: Cursor <cursoragent@cursor.com>
Unify social Twitter repost metadata presentation and sizing across grid/list cards and post modal so identity, iconography, and spacing remain consistent.

Co-authored-by: Cursor <cursoragent@cursor.com>
…erList

The metadataBottomLabel variable was being inferred as string from
metadata.bottomLabel, but was then assigned JSX elements in conditional
blocks, causing a TypeScript compilation error.

Added explicit type annotation (ReactElement | string | undefined) to
match the PostMetadataProps['bottomLabel'] type and allow both string
and JSX element assignments.

Co-authored-by: Chris Bongers <rebelchris@users.noreply.github.com>
Match social repost metadata height/order and align quote preview header avatar, typography, and spacing with shared preview styles across list and card layouts.

Co-authored-by: Cursor <cursoragent@cursor.com>
Extract shared social Twitter text/handle/avatar helpers into a single lib module and reuse them across list, grid, markdown, and share post components to remove duplicated logic and keep behavior consistent.

Co-authored-by: Cursor <cursoragent@cursor.com>
Apply prettier formatting for the getSocialPostText call in SharePostContent to satisfy lint_shared and keep CI green.

Co-authored-by: Cursor <cursoragent@cursor.com>
Unify social tweet/repost card and modal metadata presentation, spacing, and fallback behavior so repost-like content renders consistently in grid/list and modal views.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use canonical share-like checks, align sanitization between grid/list rendering, and update grid tests to match repost metadata and link behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
…tone timeline

Introduce a tier-based streak progression system with animated counter,
milestone timeline, urgency nudges, and debug controls (?debugStreak).

Co-authored-by: Cursor <cursoragent@cursor.com>
…tions, and calendar view

Enhance the streak progression system with visual feedback for streak
changes (increment popover, broken popover), full-screen milestone
celebrations, a monthly calendar view, and new high-tier milestones
(Phoenix, Titan, Godflame). Replace notification image with SVG component.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add subtle white sparkle animation on achieved milestone icons and randomize sparkle placement per milestone for a more lively reward feel.

Co-authored-by: Cursor <cursoragent@cursor.com>
Improve the streak popup with richer milestone interactions, including a sponsored coupon claim flow with reusable reveal modal and updated debug/testing controls to make milestone behavior easier to verify.

Co-authored-by: Cursor <cursoragent@cursor.com>
…verlays

Improve streak UI experimentation by adding a debug-toggleable right drawer variant, refreshed streak popup content, and milestone animations that stay open with explicit close/share actions.

Co-authored-by: Cursor <cursoragent@cursor.com>
Hide the milestones heading when nothing is achieved and add a float-style share action button for achieved milestone tooltips.

Co-authored-by: Cursor <cursoragent@cursor.com>
Make 0-1 reward milestones more compact and improve sponsored milestone gradient visibility while removing stripe overlays for a cleaner look.

Co-authored-by: Cursor <cursoragent@cursor.com>
Refine the streak recover and streak popup UI with updated spacing, animation layering, drawer behavior on tablet, and calendar/milestone visual tweaks while aligning feed tab header background styling with themed surfaces.

Co-authored-by: Cursor <cursoragent@cursor.com>
Unify the reminder popover structure with the +1 animation layout, show daily step progress as current-to-next day with full completion animation, and restore total days left context for the active milestone.

Made-with: Cursor
Keep the streak popup width stable and update the 30-day grid to a rolling 10x3 window with elevator-style row transitions, while improving debug controls for day-by-day streak simulation.

Made-with: Cursor
Promote reward summaries to the primary milestone headline, move day chips to their own top line, and simplify subtext/details while updating milestone reward definitions and sponsored visuals.

Made-with: Cursor
Make milestone rewards explicitly claimable, restore cores claim animation behavior, and remove post-claim share/confirmation popovers to keep the flow focused and consistent across tooltip and drawer views.

Made-with: Cursor
@vercel
Copy link

vercel bot commented Feb 27, 2026

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

Project Deployment Actions Updated (UTC)
daily-webapp Ready Ready Preview Mar 8, 2026 7:20pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
storybook Ignored Ignored Mar 8, 2026 7:20pm

Request Review

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ rebelchris
❌ tomeredlich
You have signed the CLA already but the status is still pending? Let us recheck it.

Document a production-ready session animation flow for the updated streak milestone experience so teammates can quickly record or generate a consistent feature demo.

Made-with: Cursor
…on-system

Made-with: Cursor

# Conflicts:
#	packages/shared/src/components/MainFeedLayout.tsx
#	packages/shared/src/components/cards/socialTwitter/EmbeddedTweetPreview.tsx
#	packages/shared/src/components/cards/socialTwitter/SocialTwitterGrid.tsx
#	packages/shared/src/components/cards/socialTwitter/SocialTwitterList.spec.tsx
#	packages/shared/src/components/cards/socialTwitter/SocialTwitterList.tsx
#	packages/shared/src/components/cards/socialTwitter/socialTwitterHelpers.tsx
#	packages/shared/src/components/post/SocialTwitterPostContent.tsx
#	packages/shared/src/components/utilities/DateFormat.tsx
Add Jest asset mocks and restore streak milestone icon mapping so shared and extension suites can load streak UI assets, then update streak lint/test regressions introduced in the branch.

Made-with: Cursor
Avoid accessing a non-existent LoggedUser.streak field by deriving preview old streak length from useReadingStreak, unblocking webapp type-check on Vercel.

Made-with: Cursor
Ensure the greeting hero is truly transparent in light mode by gating decorative backgrounds to dark themes, and improve mobile streak drawer behavior with fixed float actions and consistent milestone row sizing.

Made-with: Cursor
Unify streak reminder/increment nudges on the toast system while tightening hero/session gating and milestone visibility rules. This also aligns drawer defaults, milestone celebration flow, and icon/text polish across streak UI touchpoints.

Made-with: Cursor
Improve FeedGreetingHero visuals and messaging with dynamic user-facing text while keeping effects behind content, and align reminder toast/portal styling tweaks for consistent UX.

Made-with: Cursor
Use typo-mega2 for the FeedGreetingHero greeting so longer usernames fit more comfortably without overwhelming the hero layout.

Made-with: Cursor
…aces

Bring the reminder back to in-context popover UX and keep milestone celebration behavior stable across devices by using drawer flow on mobile while preserving popover flow on desktop.

Made-with: Cursor
Use the same background treatment for morning and afternoon variants, and tune the dark evening palette to better match the app's main background tokens.

Made-with: Cursor
Remove the debug shortcut strip from the shared FeedGreetingHero so shortcut links stay extension-only and never leak into production/web hero previews.

Made-with: Cursor
Stabilize streak-related shared changes and add smoke E2E coverage plus release quality gates so pre-push validation is faster and less brittle in CI and local runs.

Made-with: Cursor
Change the day-7 Flame milestone reward from a cosmetic flair to 25 Cores to match the revised progression rewards plan.

Made-with: Cursor
Disable the sponsored streak milestone by default while keeping a single source-of-truth toggle so it can be restored without reworking the timeline logic.

Made-with: Cursor
@tomeredlich
Copy link
Contributor Author

@claude check pr

@claude
Copy link
Contributor

claude bot commented Mar 8, 2026

Claude finished @tomeredlich's task in 2m 17s —— View job


PR Review: feat(shared): add streak progression system and milestone claim UX

  • Gather PR context and changed files
  • Analyze key source files for correctness and quality
  • Check for bugs, security issues, performance problems
  • Review code style and best practices
  • Post final review

This is a substantial feature PR (~70 files, +5723/-316). The core streak progression system is well-structured overall. Here are the issues found, grouped by severity.


🔴 Bugs / Broken Logic

1. Dead code — tooltip path is completely unreachable
packages/shared/src/components/streak/ReadingStreakButton.tsx:272

const shouldOpenInDrawer = true; // always true

The ConditionalWrapper at line 280 uses condition={!shouldOpenInDrawer}, which is always false. This means CustomStreaksTooltip (lines 63–103) and its props (showMilestoneTimeline, milestoneClaimResetNonce, isDebugMode, etc.) are entirely dead code — never rendered in production. Either remove the constant and the tooltip path entirely, or make this an actual runtime decision. Fix this →

2. Hard-coded "Day 4 Milestone!" label for sponsored reward
packages/shared/src/components/streak/popup/ClaimRewardAnimation.tsx:208

<Typography ...>Day 4 Milestone!</Typography>

This text is hardcoded and will be wrong if SPONSORED_STREAK_MILESTONE_DAY changes. It should use reward.milestoneDay instead. Fix this →


🟡 Issues Worth Addressing

3. Brittle wallet DOM selector
packages/shared/src/components/streak/popup/ClaimRewardAnimation.tsx:37

const WALLET_BUTTON_SELECTOR = 'a[href="/wallet"]';

This will silently fail (animation stays center-screen) if the wallet href changes (e.g., locale prefixes, route changes). A data-testid="wallet-nav-link" or similar attribute would be more resilient. Fix this →

4. No visual feedback when claiming non-cores rewards (Perks/Cosmetics)
packages/shared/src/components/streak/popup/MilestoneTimeline.tsx:403–413

When coresAmount is null (e.g., "48H Boost post", "Verified Reader title", "Top comment"), no animation fires — only the button state changes to "Claimed". The user gets no feedback that their perk was acknowledged. At minimum, a toast or brief confirmation should be shown.

5. StreakMonthCalendarinitialStreakRef never updated
packages/shared/src/components/streak/popup/StreakMonthCalendar.tsx:65–70

const activeStreak = Math.max(streakOverride ?? currentStreak ?? 1, 1);
const initialStreakRef = useRef(activeStreak);
const streakDelta = activeStreak - initialStreakRef.current;

initialStreakRef.current is set once on mount and never updated. In debug mode where streakOverride changes frequently, streakDelta accumulates and the displayed today date drifts unexpectedly. The ref should be updated when streakOverride changes between debug sessions, or this mechanism needs documentation.

6. Claim state is purely local/ephemeral
packages/shared/src/components/streak/popup/MilestoneTimeline.tsx:382

const [claimedDays, setClaimedDays] = useState<Set<number>>(new Set());

Closing and reopening the drawer resets all "Claimed" buttons back to "Claim". If rewards are genuinely tracked backend-side, the claimed state should be fetched from there; if not, consider persisting in sessionStorage at minimum so the state survives re-opens within the same session.


🟡 Non-Production Assets in Source Tree

7. Automation prompt/storyboard files in src/components/streak/

These three files don't belong in the production source:

  • packages/shared/src/components/streak/automation/session-animation.ai-prompt.md
  • packages/shared/src/components/streak/automation/session-animation.storyboard.md
  • packages/shared/src/components/streak/automation/session-animation.voiceover.md

These are AI video generation assets and should live in a docs/ or .internal/ directory (or be removed from the repo entirely) — not in src/components. Fix this →


🟢 Minor / Nits

8. Both UrgencyLevel.Low and UrgencyLevel.Medium use animate-streak-pulse
ReadingStreakButton.tsx:323–328 — identical animation for two different urgency levels. If intentional, collapsing the condition into (Low || Medium) would make intent clearer.

9. FeedGreetingHero.tsx is 1,126 lines — well over what a single component file should contain. While not blocking, it's worth splitting into smaller sub-components during a follow-up.

10. RELEASE_CHECKLIST.md in the repo root — This is a useful operational document, but including it in a feature PR is unexpected. Consider opening it as a separate PR with its own context so it gets proper review attention.


✅ What's Done Well

  • The seededRandom function for stable sparkle positions is a clean solution that avoids hydration mismatches.
  • useStreakDebug with useSyncExternalStore for cross-component global debug state is the right pattern.
  • useStreakIncrement is simple, focused, and correctly cleans up timers.
  • The milestone claim reset via claimResetNonce prop is a clean way to propagate reset events without lifting state unnecessarily.
  • isStreakDebugEnabled() properly gates debug mode behind isProductionAPI check + localStorage opt-in — good security posture.

· Preview

Remove the unreachable tooltip branch now that the streak UI always opens in a drawer, and derive the sponsored reward copy from the milestone day instead of a hardcoded value.

Made-with: Cursor
Refresh shared test fixtures, mocks, and asset declarations to match current provider contracts and form types so the shared package typecheck passes in quality gates.

Made-with: Cursor
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.

3 participants