📖 Scenario: You are building a Next.js app that needs to handle API requests for multiple dynamic paths under one route.For example, you want to catch requests like /api/products/123, /api/products/123/reviews, or /api/products/123/reviews/456 with a single API route file.
🎯 Goal: Build a catch-all API route in Next.js that captures all sub-paths under /api/products and returns the path segments as JSON.
📋 What You'll Learn
Create a catch-all API route file named [...slug].ts inside app/api/products/
Extract the path segments from the request parameters
Return a JSON response with the captured path segments
Use Next.js 14+ App Router conventions with a GET handler
💡 Why This Matters
🌍 Real World
Catch-all API routes let you handle many dynamic URL paths with one file, useful for building flexible APIs in Next.js apps.
💼 Career
Understanding catch-all routes is important for Next.js developers building scalable backend APIs that respond to various dynamic paths.
Progress0 / 4 steps
1
Create the catch-all API route file
Create a file named [...slug].ts inside the app/api/products/ folder. Inside it, export an async function called GET that accepts a single parameter request and returns a JSON response with an empty array for slug.
NextJS
Hint
Start by creating the API route file and export a GET function that returns { slug: [] } as JSON.
2
Extract the catch-all route parameter
Inside the GET function, extract the slug parameter from the request URL using new URL(request.url).pathname. Then split the pathname by '/' and remove the first 4 segments to isolate the slug parts. Store the result in a variable called slug.
NextJS
Hint
Use new URL(request.url).pathname to get the path, then split by '/' and slice from index 4 to get the slug array.
3
Handle the case when no slug is provided
Add a check to see if the slug array is empty. If it is empty, return a JSON response with { message: 'No slug provided' }. Otherwise, return the slug array as before.
NextJS
Hint
Check if slug.length === 0 and return a message JSON if true.
4
Complete the catch-all API route with proper export
Ensure the file exports the GET function as default export is not used. The file should be named [...slug].ts inside app/api/products/ and the GET function should handle the request as implemented.
NextJS
Hint
Make sure the GET function is exported correctly and the file is named [...slug].ts.
Practice
(1/5)
1. What does a catch-all API route file named [...slug].js in Next.js do?
easy
A. It catches all URL paths that match and provides the parts as an array in req.query.slug.
B. It only catches the root API path and ignores nested paths.
C. It catches only one specific URL path exactly matching slug.
D. It disables all API routes in the folder.
Solution
Step 1: Understand catch-all route naming
In Next.js, files named with [...name].js catch all nested paths under that route.
Step 2: Check how parameters are passed
The parts of the URL matched are passed as an array in req.query.name, here slug.
Final Answer:
It catches all URL paths that match and provides the parts as an array in req.query.slug. -> Option A
Quick Check:
Catch-all route = array in req.query [OK]
Hint: Catch-all uses [...name].js and returns array in req.query[name] [OK]
Common Mistakes:
Thinking it catches only one path instead of many
Expecting a string instead of an array in req.query
Confusing catch-all with optional catch-all routes
2. Which of the following is the correct filename for a catch-all API route in Next.js?
easy
A. [slug].js
B. [...slug].js
C. slug.js
D. [slug...].js
Solution
Step 1: Recall catch-all route syntax
Catch-all routes use three dots inside square brackets before the name, like [...slug].js.
Step 2: Compare options
Only [...slug].js matches the correct syntax for catch-all routes.
Final Answer:
[...slug].js -> Option B
Quick Check:
Catch-all filename = [...name].js [OK]
Hint: Catch-all filenames always have three dots inside brackets [OK]
Common Mistakes:
Using single brackets without dots for catch-all
Placing dots outside brackets
Missing brackets entirely
3. Given a catch-all API route file pages/api/[...params].js with this handler:
export default function handler(req, res) {
res.json(req.query.params);
}
What will be the JSON response for a request to /api/a/b/c?
medium
A. "a/b/c"
B. {"params": "a/b/c"}
C. ["a", "b", "c"]
D. null
Solution
Step 1: Understand catch-all parameter passing
The catch-all [...params] captures all path parts as an array in req.query.params.
Step 2: Check the handler response
The handler returns req.query.params as JSON, so the response is the array of parts.
Final Answer:
["a", "b", "c"] -> Option C
Quick Check:
Catch-all returns array of path parts [OK]
Hint: Catch-all returns array of URL parts in req.query [OK]
Common Mistakes:
Expecting a string instead of an array
Confusing JSON structure returned
Not recognizing catch-all returns array
4. You wrote a catch-all API route pages/api/[...slug].js but when you request /api (no extra path), you get an error. What is the likely cause?
medium
A. You forgot to export the handler function.
B. The file name is incorrect; it should be [slug].js.
C. API routes cannot have dynamic segments.
D. Catch-all routes require at least one path segment; use optional catch-all [[...slug]].js instead.
Solution
Step 1: Understand catch-all vs optional catch-all
Catch-all [...slug].js requires at least one path part; it does not match the base path alone.
Step 2: Identify fix for base path requests
To handle base path /api with no extra parts, use optional catch-all [[...slug]].js.
Final Answer:
Catch-all routes require at least one path segment; use optional catch-all [[...slug]].js instead. -> Option D
Hint: Use [[...name]].js for optional catch-all including empty path [OK]
Common Mistakes:
Expecting catch-all to match empty path
Misnaming the file without brackets
Ignoring export of handler function
5. You want to create a catch-all API route that returns a JSON object with keys for each path part and their index, for example, for /api/a/b/c it returns {"0": "a", "1": "b", "2": "c"}. Which handler code inside pages/api/[...parts].js achieves this?
B. export default function handler(req, res) {
res.json(req.query.parts.join(','));
}
C. export default function handler(req, res) {
res.json({ parts: req.query.parts });
}
D. export default function handler(req, res) {
res.json(req.query.parts.length);
}
Solution
Step 1: Understand the input and desired output
The catch-all parameter parts is an array of path parts. We want to create an object with keys as indices and values as parts.
Step 2: Check which code builds the object correctly
export default function handler(req, res) {
const obj = {};
req.query.parts.forEach((p, i) => { obj[i] = p; });
res.json(obj);
} loops over req.query.parts and assigns each part to the object with its index as key, then returns it as JSON.