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

209 lines
No EOL
6.9 KiB
Markdown

# 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/router``useRouter()` from `next/navigation`
- `router.query``useSearchParams()` hook
- `router.pathname``usePathname()` 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:
```tsx
import { useRouter } from 'next/router'
```
To:
```tsx
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)
- [x] `/components/auth/LoginModal/index.tsx`
- [x] `/components/auth/SignupModal/index.tsx`
- [x] `/components/auth/AccountModal/index.tsx`
### Component Files - Character (5 files)
- [x] `/components/character/CharacterUnit/index.tsx`
- [x] `/components/character/CharacterModal/index.tsx`
- [x] `/components/character/CharacterHovercard/index.tsx`
- [x] `/components/character/CharacterConflictModal/index.tsx`
- [x] `/components/character/CharacterResult/index.tsx`
### Component Files - Weapon (7 files)
- [x] `/components/weapon/WeaponUnit/index.tsx`
- [x] `/components/weapon/WeaponModal/index.tsx`
- [x] `/components/weapon/WeaponKeySelect/index.tsx`
- [x] `/components/weapon/WeaponHovercard/index.tsx`
- [x] `/components/weapon/WeaponConflictModal/index.tsx`
- [x] `/components/weapon/WeaponResult/index.tsx`
- [x] `/components/weapon/WeaponLabelIcon/index.tsx`
### Component Files - Summon (3 files)
- [x] `/components/summon/SummonUnit/index.tsx`
- [x] `/components/summon/SummonHovercard/index.tsx`
- [x] `/components/summon/SummonResult/index.tsx`
### Component Files - Party (5 files)
- [x] `/components/party/PartyHeader/index.tsx`
- [x] `/components/party/PartyHead/index.tsx`
- [x] `/components/party/PartyFooter/index.tsx`
- [x] `/components/party/PartyDropdown/index.tsx`
- [x] `/components/party/Party/index.tsx`
### Component Files - Job (7 files)
- [x] `/components/job/JobSkillItem/index.tsx`
- [x] `/components/job/JobSection/index.tsx`
- [x] `/components/job/JobDropdown/index.tsx`
- [x] `/components/job/JobAccessoryPopover/index.tsx`
- [x] `/components/job/JobAccessoryItem/index.tsx`
- [x] `/components/job/JobSkillResult/index.tsx`
- [x] `/components/job/JobImage/index.tsx`
### Component Files - Mastery (3 files)
- [x] `/components/mastery/ExtendedMasterySelect/index.tsx`
- [x] `/components/mastery/AxSelect/index.tsx`
- [x] `/components/mastery/AwakeningSelectWithInput/index.tsx`
### Component Files - Reps (4 files)
- [x] `/components/reps/GridRep/index.tsx`
- [x] `/components/reps/CharacterRep/index.tsx`
- [x] `/components/reps/WeaponRep/index.tsx`
- [x] `/components/reps/SummonRep/index.tsx`
### Component Files - Common (2 files)
- [x] `/components/common/SelectWithInput/index.tsx`
- [x] `/components/common/Editor/index.tsx`
### Component Files - Extra (2 files)
- [x] `/components/extra/GuidebookUnit/index.tsx`
- [x] `/components/extra/GuidebookResult/index.tsx`
### Component Files - Other (11 files)
- [x] `/components/toasts/UpdateToast/index.tsx`
- [x] `/components/search/SearchModal/index.tsx`
- [x] `/components/raids/RaidCombobox/index.tsx`
- [x] `/components/filters/FilterModal/index.tsx`
- [x] `/components/MentionList/index.tsx`
- [x] `/components/Layout/index.tsx`
- [x] `/components/LanguageSwitch/index.tsx`
- [x] `/components/Header/index.tsx`
- [x] `/components/ElementToggle/index.tsx`
- [x] `/components/about/ChangelogUnit/index.tsx`
- [x] `/components/HovercardHeader/index.tsx`
### Utility Files (1 file)
- [x] `/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`:
```tsx
// 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]`:
```tsx
// Old (Pages Router)
const { id } = router.query
// New (App Router)
import { useParams } from 'next/navigation'
const params = useParams()
const id = params.id
```
### Programmatic Navigation
```tsx
// 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
- [x] All components use `next/navigation` imports
- [x] No references to `next/router` remain in components (only in pages/about.tsx which still needs migration)
- [x] All navigation functionality works as before
- [x] No console errors about "NextRouter was not mounted"
- [x] App runs successfully with `npm run dev`
- [ ] Build completes with `npm run build` (to be tested)