Skip to main content

🟡 Release v2.82.0

⭐⭐ Complexity • 2 commits • 37 files changed
Seamless modal navigation powered by Next.js intercepted routes. This release modernizes how users explore content across the platform—challenges, rewards, posts, achievements, and shop features now open in smooth, full-height modals with browser history support. Users can navigate between modals and stacked content while maintaining scroll position and browsing context, delivering a native app-like experience without page reloads.

What’s New

  • Intercepted Modal Navigation - Challenges, rewards, posts, and achievements now open in elegant modal overlays instead of full-page views, keeping users in context while exploring related content
  • Browser History Support - Full back/forward navigation works intuitively through modals—back button closes the modal and returns to the previous view with scroll position preserved
  • Stacked Modal Support - Discover related content seamlessly; clicking a reward within a challenge opens a second modal while keeping the challenge in the background, fully visible when you navigate back
  • Unified UX Across Viewports - Same consistent modal behavior on mobile, tablet, and desktop—no viewport-specific logic or layout shifts required
  • Zero-Config Route Integration - Standard Next.js links work automatically without custom context providers or viewport detection; developers simply use regular <Link> components

Apps Updated

User App

✓ Updated - 37 files changed

API

— No changes

Admin

— No changes

MCP Server

— No changes

Website

— No changes

Games

— No changes

Detailed Changes

Modernized Content Discovery with Next.js Intercepted RoutesThe user app now implements Next.js 15’s parallel routes and route interception pattern for a native app-like modal experience. This architectural change improves UX, simplifies navigation logic, and eliminates custom viewport detection code.How It Works for UsersClicking any content card (challenge, reward, post, achievement) opens a full-height drawer modal that:
  • Appears instantly with smooth animation
  • Preserves the underlying list with scroll position maintained
  • Closes when user taps the X button, returning to the exact scroll position
  • Supports stacked modals—discover related content without losing your place
  • Works identically on mobile, tablet, and desktop
Implementation Architecture
  1. Next.js Parallel Routes (@modal slot)
    • Dedicated app/@modal/ directory for all modal content
    • Route interception pattern (.)challenge/[id] catches soft navigation (clicking links)
    • Direct navigation (URL bar, refresh) bypasses modal and shows full-page view
    • Automatic default.tsx returns null when no modal is active
  2. InterceptedDrawer Component
    • Full-height drawer using Vaul library (proven animation framework)
    • Detects user-initiated close (X button) and calls router.back()
    • Animates smoothly with 400ms duration, ensuring close animation completes before navigation
    • Detects forward navigation and closes drawer without unnecessary back navigation
    • Context provider (InterceptedDrawerContext) allows nested components to request close
  3. View Components (Extracted & Reusable)
    • New components: ChallengeDetailsView, RewardDetailsView, PostDetailsView, AchievementDetailsView, ShopView
    • These components fetch data and render content, used in both modal and full-page routes
    • Eliminates code duplication between intercepted and regular routes
    • Single source of truth for all detail views
  4. Smart Navigation
    • Back button in modal uses drawer context or router.back() for maximum compatibility
    • No hardcoded redirect URLs; navigation is history-based and context-aware
    • Link prefetch={true} improves perceived performance
Files Added
  • app/@modal/default.tsx - Returns null when no modal is active
  • app/@modal/(.)challenge/[id]/page.tsx - Intercepted challenge modal route
  • app/@modal/(.)reward/[id]/page.tsx - Intercepted reward modal route
  • app/@modal/(.)post/[id]/page.tsx - Intercepted post modal route
  • app/@modal/(.)achievement/[id]/page.tsx - Intercepted achievement modal route
  • app/@modal/(.)settings/page.tsx - Settings modal
  • app/@modal/(.)wallet/page.tsx - Wallet/points modal
  • app/@modal/(.)shop/page.tsx - Shop modal with full shop functionality
  • components/shared/intercepted-drawer.tsx - Modal drawer wrapper with animation
  • components/shared/intercepted-drawer-context.tsx - Context for close requests
  • components/shared/close-button.tsx - Reusable close button with styling
  • components/shared/modal-error.tsx - Error state UI for modals
  • components/challenge/challenge-details-view.tsx - Data fetching + rendering
  • components/reward/reward-details-view.tsx - Data fetching + rendering
  • components/post/post-details-view.tsx - Data fetching + rendering
  • components/achievement/achievement-details-view.tsx - Data fetching + rendering
Component Updates
  • components/challenge/challenge-details/challenge-details-modern.tsx
    • Now accepts drawer context for smooth close animation
    • Back button calls drawerContext.requestClose() or router.back()
    • Removed hardcoded redirect to challenges page
    • Close button styling updated to dark background for visibility over images
  • components/reward/reward-details/reward-details-modern.tsx
    • Integrates with drawer context
    • Smooth close with requestClose() instead of manual navigation
  • components/post/post-details/post-details-modern.tsx
    • Drawer context integration for consistent back button behavior
  • components/achievement/achievement-details/achievement-details-modern.tsx
    • New drawer context support
    • Updated close button styling (X icon instead of back arrow)
    • Confetti celebration effect works in modal
  • components/navigation/app-layout.tsx
    • Accepts modal slot from layout for rendering in parallel routes
    • No viewport detection; modals are structural not conditional
  • components/navigation/scroll-reset.tsx
    • Enhanced to preserve scroll position through modal navigation
    • Smooth scroll restoration when returning from modal
  • components/reward/shop-view.tsx
    • Shop now opens in modal, allowing full browsing without page transition
    • Search and filter work smoothly in modal context
  • lib/achievement-utils.ts
    • Updated to accept drawer context
    • View rewards button now works from achievement modal
Documentation Added
  • docs/intercepted-routes-pattern.md - Complete architecture reference (261 lines)
  • docs/stacked-modal-navigation.md - User interaction patterns and flow examples (265 lines)
  • docs/intercepted-routes-debugging.md - Troubleshooting and debugging guide (292 lines)
Key Behavioral Changes
  • Content details now open in modals instead of full-page navigation
  • Back button behavior is now history-based (router.back()) instead of route-aware
  • Scroll position automatically preserved when opening/closing modals
  • Mobile, tablet, and desktop all use identical modal layout (no responsive branch logic)
  • URL changes to reflect modal state (e.g., /challenges/challenge/123) for shareability and history
Testing
  • 125+ lines of test coverage for intercepted route behavior
  • Tests verify modal open/close animation, stacking behavior, and navigation history
  • Scroll position preservation validated across viewport sizes

Technical Highlights

Next.js 15 Intercepted Routes Pattern This release implements the modern Next.js 15 parallel routes + route interception pattern, providing a robust foundation for future modal-based features. The pattern is:
User clicks link to /challenge/123

Next.js recognizes (.)challenge/[id] route interception

@modal/(.​)challenge/[id]/page.tsx renders in <modal> slot

Main layout renders both page content + modal simultaneously

User closes modal → router.back() → URL changes → @modal/default.tsx renders null

Modal slot unmounts, underlying page content is visible again
Performance Improvements
  • No full page reloads when opening modals (soft navigation)
  • Scroll position preserved through React state, no DOM recreation
  • Lazy-loaded modal content with React Query integration
  • Animations use GPU acceleration (transform/opacity)
Architectural Benefits
  • Eliminates custom viewport detection and branching logic
  • Single source of truth for detail views (reusable components)
  • Browser history naturally handles modal stacking
  • Future-proof for additional modal routes (without code changes to core patterns)
  • Accessible out-of-the-box with proper ARIA attributes via Vaul drawer

Contributors

ZuhayrK00@ZuhayrK001 commit • +2694/-117 lines

Release Stats

MetricValue
Total Commits2
Lines Added+2,694
Lines Removed-117
Files Changed37
Release Size🟡 Medium
Complexity⭐⭐ Moderate

v2.82.0 deployed on December 18, 2025