Skip to content
Book a call

3 min readSEO

JSON-LD schema markup for a Next.js site, step by step

Add JSON-LD structured data to a Next.js App Router site: which schema types matter, a small component that renders it safely, and how to test it.

In a Next.js App Router site, add JSON-LD by rendering a <script type="application/ld+json"> tag from a server component, with the data built from the same content the page shows. Escape < in the JSON so a stray </script> can't break out, keep the IDs stable so pages refer to each other, and test each page type in Google's Rich Results Test. Search engines and AI assistants both read it to understand who you are and what a page is about.

Which schema types are worth adding

  • Organization or Person, onceYour name, logo, URL and sameAs links to your LinkedIn, GitHub and marketplace profiles. This is how engines join your profiles to your site.
  • WebSiteThe site's name and URL. Reference the Organization as its publisher.
  • BreadcrumbListOn every page below the home page. Google shows it in place of the raw URL.
  • Article or BlogPostingOn posts: headline, dates, author and image.
  • Service or ProductOn service and product pages: what it is, who provides it, where.
  • FAQPageGoogle now shows FAQ rich results only for a few authoritative sites, but the questions still help engines and AI tools understand the page. Only mark up questions that are visible on the page.

A small component that renders it safely

This is the helper this site uses. It takes one or more things and puts them in a single @graph:

type Thing = Record<string, unknown>;

export function JsonLd({ data }: { data: Thing | Thing[] }) {
  const graph = Array.isArray(data) ? data : [data];
  const json = JSON.stringify({ "@context": "https://schema.org", "@graph": graph })
    .replace(/</g, "\\u003c");
  return <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: json }} />;
}

Use it in any page or layout. Because it's a server component, the markup is in the HTML Google and AI crawlers fetch, with no JavaScript needed:

const site = "https://example.com";
const org = { "@type": "Organization", "@id": `${site}/#org`, name: "Example", url: site,
  sameAs: ["https://www.linkedin.com/company/example", "https://github.com/example"] };

export default function Page() {
  return (
    <>
      <JsonLd data={[org, {
        "@type": "BreadcrumbList",
        itemListElement: [
          { "@type": "ListItem", position: 1, name: "Home", item: site },
          { "@type": "ListItem", position: 2, name: "Services", item: `${site}/services` },
        ],
      }]} />
      {/* the page */}
    </>
  );
}

Rules that keep it trustworthy

  • Build it from the same data as the visible page, so the two never disagree.
  • Give the Organization, WebSite and Person an @id and point to it from other pages instead of repeating them.
  • Don't mark up reviews, ratings or prices you don't show. Google treats that as spam.
  • Use full URLs, and dates in ISO format (2026-10-27).

How to test it

  1. Rich Results TestGoogle's tool shows which rich results a page qualifies for and any errors.
  2. Schema Markup Validatorvalidator.schema.org checks every type, including ones Google doesn't use for rich results.
  3. Search ConsoleThe Enhancements reports (Breadcrumbs, Articles and others) show problems across the whole site after Google crawls it.
Structured data is one part of my AI search and SEO audit, with server rendering, llms.txt and page speed. See AI search and SEO.

Questions people ask

Does JSON-LD help SEO?
It doesn't raise rankings on its own, but it makes pages eligible for rich results like breadcrumbs and helps search engines and AI assistants understand what a page and its author are.
Where should JSON-LD go in a Next.js App Router project?
Render it from the page or layout server component with a script tag of type application/ld+json. Site-wide types like Organization can sit in the root layout; page types belong in each page.
Should I use next/script for JSON-LD?
No need. A plain script tag rendered on the server is simpler and puts the data straight into the HTML.
Is FAQ schema still worth adding?
Google shows FAQ rich results only for some authoritative sites now. The markup can still help engines understand the page, as long as the questions are visible on it.

Reply within a day

Got an app, or an idea?

Send me the link, or a few lines about what you want to build. I'll reply within a day with honest next steps, even if I'm not the right fit.

Free 30-minute call · No commitment · Reply within a day

Pick a time on my Cal.com page. Calls are on Google Meet. Or email me.

  1. Step 1

    You send a link or an idea

    A few lines is enough.

  2. Step 2

    I reply within a day

    With questions or a first take.

  3. Step 3

    A free 30-minute call

    Then a written quote.