hensei-web/prd/app-router-migration.md
Justin Edmund c6b53eb538 Migrate all remaining components to App Router navigation
- Add 'use client' directives to all remaining components
- Update imports from next/router to next/navigation
- Replace router.locale with getCookie('NEXT_LOCALE')
- Update LanguageSwitch to use router.refresh()
- Replace router.asPath with usePathname()

Components migrated:
- Common: SelectWithInput, Editor
- Layout: Header, Layout, MentionList, ElementToggle
- Misc: UpdateToast, SearchModal, RaidCombobox, FilterModal
- Misc: ChangelogUnit, HovercardHeader, LanguageSwitch
- Extra: GuidebookUnit, GuidebookResult
- Reps: GridRep, CharacterRep, WeaponRep, SummonRep

Added migration PRD documentation to track progress.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-01 16:31:18 -07:00

6.9 KiB

App Router Migration PRD

Overview

Complete migration from Next.js Pages Router to App Router by updating all components to use next/navigation instead of next/router.

Migration Requirements

Router API Changes

  • useRouter() from next/routeruseRouter() from next/navigation
  • router.queryuseSearchParams() hook
  • router.pathnameusePathname() hook
  • router.asPath → combination of usePathname() + useSearchParams()
  • router.push() → stays the same
  • router.replace() → stays the same
  • router.back() → stays the same
  • router.reload()router.refresh()
  • router.prefetch() → stays the same
  • router.beforePopState() → not available in App Router (needs alternative)
  • router.events → not available in App Router (needs alternative)

Import Updates Required

All imports need to change from:

import { useRouter } from 'next/router'

To:

import { useRouter, usePathname, useSearchParams } from 'next/navigation'

Files to Migrate

App Directory Files (Already using next/navigation - 6 files)

These files already use next/navigation but should be verified:

  • /app/teams/TeamsPageClient.tsx
  • /app/saved/SavedPageClient.tsx
  • /app/p/[party]/PartyPageClient.tsx
  • /app/new/NewPartyClient.tsx
  • /app/components/Header.tsx
  • /app/[username]/ProfilePageClient.tsx

Pages Directory Files (1 file)

  • /pages/about.tsx - Needs migration to app router or update imports

Component Files - Auth (3 files)

  • /components/auth/LoginModal/index.tsx
  • /components/auth/SignupModal/index.tsx
  • /components/auth/AccountModal/index.tsx

Component Files - Character (5 files)

  • /components/character/CharacterUnit/index.tsx
  • /components/character/CharacterModal/index.tsx
  • /components/character/CharacterHovercard/index.tsx
  • /components/character/CharacterConflictModal/index.tsx
  • /components/character/CharacterResult/index.tsx

Component Files - Weapon (7 files)

  • /components/weapon/WeaponUnit/index.tsx
  • /components/weapon/WeaponModal/index.tsx
  • /components/weapon/WeaponKeySelect/index.tsx
  • /components/weapon/WeaponHovercard/index.tsx
  • /components/weapon/WeaponConflictModal/index.tsx
  • /components/weapon/WeaponResult/index.tsx
  • /components/weapon/WeaponLabelIcon/index.tsx

Component Files - Summon (3 files)

  • /components/summon/SummonUnit/index.tsx
  • /components/summon/SummonHovercard/index.tsx
  • /components/summon/SummonResult/index.tsx

Component Files - Party (5 files)

  • /components/party/PartyHeader/index.tsx
  • /components/party/PartyHead/index.tsx
  • /components/party/PartyFooter/index.tsx
  • /components/party/PartyDropdown/index.tsx
  • /components/party/Party/index.tsx

Component Files - Job (7 files)

  • /components/job/JobSkillItem/index.tsx
  • /components/job/JobSection/index.tsx
  • /components/job/JobDropdown/index.tsx
  • /components/job/JobAccessoryPopover/index.tsx
  • /components/job/JobAccessoryItem/index.tsx
  • /components/job/JobSkillResult/index.tsx
  • /components/job/JobImage/index.tsx

Component Files - Mastery (3 files)

  • /components/mastery/ExtendedMasterySelect/index.tsx
  • /components/mastery/AxSelect/index.tsx
  • /components/mastery/AwakeningSelectWithInput/index.tsx

Component Files - Reps (4 files)

  • /components/reps/GridRep/index.tsx
  • /components/reps/CharacterRep/index.tsx
  • /components/reps/WeaponRep/index.tsx
  • /components/reps/SummonRep/index.tsx

Component Files - Common (2 files)

  • /components/common/SelectWithInput/index.tsx
  • /components/common/Editor/index.tsx

Component Files - Extra (2 files)

  • /components/extra/GuidebookUnit/index.tsx
  • /components/extra/GuidebookResult/index.tsx

Component Files - Other (11 files)

  • /components/toasts/UpdateToast/index.tsx
  • /components/search/SearchModal/index.tsx
  • /components/raids/RaidCombobox/index.tsx
  • /components/filters/FilterModal/index.tsx
  • /components/MentionList/index.tsx
  • /components/Layout/index.tsx
  • /components/LanguageSwitch/index.tsx
  • /components/Header/index.tsx
  • /components/ElementToggle/index.tsx
  • /components/about/ChangelogUnit/index.tsx
  • /components/HovercardHeader/index.tsx

Utility Files (1 file)

  • /utils/changeLanguage.tsx

Total Files to Migrate: 59

Migration Steps for Each File

  1. Analyze current usage

    • Check how router is being used
    • Identify which properties/methods are accessed
    • Note any router.events listeners
  2. Update imports

    • Change from next/router to next/navigation
    • Add additional hooks if needed (usePathname, useSearchParams)
  3. Update router usage

    • Replace router.query with useSearchParams()
    • Replace router.pathname with usePathname()
    • Update any other router property access
  4. Handle edge cases

    • Router events (need alternative approach)
    • beforePopState (need alternative approach)
    • Dynamic route params (use useParams())
  5. Test the component

    • Ensure navigation still works
    • Check query parameter handling
    • Verify dynamic routes

Special Considerations

Router Events

Files using router.events will need special handling as this is not available in App Router. Common patterns:

  • Route change start/complete events → Use loading.tsx or Suspense
  • Route change error → Use error boundaries

Query Parameters

When migrating router.query:

// Old (Pages Router)
const { id, filter } = router.query

// New (App Router)
const searchParams = useSearchParams()
const id = searchParams.get('id')
const filter = searchParams.get('filter')

Dynamic Route Parameters

For dynamic segments like [id]:

// Old (Pages Router)
const { id } = router.query

// New (App Router)
import { useParams } from 'next/navigation'
const params = useParams()
const id = params.id

Programmatic Navigation

// Both routers (mostly the same)
router.push('/path')
router.replace('/path')
router.back()

// Refresh (different)
// Old: router.reload()
// New: router.refresh()

Post-Migration Cleanup

After all files are migrated:

  1. Remove /pages directory (except /pages/api if still needed)
  2. Remove Pages Router specific configuration
  3. Update _app.tsx dependencies if any remain
  4. Test all routes thoroughly
  5. Update any documentation

Success Criteria

  • All components use next/navigation imports
  • No references to next/router remain in components (only in pages/about.tsx which still needs migration)
  • All navigation functionality works as before
  • No console errors about "NextRouter was not mounted"
  • App runs successfully with npm run dev
  • Build completes with npm run build (to be tested)