Stop Hardcoding Routes in Next.js: Use This Scalable Pattern Instead

4 min readNextJS
#next.js#tips
Stop Hardcoding Routes in Next.js: Use This Scalable Pattern Instead

When building Next.js apps, most developers write route paths directly in their code (means they hard-code the route path). This seems easy and fast at first, but it creates big problems when your app grows bigger.

The Problem with Hardcoded Routes

Consider this common pattern you've probably seen (or written) before:

tsx
1// ❌ Problematic approach 2 3import Link from 'next/link' 4import { useRouter } from 'next/router' 5 6export default function Navbar() { 7 const router = useRouter() 8 9 const handleNavigation = () => { 10 router.push('/dashboard/user/profile') 11 } 12 13 return ( 14 <nav> 15 <Link href="/about">About</Link> 16 <Link href="/contact">Contact</Link> 17 <Link href="/blog">Blog</Link> 18 <Link href="/dashboard/analytics">Analytics</Link> 19 <button onClick={handleNavigation}>Profile</button> 20 </nav> 21 ) 22}

In above code snippet all the route path are hard-coded.

Why This Approach Fails

1. Maintenance Issue When you need to change a route from /blog to /articles, you'll have to hunt through your entire codebase to find and update every occurrence.

2. Chances of Typos It's easy to mistype /dashbord instead of /dashboard, leading to broken links that might not be caught until production.

3. No IntelliSense Support Your IDE can't help you with autocomplete or catch errors when routes are just strings scattered throughout your code.

4. Team Collaboration Issues Different team members might use slightly different paths for the same route, creating inconsistencies.

5. Testing Difficulties Hardcoded routes make it harder to write comprehensive tests and mock navigation behavior.

The Solution: Centralized Route Management

The solution is to create a centralized route configuration that serves as the single source of truth for all your application's routes.

Let me show you how with step by step process.

Step 1: Create Your Routes Configuration

First, create a dedicated file for your routes. I recommend placing it in a constants or config directory:

bash
1/src 2 /app 3 /components 4 /constants 5 └── routes.ts 6 /lib

Step 2: Define Your Routes Object

ts
1// constants/routes.ts 2export const ROUTES = { 3 // Public routes 4 HOME: '/', 5 ABOUT: '/about', 6 CONTACT: '/contact', 7 PRICING: '/pricing', 8 9 // Auth routes 10 LOGIN: '/auth/login', 11 REGISTER: '/auth/register', 12 FORGOT_PASSWORD: '/auth/forgot-password', 13 14 // Blog routes 15 BLOG: '/blog', 16 BLOG_DETAIL: (slug: string) => `/blog/${slug}`, 17 BLOG_CATEGORY: (category: string) => `/blog/category/${category}`, 18 19 // Dashboard routes 20 DASHBOARD: '/dashboard', 21 DASHBOARD_ANALYTICS: '/dashboard/analytics', 22 DASHBOARD_SETTINGS: '/dashboard/settings', 23 DASHBOARD_PROFILE: '/dashboard/profile', 24 25 // Dynamic user routes 26 USER_PROFILE: (userId: string) => `/user/${userId}`, 27 USER_POSTS: (userId: string) => `/user/${userId}/posts`, 28 29 // API routes (useful for fetch calls) 30 API: { 31 USERS: '/api/users', 32 POSTS: '/api/posts', 33 AUTH: '/api/auth', 34 }, 35} as const 36 37// Export route groups for better organization 38export const AUTH_ROUTES = { 39 LOGIN: ROUTES.LOGIN, 40 REGISTER: ROUTES.REGISTER, 41 FORGOT_PASSWORD: ROUTES.FORGOT_PASSWORD, 42} as const 43 44export const DASHBOARD_ROUTES = { 45 HOME: ROUTES.DASHBOARD, 46 ANALYTICS: ROUTES.DASHBOARD_ANALYTICS, 47 SETTINGS: ROUTES.DASHBOARD_SETTINGS, 48 PROFILE: ROUTES.DASHBOARD_PROFILE, 49} as const

Step 3: Use Routes in Your Components

Now your components become much cleaner and more maintainable:

tsx
1// components/Navbar.tsx 2import Link from 'next/link' 3import { useRouter } from 'next/router' 4import { ROUTES, DASHBOARD_ROUTES } from '@/constants/routes' 5 6export default function Navbar() { 7 const router = useRouter() 8 9 const handleProfileNavigation = () => { 10 router.push(DASHBOARD_ROUTES.PROFILE) 11 } 12 13 return ( 14 <nav className="flex space-x-4"> 15 <Link href={ROUTES.ABOUT} className="hover:text-blue-500"> 16 About 17 </Link> 18 <Link href={ROUTES.CONTACT} className="hover:text-blue-500"> 19 Contact 20 </Link> 21 <Link href={ROUTES.BLOG} className="hover:text-blue-500"> 22 Blog 23 </Link> 24 <Link href={DASHBOARD_ROUTES.ANALYTICS} className="hover:text-blue-500"> 25 Analytics 26 </Link> 27 <button 28 onClick={handleProfileNavigation} 29 className="rounded bg-blue-500 px-4 py-2 text-white" 30 > 31 Profile 32 </button> 33 </nav> 34 ) 35}

Step 4: Handle Dynamic Routes Elegantly

Dynamic routes become much more readable and type-safe:

tsx
1// components/BlogList.tsx 2import Link from 'next/link' 3import { ROUTES } from '@/constants/routes' 4 5interface Post { 6 slug: string 7 title: string 8 category: string 9} 10 11interface BlogListProps { 12 posts: Post[] 13} 14 15export default function BlogList({ posts }: BlogListProps) { 16 return ( 17 <div className="space-y-4"> 18 {posts.map((post) => ( 19 <article key={post.slug} className="rounded border p-4"> 20 <h2 className="text-xl font-bold"> 21 <Link href={ROUTES.BLOG_DETAIL(post.slug)} className="hover:text-blue-500"> 22 {post.title} 23 </Link> 24 </h2> 25 <Link 26 href={ROUTES.BLOG_CATEGORY(post.category)} 27 className="text-sm text-gray-500 hover:text-blue-500" 28 > 29 Category: {post.category} 30 </Link> 31 </article> 32 ))} 33 </div> 34 ) 35}

Benefits of This Approach

  • No Repetition – Define once, use everywhere.

  • No Typos – Reduce the risk of route misnaming.

  • Easy Refactor – Change the route in one place, and it updates across the app.

  • Scalable – As your app grows, this structure keeps things organized.

  • Improved Development Experience – You get autocomplete and type safety in editors like VSCode.

Centralizing your routes in a routes.ts file is a small habit that pays off big in the long run. It keeps your code DRY, readable, and easier to maintain, especially in teams and large-scale projects.

Start doing this early in your Next.js projects, and you’ll thank yourself later.

ShareTwitterLinkedIn

Written by

Abdul Basit

Frontend developer passionate about JavaScript, React, and building great web experiences. Writing about web development to help developers level up their skills.

Continue reading