Understanding File-System Routing
Understanding File-System Routing
Section titled “Understanding File-System Routing”Introduction
Section titled “Introduction”Next.js uses a file-system based routing mechanism where the structure of the pages directory directly defines the routes of your application. This intuitive approach eliminates the need for manual route configuration and makes navigation predictable.
Why do we need this?
Section titled “Why do we need this?”Traditional routing requires explicit route definitions in a separate configuration file, which can become cumbersome and error-prone as applications grow. File-system routing simplifies this by making the route structure visible and directly tied to your file organization.
Problem Statement
Section titled “Problem Statement”Manually configuring routes in a separate file leads to duplication of effort, potential mismatches between UI and route configuration, and a steeper learning curve for new developers joining the project.
Real World Story
Section titled “Real World Story”You’re working on a blog application and need to add a new section for tutorials. With file-system routing, you simply create a tutorials folder inside pages and add an index.js file. Instantly, the /tutorials route is available without touching any routing configuration.
Real World Analogy
Section titled “Real World Analogy”Think of file-system routing like organizing files in a cabinet:
- Each drawer represents a route section (
/blog,/api,/admin) - Folders inside drawers represent nested routes (
/blog/2023,/api/v1/users) - Files are the actual pages that get displayed
- Just as you can instantly see what’s in each drawer by opening it, you can instantly see what routes exist by looking at the
pagesfolder structure
Visual Explanation
Section titled “Visual Explanation”The pages directory uses a tree structure where each file or folder corresponds to a route segment.
Mermaid Diagram 1: File-to-Route Mapping
Section titled “Mermaid Diagram 1: File-to-Route Mapping”graph TD A[pages/index.js] --> B[Route: /] C[pages/about.js] --> D[Route: /about] E[pages/blog/index.js] --> F[Route: /blog] G[pages/blog/[slug].js] --> H[Route: /blog/:slug] I[pages/products/index.js] --> J[Route: /products] K[pages/products/[id].js] --> L[Route: /products/:id] M[pages/api/users.js] --> N[Route: /api/users] O[pages/api/posts/[id].js] --> P[Route: /api/posts/:id]Internal Working
Section titled “Internal Working”When Next.js starts, it:
- Scans the
pages/directory recursively - Maps each
.js,.jsx,.ts,.tsxfile to a route based on its path - Handles special filenames (
_app.js,_document.js, etc.) differently - Creates a route object for each page that includes:
- The page component
- Data fetching functions (
getStaticProps,getServerSideProps, etc.) - Route parameters info (for dynamic routes)
- Uses this route map to handle incoming requests and client-side navigation
Mermaid Diagram 2: Route Resolution Process
Section titled “Mermaid Diagram 2: Route Resolution Process”flowchart TD A[HTTP Request] --> B[Next.js Router] B --> C{Match Route} C -->|Static File| D[Serve Static File from public/] C -->|Page Route| E[Render Page Component] C -->|API Route| F[Execute API Handler] D --> G[Send File] E --> H[Execute Component] E --> I[Apply Data Fetching] E --> J[Generate HTML] E --> K[Send HTML + JS] F --> L[Run Handler] F --> M[Return JSON/Response] G --> H H --> N[Send Response] I --> O[Send Response] J --> P[Send Response] K --> Q[Send Response] L --> R[Send Response] M --> S[Send Response] N --> T[Send Response] O --> U[Send Response] P --> V[Send Response] Q --> W[Send Response]Architecture
Section titled “Architecture”Next.js routing is built on the principle of convention over configuration. The framework automatically determines routes based on the file system structure, eliminating the need for external route configuration files. This approach provides:
- Predictable routing based on file locations
- Automatic code splitting per route
- Seamless integration with data fetching methods
- Support for static site generation (SSG), server-side rendering (SSR), and incremental static regeneration (ISR)
- Built-in support for API routes
Marks of a Route
Section titled “Marks of a Route”Static Routes
Section titled “Static Routes”Files like pages/about.js map directly to /about.
Dynamic Routes
Section titled “Dynamic Routes”Files using bracket notation like pages/posts/[id].js map to /posts/:id, where id is a dynamic parameter.
Catch-all Routes
Section titled “Catch-all Routes”Files like pages/[...slug].js match /slug/* (one or more segments).
Optional Catch-all
Section titled “Optional Catch-all”Files like pages/[[...slug]].js match /:slug* (zero or more segments).
API Routes
Section titled “API Routes”Files in pages/api/ are treated as API endpoints rather than pages.
Step-by-Step Flow
Section titled “Step-by-Step Flow”- File Creation: Add a file to the
pages/directory (e.g.,pages/blog/post.js) - Route Detection: Next.js scans the directory and maps the file to a route (
/blog/post) - Component Rendering: When the route is accessed, the file’s default export is rendered as a React component
- Data Fetching: If the component exports
getStaticPropsorgetServerSideProps, data is fetched accordingly - Response: The rendered HTML (or JSON for API routes) is sent to the client
Syntax
Section titled “Syntax”Basic Page
Section titled “Basic Page”export default function About() { return <div>About Us</div>;}Dynamic Route
Section titled “Dynamic Route”export default function Post({ params }) { return <div>Post ID: {params.id}</div>;}Catch-all Route
Section titled “Catch-all Route”export default function Path({ params }) { return <div>Path: {params.slug.join('/')}</div>;}API Route
Section titled “API Route”export default function handler(req, res) { res.status(200).json({ message: 'Hello' });}Basic Example
Section titled “Basic Example”Setting up basic navigation:
import Link from 'next/link';
export default function Home() { return ( <div> <h1>Home</h1> <nav> <Link href="/about"> <a>About</a> </Link> | <Link href="/blog"> <a>Blog</a> </Link> </nav> </div> );}Intermediate Example
Section titled “Intermediate Example”Creating a dynamic route for blog posts:
import Link from 'next/link';
export default function Post({ params }) { return ( <div> <h1>Post: {params.slug}</h1> <p>Content for post {params.slug}</p> <Link href="/posts"> <a>All Posts</a> </Link> </div> );}Advanced Example
Section titled “Advanced Example”Implementing a catch-all route for documentation:
import Link from 'next/link';
export default function Docs({ params }) { const path = params.slug ? `/${params.slug.join('/')}` : '/';
return ( <div> <h1>Documentation</h1> <p>Current path: {path}</p> <nav> <Link href="/docs"> <a>Overview</a> </Link> | <Link href="/docs/getting-started"> <a>Getting Started</a> </Link> </nav> </div> );}Production Example
Section titled “Production Example”In production, Next.js optimizes routes:
- Static routes (e.g.,
/about) are pre-rendered as HTML at build time - Dynamic routes (e.g.,
/posts/[id]) use the appropriate rendering strategy (SSG, SSR, or CSR) based on data fetching methods - API routes become serverless functions on platforms like Vercel
- Client-side navigation via
next/linkprovides instant transitions without full page reloads - Prefetching: Links in the viewport are preloaded for faster navigation
Folder Structure
Section titled “Folder Structure”A typical pages directory structure:
pages/├── api/ # API Routes│ ├── auth/│ │ ├── login.js│ │ └── register.js│ ├── users/│ │ └── [id].js│ └── posts.js├── admin/ # Admin Section│ ├── index.js → /admin│ ├── dashboard.js → /admin/dashboard│ └── users/│ ├── index.js → /admin/users│ └── [id].js → /admin/users/:id├── blog/ # Blog Section│ ├── index.js → /blog│ ├── [slug].js → /blog/:slug│ └── feed.xml → /blog/feed.xml (static file)├── products/ # Products Section│ ├── index.js → /products│ ├── [id].js → /products/:id│ └── categories/│ └── [slug].js → /products/categories/:slug├── users/ # User Profiles│ └── [username].js → /:username├── _app.js # Custom App├── _document.js # Custom Document├── 404.js # Custom 404 Page├── 500.js # Custom 500 Page└── index.js → / (Homepage)Best Practices
Section titled “Best Practices”- Keep pages directory focused: Only place files that define routes here
- Use meaningful folder names: Reflect your site’s information architecture
- Leverage dynamic routes: For data-driven content (blog posts, products, users)
- Consider URL design: Make URLs intuitive, SEO-friendly, and consistent
- Use index.js for folder indexes: Represents the “main” page of a section
- Avoid deep nesting: While possible, deeply nested URLs can be hard to manage
- Leverage API routes: Keep backend logic close to frontend code
- Use route groups (App Router): For organizing routes without changing URL paths
- Implement proper 404 handling: Create a custom 404 page for better UX
- Consider backward compatibility: When changing URLs, implement redirects (via middleware or
next.config.js)
Common Mistakes
Section titled “Common Mistakes”- Placing components in pages/: This creates unintended routes (every file in
pagesbecomes a route) - Inconsistent naming: Mixing
snake_case,camelCase, andkebab-caseleads to confusing URLs - Forgetting index.js: Accessing
/blogfails ifpages/blog/index.jsdoesn’t exist - Overlooking route precedence: Static routes are matched before dynamic ones (e.g.,
/blog/creatematches before/blog/[slug]if both exist) - Misunderstanding catch-all vs optional catch-all:
[...slug]requires at least one segment,[[...slug]]allows zero segments - Neglecting edge cases: Empty parameters, special characters in dynamic segments, and trailing slashes
- Using reserved filenames: Avoid names that conflict with system files or directories
- Ignoring case sensitivity: On case-sensitive systems (
/Blog≠/blog) - Forgetting to restart dev server: After adding new files/folders, the dev server may not detect them until restarted
- Mixing Pages and App Router: In Next.js 13+, understanding the distinction between the two routing systems
Performance Notes
Section titled “Performance Notes”- Static Routes: Fastest - served as pre-rendered HTML (if using SSG)
- Static Generation with Revalidation (ISR): Balances freshness and performance
- Server-Side Rendering (SSR): Slower initial load but always up-to-date data
- Client-Side Rendering (CSR): Quickest initial HTML but requires client-side data fetching
- Route Prefetching:
next/linkcomponent automatically prefetches linked pages in the viewport - Client-side Navigation: Near-instantaneous transitions (no full page reload)
- Code Splitting: Each route gets its own JavaScript bundle, reducing initial load time
- Dynamic Imports: Further split code within routes using
next/dynamicfor large components - Edge Functions: For ultra-low latency, consider deploying middleware or API routes to edge networks
Security Notes
Section titled “Security Notes”- Input Validation: Always validate parameters from dynamic routes (e.g., ensure an ID is a number)
- Path Traversal Protection: While Next.js prevents filesystem access, still sanitize user input
- API Route Security: Apply authentication, authorization, and rate limiting to API endpoints
- CORS Configuration: Configure Cross-Origin Resource Sharing headers for API routes as needed
- Secure Headers: Implement security headers (CSP, HSTS, X-Frame-Options) via middleware or headers API
- Dependency Management: Regularly audit dependencies with
npm auditoryarn audit - Environment Variables: Never expose secrets in client-side code; use
.env.localfor server-only values - Error Handling: Implement proper error boundaries and error pages (404, 500) to avoid leaking stack traces
SEO Considerations
Section titled “SEO Considerations”- Descriptive URLs: Use readable, keyword-rich paths (e.g.,
/blog/nextjs-routing-tipsvs/blog/post123) - Canonical URLs: Prevent duplicate content by specifying preferred URLs
- Trailing Slashes: Be consistent (configure via
next.config.js->trailingSlash: true) - URL Hierarchy: Reflect content structure in URLs (e.g.,
/category/subcategory/item) - Pagination: Use proper
rel="next"andrel="prev"links for paginated content - Meta Tags: Use the
next/headcomponent to set title, description, and open graph tags - Structured Data: Implement JSON-LD for rich snippets (recipes, events, products, etc.)
- Image Optimization: Use
next/imagefor optimized, responsive images with properalttext - Sitemap Generation: Automatically generate
sitemap.xmlbased on your routes - Robots.txt: Control search engine crawling with a
robots.txtfile inpublic/
Interview Questions
Section titled “Interview Questions”- How does Next.js determine the route for a given file in the
pagesdirectory? - What is the difference between
pages/blog/index.jsandpages/blog.js? - How do you create a dynamic route for a resource with an ID (e.g.,
/posts/123)? - What is the difference between
[param].js,[...param].js, and[[...param]].jsin Next.js routing? - How do you create an API route in Next.js, and what HTTP methods does it support?
- What special files does Next.js recognize in the
pagesdirectory (e.g.,_app.js,_document.js)? - How does Next.js handle 404 errors (page not found)?
- What is route precedence in Next.js, and how does it affect conflicting routes?
- How would you implement a redirect from an old URL to a new one in Next.js?
- How does Next.js support internationalized (i18n) routing?
- What is the difference between
getStaticPathsandgetStaticPropsfor dynamic routes? - How can you prevent a route from being indexed by search engines (e.g., using
robots.txt)? - What is the purpose of the
basePathconfiguration innext.config.js? - How does Next.js handle trailing slashes in URLs, and how can you configure this behavior?
- What are the performance implications of using dynamic routes vs static routes?
-
Which file creates the route
/blog/2023/05? a)pages/blog/2023/05.jsb)pages/blog/[year]/[month].jsc)pages/blog/2023/05/index.jsd)pages/blog/[...slug].jsAnswer
-
What does
pages/[...slug].jsmatch? a) Only/b)/and/anythingc)/anythingand/anything/anything(one or more segments) d) Only/somethingAnswer
-
Which file would create the route
/admin/dashboard/settings? a)pages/admin/dashboard/settings.jsb)pages/admin/[...segments].jsc)pages/admin/dashboard/index.jsd)pages/admin/[section]/[subsection].jsAnswer
-
How do you access a dynamic route parameter in a page component using the
pagesrouter? a)props.paramsb)this.paramsc)useRouter().queryd) All of the aboveAnswer
-
What special file is used to customize the
<html>and<body>tags in Next.js? a)_app.jsb)_document.jsc)custom-html.jsd)head.jsAnswer
-
What is the difference between
[param].jsand[[...param]].js? a)[param].jsmatches one segment,[[...param]].jsmatches zero or more segments b)[param].jsmatches zero or more segments,[[...param]].jsmatches one or more segments c) Both match the same thing d)[param].jsis for API routes,[[...param]].jsis for pagesAnswer
-
How does Next.js handle a request for a route that doesn’t match any file? a) Returns a 500 error b) Returns a 404 error with a default page c) Redirects to the homepage d) Serves the
index.jsfileAnswer
-
What is the purpose of the
pages/apidirectory? a) To store application logic b) To define custom middleware c) To create API routes (serverless functions) d) To store static assetsAnswer
-
Which file would create the route
/docs/v1/introduction? a)pages/docs/v1/introduction.jsb)docs/[version]/[topic].jsc)pages/docs/[version]/[topic].jsd)pages/docs/[...slug].jsAnswer
-
How do you access route parameters in a server-side function like
getStaticProps? a)paramsargument b)queryargument c)request.paramsd)context.routeAnswer
Practice Exercise
Section titled “Practice Exercise”- Create a new Next.js project called
routing-exercise - Create the following pages:
- Home (
/) - About (
/about) - Blog listing (
/blog) - Individual blog post (
/blog/[slug]) - User profile (
/users/[username]) - API endpoint to get user data (
/api/users/[id])
- Home (
- Implement navigation between pages using
next/link - Create a custom 404 page
- Test all routes in the development server
- Try accessing non-existent routes to see the 404 page
- Create a catch-all route for undefined paths
Mini Project
Section titled “Mini Project”Build a simple e-commerce browsing experience:
- Create a product catalog with:
- Homepage (
/) featuring featured products - Product listing (
/products) with filtering capabilities - Individual product page (
/products/[id]) - Category pages (
/products/category/[slug]) - Search results page (
/search) - can use query parameters
- Homepage (
- Implement a shopping cart (client-side only for this exercise)
- Create API routes for:
- Getting product list (
/api/products) - Getting single product (
/api/products/[id]) - Creating an order (
/api/orders- POST)
- Getting product list (
- Add authentication routes:
- Login (
/api/auth/login) - Logout (
/api/auth/logout) - Profile (
/api/profile)
- Login (
- Create user profile pages:
- Profile view (
/profile) - Profile edit (
/profile/edit)
- Profile view (
- Implement proper error handling and loading states
- Add meta tags for SEO on important pages
- Test navigation and ensure all routes work correctly
Summary
Section titled “Summary”In this topic, you learned how Next.js uses file-system routing to automatically map files in the pages directory to application routes. You understand how to create static, dynamic, catch-all, and API routes, and how to leverage this system for intuitive and maintainable route management.
Cheat Sheet
Section titled “Cheat Sheet”# Static Routespages/index.js → /pages/about.js → /aboutpages/blog/index.js → /blog
# Dynamic Routespages/posts/[id].js → /posts/:idpages/[slug].js → /:slugpages/[id]/comments.js → /:id/comments
# Catch-all Routespages/[...slug].js → /:slug* (one or more segments)pages/[[...slug]].js → /:slug?* (zero or more segments)
# API Routespages/api/hello.js → /api/hellopages/api/users/[id].js → /api/users/:id
# Special Filespages/_app.js # Custom Apppages/_document.js # Custom Documentpages/404.js # Custom 404pages/500.js # Custom 500
# Accessing Parameters// In getStaticProps/getServerSidePropsexport async function getStaticProps({ params }) { const id = params.id // ...}
// In page component (pages router)import { useRouter } from 'next/router'const router = useRouter()const slug = router.query.slug
// Or with useParams (app router)import { useParams } from 'next/navigation'const { slug } = useParams()Related Topics
Section titled “Related Topics”- Creating Pages and Navigation
- Data Fetching Methods (getStaticProps, getServerSideProps, getStaticPaths)
- API Routes and Middleware
- Internationalized Routing (i18n)
- Redirects and Rewrites
- Route Groups (App Router)
- Server Components (App Router)