Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
World desk5 min

How to Generate Product Pages and Sitemaps from JSON in Next.js

Learn how to use one JSON product catalog to generate Next.js App Router product pages, product metadata, and sitemap URLs.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

In the Next.js App Router, a JSON product catalog can drive dynamic product pages, product-specific metadata, and sitemap entries from one shared data source. Define a route such as app/products/[slug]/page.tsx, map catalog records to route parameters with generateStaticParams, and use those same records in generateMetadata and app/sitemap.ts. This guide covers the App Router; the Pages Router uses different conventions.

1. Keep the catalog available to every part of the route

Use one canonical source for product records so route generation, page rendering, metadata, and sitemap URLs agree. For a small catalog built with the site, that may be a local JSON module; for data that changes independently of deployments, it may be a fetched source. Next.js documents the framework mechanisms, but does not prescribe a JSON schema, file layout, slug policy, or validation library.

As an Amazon Associate I earn from qualifying purchases.

For illustration, assume each product has a unique, stable slug, a name, a description, and optionally a trustworthy updatedAt value. Validate the actual data according to the needs of your project; these fields are an example, not a required Next.js schema.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Create a dynamic product route

A bracketed directory creates a dynamic route segment. In app/products/[slug]/page.tsx, the segment name [slug] determines the route parameter key. A product with slug trail-pack is served at /products/trail-pack.

The following example assumes a shared getProducts() helper that returns the canonical catalog, whether that helper reads local JSON or fetches data:

import { notFound } from 'next/navigation'
import { getProducts } from '@/lib/products'

export async function generateStaticParams() {
  const products = await getProducts()
  return products.map((product) => ({ slug: product.slug }))
}

export default async function ProductPage({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const { slug } = await params
  const products = await getProducts()
  const product = products.find((item) => item.slug === slug)

  if (!product) notFound()

  return (
    <main>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
    </main>
  )
}

Current App Router documentation types params as a promise in page examples. Match the type and access pattern supported by the Next.js version installed in your project; older versions may use different conventions. The notFound() check handles a request for a slug that has no catalog record rather than assuming every requested URL is valid.

Nested route segments

For a route such as app/products/[category]/[product]/page.tsx, each object returned by generateStaticParams must provide both keys, for example { category: product.categorySlug, product: product.slug }. Parameter names must match the bracketed directory names. See the Next.js generateStaticParams reference.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Choose which product routes to prerender

generateStaticParams returns the dynamic route parameters Next.js should statically generate during the build. The official description says: “The generateStaticParams function can be used in combination with dynamic route segments to statically generate routes at build time instead of on-demand at request time.”

You can return every known slug or only a subset. Next.js does not specify a universal catalog-size threshold for choosing between these approaches; consider your build needs and how the remaining routes should behave.

Approach What happens at build time Decision to make
Return all product slugs All returned product routes are generated at build time. Whether the catalog and build workflow make generating every known page appropriate.
Return a subset Only the returned product routes are generated at build time. Whether routes omitted from the list should be served on demand or treated as unavailable.

The route segment option dynamicParams controls the behavior for paths not returned by generateStaticParams. Check the current reference and your route configuration to choose the behavior you intend.

Builds, development, and revalidation

During a build, generateStaticParams runs before the corresponding layouts and pages are generated. In development, it runs as routes are navigated. The function is not called again during ISR, so do not rely on ISR alone to refresh its generated parameter list; configure the route and data-refresh approach for your update requirements. The details depend on your Next.js version and route configuration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Cache Components considerations

Next.js documentation describes a Cache Components-specific constraint: dynamic routes require at least one parameter from generateStaticParams, and returning an empty array causes a build error. This behavior depends on the version and mode in use, so verify it against the documentation for your installed version.

4. Generate product-specific metadata

Export generateMetadata from the product page when a title or description depends on the requested product. Resolve the same canonical record by slug and return a Metadata object. If metadata is identical across products and does not depend on route or request information, use the static metadata export instead.

import type { Metadata } from 'next'
import { getProducts } from '@/lib/products'

type Props = {
  params: Promise<{ slug: string }>
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { slug } = await params
  const products = await getProducts()
  const product = products.find((item) => item.slug === slug)

  if (!product) {
    return { title: 'Product not found' }
  }

  return {
    title: product.name,
    description: product.description,
  }
}

Adapt the missing-record metadata behavior to the rest of your route handling. When data is fetched with matching fetch requests, Next.js memoizes those requests across generateMetadata, generateStaticParams, layouts, pages, and Server Components. For a non-fetch source such as a local JSON helper, consider sharing a data-access helper or using React cache as described in the Next.js metadata documentation.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

5. Build the sitemap from the same canonical slugs

Create app/sitemap.ts and return absolute product URLs using the same slugs as the route. Configure the site’s absolute base URL for your deployment rather than constructing inconsistent product paths in multiple places.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import type { MetadataRoute } from 'next'
import { getProducts } from '@/lib/products'

const siteUrl = process.env.SITE_URL!

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const products = await getProducts()

  return products.map((product) => ({
    url: new URL(`/products/${product.slug}`, siteUrl).toString(),
    ...(product.updatedAt
      ? { lastModified: new Date(product.updatedAt) }
      : {}),
  }))
}

Set SITE_URL to the site’s actual absolute origin in the deployment environment. Include lastModified only if the catalog has a reliable modification date; omitting it is better than inventing one. Next.js’s sitemap convention uses a default-exported function that returns a URL array.

Using the same catalog and canonical URL rules for pages and sitemap entries helps prevent links to nonexistent routes or omitted products. The sitemap should reflect the URLs your application actually intends to serve.

6. Split a large sitemap into multiple files

Next.js documentation states a limit of 50,000 URLs per sitemap. For a catalog too large for one sitemap, you can use sitemap files nested under route segments or use generateSitemaps to create separate groups. The generateSitemaps reference demonstrates dividing product records into batches.

Partition records deterministically: each product should appear once, with no gaps at batch boundaries. The documentation’s numeric example uses an inclusive lower bound and an exclusive upper bound; if your catalog IDs are not sequential, partition the actual records or query results rather than assuming they are.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

7. Keep JSON, routes, metadata, and sitemap consistent

  • Use matching parameter keys: return slug for [slug], and provide every key for nested dynamic segments.
  • Use one canonical record lookup: page content and metadata should resolve products from the same source and slug rules.
  • Handle missing products: a URL request may not match a current catalog entry; decide the page and metadata behavior deliberately.
  • Choose the generated route set: returning a subset requires a decision about unlisted routes and the dynamicParams setting.
  • Match sitemap URLs to route URLs: use the same base URL and slug construction, and only emit modification dates supported by the data.
  • Recheck version-sensitive behavior: App Router parameter typing, Cache Components constraints, and route behavior should match the installed Next.js version.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.