Agent skill
react-router-setup
Add URL routing to React Vite SPAs using react-router-dom v6. Use when asked to "add routing", "add URL navigation", "make URLs work", "add deep linking", "enable browser back/forward", or when converting state-based navigation to URL-based routing. Covers installation, BrowserRouter configuration with basename, route definitions, nested routes, Link components, useNavigate hooks, redirects, and SPA server fallback.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/react-router-setup
SKILL.md
React Router Setup for Vite SPAs
Add react-router-dom v6 to existing React Vite projects.
Installation
npm install react-router-dom
# or
pnpm add react-router-dom
Setup Steps
1. Wrap App with BrowserRouter
In main.tsx:
import { BrowserRouter } from 'react-router-dom';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<BrowserRouter basename="/app">
{' '}
{/* basename for SPA base path */}
<App />
</BrowserRouter>
</React.StrictMode>
);
basename: Set to your SPA's base path (e.g., /dashboard, /app). All routes become relative to this.
2. Create Route Constants
Create routes.ts for type-safe route management:
export const ROUTES = {
HOME: '/',
USERS: '/users',
USER_DETAIL: '/users/:id',
SETTINGS: '/settings',
SETTINGS_PROFILE: '/settings/profile',
} as const;
// Derive state from URL path
export function getRouteState(pathname: string) {
if (pathname.startsWith('/users')) return { view: 'users' };
if (pathname.startsWith('/settings')) return { view: 'settings' };
return { view: 'home' };
}
3. Add Routes Component
Using Routes and Route:
import { Routes, Route, Navigate } from 'react-router-dom';
function App() {
return (
<Routes>
<Route path="/" element={<Navigate to="/home" replace />} />
<Route path="/home" element={<Home />} />
<Route path="/users" element={<Users />} />
<Route path="/users/:id" element={<UserDetail />} />
<Route path="/settings" element={<Navigate to="/settings/profile" replace />} />
<Route path="/settings/profile" element={<SettingsProfile />} />
<Route path="/settings/account" element={<SettingsAccount />} />
<Route path="*" element={<Navigate to="/home" replace />} />
</Routes>
);
}
4. Convert Navigation
Replace buttons with Link:
// Before
<button onClick={() => setView('users')}>Users</button>;
// After
import { Link } from 'react-router-dom';
<Link to="/users">Users</Link>;
Use navigate() for programmatic navigation:
import { useNavigate } from 'react-router-dom';
function Component() {
const navigate = useNavigate();
const handleClick = () => {
navigate('/users'); // push
navigate('/users', { replace: true }); // replace
navigate(-1); // back
};
}
5. Derive State from URL
Replace state variables with URL-derived state:
import { useLocation } from 'react-router-dom';
function App() {
const location = useLocation();
// Before: const [activeView, setActiveView] = useState('home');
// After: derive from URL
const activeView = useMemo(() => {
if (location.pathname.startsWith('/users')) return 'users';
if (location.pathname.startsWith('/settings')) return 'settings';
return 'home';
}, [location.pathname]);
}
6. Active Link Styling
import { useLocation, Link } from 'react-router-dom';
function NavLink({ to, children }) {
const location = useLocation();
const isActive = location.pathname.startsWith(to);
return (
<Link to={to} className={isActive ? 'active' : ''}>
{children}
</Link>
);
}
7. URL Parameters
import { useParams, useSearchParams } from 'react-router-dom';
function UserDetail() {
const { id } = useParams(); // from /users/:id
const [searchParams, setSearchParams] = useSearchParams();
const tab = searchParams.get('tab') || 'profile';
return (
<div>
User {id}, Tab: {tab}
</div>
);
}
Server SPA Fallback
The server must serve index.html for all non-API routes.
Express:
app.get('/*', (req, res, next) => {
if (req.path.startsWith('/api')) return next();
res.sendFile(path.join(staticPath, 'index.html'));
});
Vite dev server handles this automatically.
Nginx:
location / {
try_files $uri $uri/ /index.html;
}
Common Pitfalls
- Missing basename: If SPA is at
/app, setbasename="/app"in BrowserRouter - Hash vs History: Use BrowserRouter (history API), not HashRouter, for clean URLs
- Refresh fails: Server must return index.html for all routes (SPA fallback)
- Link vs anchor: Always use
<Link>not<a>for internal navigation - State not updating: Derive state from
location.pathname, don't maintain separate state
Testing Checklist
- Direct URL access works (e.g.,
/app/users/123) - Browser back/forward navigation works
- Page refresh on nested routes works
- Sidebar/nav highlighting matches URL
- Redirects work (root → default route)
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?