Direct URL navigation on mobile (e.g. typing /garage/fuel-logs or /garage/maintenance in the address bar, or refreshing the page) renders the Dashboard instead of the correct page. Only bottom-nav button taps correctly navigate. This means bookmarked links and shared URLs break on mobile.
Acceptance Criteria
Direct URL navigation on mobile renders the correct page (not Dashboard)
Page refresh on mobile preserves the current route
Bookmarked and shared URLs work correctly on mobile
Bottom-nav navigation continues to work
Desktop routing unaffected
Tested on mobile (320px, 768px) and desktop (1920px)
Relates to #162
## Severity: Critical
## Problem
Direct URL navigation on mobile (e.g. typing `/garage/fuel-logs` or `/garage/maintenance` in the address bar, or refreshing the page) renders the Dashboard instead of the correct page. Only bottom-nav button taps correctly navigate. This means bookmarked links and shared URLs break on mobile.
## Acceptance Criteria
- Direct URL navigation on mobile renders the correct page (not Dashboard)
- Page refresh on mobile preserves the current route
- Bookmarked and shared URLs work correctly on mobile
- Bottom-nav navigation continues to work
- Desktop routing unaffected
- Tested on mobile (320px, 768px) and desktop (1920px)
Mobile navigation uses Zustand state-based nav (activeScreen in the navigation store), NOT React Router. When a user navigates directly to a URL like /garage/maintenance, the browser path is ignored and the Dashboard screen renders instead. URLs and Zustand screen state are never synchronized.
Implementation
1. Create route-to-screen mapping in frontend/src/core/store/navigation.ts:
2. In frontend/src/App.tsx, add useEffect for URL-to-screen sync on mount:
Read window.location.pathname
Map to MobileScreen value using the mapping above
Call navigateToScreen() from Zustand store
URL takes precedence on initial load
3. Sync screen changes back to browser URL:
When activeScreen changes in Zustand, call window.history.replaceState() to update the browser URL
This enables bookmark support and URL sharing
4. Prevent stale localStorage override:
Remove activeScreen from Zustand partialize persist config to avoid stale localStorage overriding URLs on reload
Files
frontend/src/App.tsx
frontend/src/core/store/navigation.ts
Commit Convention
fix: sync mobile routing with browser URL for direct navigation (refs #163)
Test Criteria
Direct URL navigation on mobile (e.g., /garage/maintenance) renders the correct page
Page refresh preserves the current route
Back/forward browser buttons work correctly
Tapping nav items in bottom bar and hamburger menu updates the URL
Desktop routing is unaffected
Verify on mobile (320px, 768px) and desktop (1920px) viewports
Risk Notes
Highest complexity milestone. Zustand/URL sync must not break existing navigation flows.
Test all navigation paths: bottom nav, hamburger menu, quick actions, breadcrumbs.
Branch
Work on branch issue-162-ux-design-audit-cleanup (shared with all #162 sub-issues)
## Implementation Plan (from #162 -- Milestone 2)
**Phase**: 1 (Foundation) | **Priority**: Critical | **Depends on**: None | **Blocks**: None
### Context
Mobile navigation uses Zustand state-based nav (`activeScreen` in the navigation store), NOT React Router. When a user navigates directly to a URL like `/garage/maintenance`, the browser path is ignored and the Dashboard screen renders instead. URLs and Zustand screen state are never synchronized.
### Implementation
**1. Create route-to-screen mapping in `frontend/src/core/store/navigation.ts`:**
```typescript
const routeToScreen: Record<string, MobileScreen> = {
'/garage/dashboard': 'Dashboard',
'/garage/vehicles': 'Vehicles',
'/garage/fuel-logs': 'Log Fuel',
'/garage/maintenance': 'Maintenance',
'/garage/documents': 'Documents',
'/garage/stations': 'Stations',
'/garage/settings': 'Settings',
};
```
**2. In `frontend/src/App.tsx`, add `useEffect` for URL-to-screen sync on mount:**
- Read `window.location.pathname`
- Map to `MobileScreen` value using the mapping above
- Call `navigateToScreen()` from Zustand store
- URL takes precedence on initial load
**3. Sync screen changes back to browser URL:**
- When `activeScreen` changes in Zustand, call `window.history.replaceState()` to update the browser URL
- This enables bookmark support and URL sharing
**4. Prevent stale localStorage override:**
- Remove `activeScreen` from Zustand `partialize` persist config to avoid stale localStorage overriding URLs on reload
### Files
- `frontend/src/App.tsx`
- `frontend/src/core/store/navigation.ts`
### Commit Convention
```
fix: sync mobile routing with browser URL for direct navigation (refs #163)
```
### Test Criteria
- Direct URL navigation on mobile (e.g., `/garage/maintenance`) renders the correct page
- Page refresh preserves the current route
- Back/forward browser buttons work correctly
- Tapping nav items in bottom bar and hamburger menu updates the URL
- Desktop routing is unaffected
- Verify on mobile (320px, 768px) and desktop (1920px) viewports
### Risk Notes
- **Highest complexity milestone**. Zustand/URL sync must not break existing navigation flows.
- Test all navigation paths: bottom nav, hamburger menu, quick actions, breadcrumbs.
### Branch
Work on branch `issue-162-ux-design-audit-cleanup` (shared with all #162 sub-issues)
Added routeToScreen mapping: 16 URL paths to MobileScreen values (including /garage, /garage/dashboard, all feature and admin routes)
Added screenToRoute reverse mapping: MobileScreen values to canonical URL paths
Removed activeScreen from partialize persist config to prevent stale localStorage from overriding URL on reload
2. URL sync effects (App.tsx)
Added mount-time useEffect: reads window.location.pathname, maps via routeToScreen, calls navigateToScreen() so direct URLs render the correct screen
Added activeScreen watcher useEffect: calls window.history.replaceState() to keep browser URL in sync when Zustand state changes (enables bookmarks and URL sharing)
3. Store barrel export (store/index.ts)
Exported routeToScreen and screenToRoute for use in App.tsx
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Relates to #162
Severity: Critical
Problem
Direct URL navigation on mobile (e.g. typing
/garage/fuel-logsor/garage/maintenancein the address bar, or refreshing the page) renders the Dashboard instead of the correct page. Only bottom-nav button taps correctly navigate. This means bookmarked links and shared URLs break on mobile.Acceptance Criteria
Implementation Plan (from #162 -- Milestone 2)
Phase: 1 (Foundation) | Priority: Critical | Depends on: None | Blocks: None
Context
Mobile navigation uses Zustand state-based nav (
activeScreenin the navigation store), NOT React Router. When a user navigates directly to a URL like/garage/maintenance, the browser path is ignored and the Dashboard screen renders instead. URLs and Zustand screen state are never synchronized.Implementation
1. Create route-to-screen mapping in
frontend/src/core/store/navigation.ts:2. In
frontend/src/App.tsx, adduseEffectfor URL-to-screen sync on mount:window.location.pathnameMobileScreenvalue using the mapping abovenavigateToScreen()from Zustand store3. Sync screen changes back to browser URL:
activeScreenchanges in Zustand, callwindow.history.replaceState()to update the browser URL4. Prevent stale localStorage override:
activeScreenfrom Zustandpartializepersist config to avoid stale localStorage overriding URLs on reloadFiles
frontend/src/App.tsxfrontend/src/core/store/navigation.tsCommit Convention
Test Criteria
/garage/maintenance) renders the correct pageRisk Notes
Branch
Work on branch
issue-162-ux-design-audit-cleanup(shared with all #162 sub-issues)Milestone: Mobile URL-to-Screen Sync
Phase: Execution | Agent: Developer | Status: PASS
Changes Made
1. Route-to-screen mapping (
navigation.ts)routeToScreenmapping: 16 URL paths toMobileScreenvalues (including/garage,/garage/dashboard, all feature and admin routes)screenToRoutereverse mapping:MobileScreenvalues to canonical URL pathsactiveScreenfrompartializepersist config to prevent stale localStorage from overriding URL on reload2. URL sync effects (
App.tsx)useEffect: readswindow.location.pathname, maps viarouteToScreen, callsnavigateToScreen()so direct URLs render the correct screenactiveScreenwatcheruseEffect: callswindow.history.replaceState()to keep browser URL in sync when Zustand state changes (enables bookmarks and URL sharing)3. Store barrel export (
store/index.ts)routeToScreenandscreenToRoutefor use in App.tsxFiles Modified
frontend/src/core/store/navigation.ts- route mappings + persist fixfrontend/src/App.tsx- URL sync effectsfrontend/src/core/store/index.ts- exportsVerification
Commit
0e8c607-fix: sync mobile routing with browser URL for direct navigation (refs #163)Verdict: PASS | Next: Browser testing on mobile (320px, 768px) and desktop (1920px) viewports