Description
src/main.tsx ships a custom renderRoute() function that inspects window.location.pathname, lazy-imports MarketplacePage/ApiDetailPage, and calls root.render() again on every popstate event (src/main.tsx:14-69). This runs in parallel with the React Router <Routes> block already declared in App.tsx:486-654, so the app effectively has two competing routers. As a result the /marketplace route inside App.tsx:504-516 renders a placeholder card, while the real MarketplacePage is only reachable through the bespoke main.tsx branch, and navigation uses history.pushState + manual PopStateEvent dispatch (src/pages/MarketplacePage.tsx:105-107) instead of router navigation.
This issue consolidates everything onto a single react-router-dom (v6.30.3, already in package.json:14) tree so /marketplace, /details/:id, and the existing app routes are all driven by one router.
Requirements and context
- Reduce
src/main.tsx to a single root.render() that mounts <BrowserRouter><ThemeProvider><App/></ThemeProvider></BrowserRouter>; remove renderRoute(), the popstate listener, and the dynamic import() branches.
- In
App.tsx replace the placeholder marketplace <section> (src/App.tsx:504-516) with <MarketplacePage /> and add a <Route path="/details/:id"> rendering ApiDetailPage.
- Update
ApiDetailPage to read the id via useParams() instead of parsing window.location.pathname (src/pages/ApiDetailPage.tsx:34-40), and replace its window.location.href = "/marketplace" back action (src/pages/ApiDetailPage.tsx:68) with useNavigate.
- Update
MarketplacePage.handleViewDetails (src/pages/MarketplacePage.tsx:104-108) to call navigate(\/details/${api.id}`)instead ofhistory.pushState+PopStateEvent`.
- Non-functional: keep
<React.StrictMode> and ThemeProvider wrapping, no console errors on back/forward navigation, and ensure code-splitting via React.lazy if bundle size matters.
Acceptance criteria
Suggested execution
1. Fork the repo and create a branch — git checkout -b feature/unify-react-router.
2. Implement changes — src/main.tsx, src/App.tsx, src/pages/MarketplacePage.tsx, src/pages/ApiDetailPage.tsx.
3. Write/extend tests — this repo currently has no test runner configured (package.json:6-10 exposes only dev/build/preview). Add Vitest + @testing-library/react + jsdom as devDependencies, a vitest.config.ts (or test block in vite.config.ts) with environment: "jsdom", and a "test": "vitest run" script. Add a routing smoke test that renders <MemoryRouter initialEntries={["/details/weather-001"]}> and asserts the detail page mounts.
4. Test and commit —
npm install
npm run dev # manually verify /marketplace and /details/:id
npm run build # tsc -b + vite build must pass
npm run test # vitest run (after adding the runner)
Example commit message
feat(routing): unify app on a single react-router tree and remove custom main.tsx router
Guidelines
- Any module you add tests for must reach ≥90% line coverage.
- Preserve keyboard accessibility of
ApiCard (role="button", tabIndex={0}) and ensure focus is not lost on navigation; update docs/comments that reference the old custom router.
- Timeframe: 96 hours.
Description
src/main.tsxships a customrenderRoute()function that inspectswindow.location.pathname, lazy-importsMarketplacePage/ApiDetailPage, and callsroot.render()again on everypopstateevent (src/main.tsx:14-69). This runs in parallel with the React Router<Routes>block already declared inApp.tsx:486-654, so the app effectively has two competing routers. As a result the/marketplaceroute insideApp.tsx:504-516renders a placeholder card, while the realMarketplacePageis only reachable through the bespokemain.tsxbranch, and navigation useshistory.pushState+ manualPopStateEventdispatch (src/pages/MarketplacePage.tsx:105-107) instead of router navigation.This issue consolidates everything onto a single
react-router-dom(v6.30.3, already inpackage.json:14) tree so/marketplace,/details/:id, and the existing app routes are all driven by one router.Requirements and context
src/main.tsxto a singleroot.render()that mounts<BrowserRouter><ThemeProvider><App/></ThemeProvider></BrowserRouter>; removerenderRoute(), thepopstatelistener, and the dynamicimport()branches.App.tsxreplace the placeholder marketplace<section>(src/App.tsx:504-516) with<MarketplacePage />and add a<Route path="/details/:id">renderingApiDetailPage.ApiDetailPageto read the id viauseParams()instead of parsingwindow.location.pathname(src/pages/ApiDetailPage.tsx:34-40), and replace itswindow.location.href = "/marketplace"back action (src/pages/ApiDetailPage.tsx:68) withuseNavigate.MarketplacePage.handleViewDetails(src/pages/MarketplacePage.tsx:104-108) to callnavigate(\/details/${api.id}`)instead ofhistory.pushState+PopStateEvent`.<React.StrictMode>andThemeProviderwrapping, no console errors on back/forward navigation, and ensure code-splitting viaReact.lazyif bundle size matters.Acceptance criteria
src/main.tsxmounts exactly one router and contains nopopstatelistener orrenderRoutefunction./marketplacerenders the realMarketplacePage(not the placeholder card)./details/:idrendersApiDetailPage, which resolves the id viauseParams.ApiCardand the "Back" button both navigate via React Router (no full page reload).npm run buildpasses with no TypeScript errors.Suggested execution
1. Fork the repo and create a branch —
git checkout -b feature/unify-react-router.2. Implement changes —
src/main.tsx,src/App.tsx,src/pages/MarketplacePage.tsx,src/pages/ApiDetailPage.tsx.3. Write/extend tests — this repo currently has no test runner configured (
package.json:6-10exposes onlydev/build/preview). Add Vitest +@testing-library/react+jsdomas devDependencies, avitest.config.ts(ortestblock invite.config.ts) withenvironment: "jsdom", and a"test": "vitest run"script. Add a routing smoke test that renders<MemoryRouter initialEntries={["/details/weather-001"]}>and asserts the detail page mounts.4. Test and commit —
Example commit message
Guidelines
ApiCard(role="button",tabIndex={0}) and ensure focus is not lost on navigation; update docs/comments that reference the old custom router.