ITADN
obra/lace/Issues

Migrate from hash-based routing to Next.js standard routing

#110Openobra 创建于 2025-07-28
enhancement
O
obracommented
## Problem The current hash-based routing architecture has multiple sources of truth for navigation state, causing bugs like: - "Configure Session" button not working (calling `setSelectedAgent(undefined)` instead of router method) - State synchronization issues between URL hash and component state - Manual state management that's error-prone ## Current Architecture Issues 1. **Dual State Management**: Hash router manages URL state, but components also have local `selectedAgent` state 2. **Manual Synchronization**: Every navigation action requires remembering to call the right router method 3. **State Conflicts**: Local state can get out of sync with URL state ## Proposed Solution: Next.js Standard Routing ### New Route Structure ``` app/ ├── page.tsx # "/" - Root redirect to /projects ├── projects/ │ ├── page.tsx # "/projects" - Project selector │ └── [projectId]/ │ ├── page.tsx # "/projects/123" - Project overview with sessions │ ├── configure/ │ │ └── page.tsx # "/projects/123/configure" - Project config │ └── sessions/ │ ├── [sessionId]/ │ │ ├── page.tsx # "/projects/123/sessions/456" - Session config │ │ └── agents/ │ │ └── [agentId]/ │ │ └── page.tsx # "/projects/123/sessions/456/agents/789" - Agent chat │ └── new/ │ └── page.tsx # "/projects/123/sessions/new" - Create session ``` ### Navigation Hook ```typescript // hooks/useAppNavigation.ts import { useRouter, useParams } from 'next/navigation'; import type { ThreadId } from '@/lib/server/core-types'; export function useAppNavigation() { const router = useRouter(); const params = useParams(); return { // Current state (derived from URL) currentProject: params.projectId as string | undefined, currentSession: params.sessionId as ThreadId | undefined, currentAgent: params.agentId as ThreadId | undefined, // Navigation methods selectProject: (projectId: string) => { router.push('/projects/' + projectId); }, createSession: (projectId: string) => { router.push('/projects/' + projectId + '/sessions/new'); }, selectSession: (projectId: string, sessionId: ThreadId) => { router.push('/projects/' + projectId + '/sessions/' + sessionId); }, selectAgent: (projectId: string, sessionId: ThreadId, agentId: ThreadId) => { router.push('/projects/' + projectId + '/sessions/' + sessionId + '/agents/' + agentId); }, configureSession: (projectId: string, sessionId: ThreadId) => { router.push('/projects/' + projectId + '/sessions/' + sessionId); }, configureProject: (projectId: string) => { router.push('/projects/' + projectId + '/configure'); }, goBack: () => router.back(), goToProjects: () => router.push('/projects'), }; } ``` ## Migration Steps ### Phase 1: Create New Routes 1. Create the new page structure in app/ 2. Move existing components to new pages 3. Add the useAppNavigation hook ### Phase 2: Update Components 1. Replace useHashRouter with useAppNavigation 2. Remove local state for navigation (selectedAgent, etc.) 3. Update all navigation calls to use new methods ### Phase 3: Clean Up 1. Remove hash router files 2. Update any remaining navigation references 3. Test all navigation flows ## Benefits After Migration - ✅ **No more state sync issues** - URL is single source of truth - ✅ **Proper browser navigation** - Back/forward work perfectly - ✅ **Shareable URLs** - /projects/123/sessions/456/agents/789 - ✅ **Simpler components** - No navigation state management - ✅ **Better SEO** - Real URLs instead of hash fragments - ✅ **Standard Next.js patterns** - Easier for other devs ## Acceptance Criteria - [ ] New route structure implemented - [ ] useAppNavigation hook created and tested - [ ] All components migrated from hash router to new navigation - [ ] Hash router code removed - [ ] All navigation flows working properly - [ ] Browser back/forward navigation working - [ ] URLs are shareable and work on page refresh
0 条评论