pagegraph

Declare SEO on the route. PageGraph derives the rest.

Head tags, sitemap, robots.txt, JSON-LD and a CI gate for TanStack Start, from one declaration per route. This site is built with it.

Start the tutorialbun add pagegraph
pagegraph graph
//changelog/docs/the-graph/guides/agent-workflows/audit/ci-check/claims-gate/contextual-links/coverage-gate/markdown-twins/og-images/without-tanstack-start/quick-start/reference/check-rules/cli/configuration/entries

Frontmatter of /docs/quick-start

title: "Quick start",
related: ["/docs/guides/ci-check", "/docs/concepts/the-graph", "/docs/reference/configuration"],
description: "Add PageGraph to an existing TanStack Start app in five steps and finish by running pagegraph check against your own routes.",

Derived at build

Title
Quick start | PageGraph docs
Canonical
https://pagegraph.arya.sh/docs/quick-start
Breadcrumb
Home › Docs › Quick start
Markdown
/docs/quick-start.md
This is the graph PageGraph built for this site: 20 pages, 40 related links. Choose a page to see what it declares and what the build derives. The same graph writes sitemap.xml and robots.txt.

One object on the route. Every output reads it.

staticData.seo holds the crawl policy and the head together. The rendered head, the graph and the checks read the same object, so the page and the sitemap cannot disagree.

src/routes/(docs)/docs/quick-start.tsx
export const Route = createFileRoute("/(docs)/docs/quick-start")({
  staticData: {
    seo: {
      kind: "page",
      crumb: "Quick start",
      sitemap: { priority: 0.9, changeFrequency: "monthly" },
      related: ["/docs/guides/ci-check", "/docs/reference/cli"],
      modifiedAt: "2026-11-13",
      head: {
        title: "Quick start",
        description: "Add route-declared SEO to a TanStack Start app.",
      },
    },
    markdown: "rendered",
  },
  head: seo.head,
});
  1. A breadcrumb

    crumb becomes a BreadcrumbList: Home › Docs › Quick start.

  2. A sitemap entry

    sitemap and modifiedAt become the page's <url> with its <lastmod>.

  3. Typed links

    A renamed related target is a type error. A target with no link card fails the check.

  4. The head

    seo.head renders the title, description, canonical, Open Graph tags and JSON-LD.

  5. A Markdown twin for agents

    The page is captured as /docs/quick-start.md and listed in /llms.txt.

Drift fails the build, not the crawl.

pagegraph check reads the same graph through pagegraph.config.ts. Broken declarations exit 1 in CI, before a crawler finds them.

Terminal
$ pagegraph check
Structural (2):

  ✗ [dead-edge]  /blog/launch
      related edge from "/blog/launch" points at "/pricing",
      which is not a node in the graph.
  ✗ [robots-blocks-sitemap-url]  /solutions
      Disallow: /s blocks a sitemap page.

2 structural, 0 editorial

$ pagegraph check
✓ No violations. The SEO graph is clean.
  • Structural exit 1Dead or duplicate edges, path collisions, a redirect or a noindex page in the sitemap, a published URL that robots.txt blocks.
  • Editorial reportedDuplicate titles and descriptions, descriptions too long for results, and pages older than your freshness policy.
  • RenderedWith --site, it fetches every declared page and checks the HTML a crawler receives: one H1, the canonical, robots meta, visible FAQ answers and prices.
Where a broken declaration surfaces: typed paths at type check, the Vite build's evaluation, coverage and claims gates, pagegraph check's structural and editorial rules, and pagegraph links verify on the served site.
Where a broken declaration surfaces, from type check to the served site.

Rename one route. Every copy has to follow.

A silent, 60-second film of the problem and the fix, drawn from the repository's test fixture.

No sound. Read the transcript.

Each entry runs in one place.

Runtime entries have no dependencies beyond their listed peers. Build entries resolve to a stub under workerd, so a Worker bundle that reaches one fails at import instead of on its first request.

EntryRuns inFor
Runtime
pagegraphWorker, SSR, browserBuild the graph, render sitemap and robots, run checks
pagegraph/reactWorker, SSR, browserseo.head, breadcrumbs, JSON-LD
pagegraph/tanstack-start/serverStart server routesrobotsTxt, sitemapXml, llmsTxt
Build
pagegraph/tanstack-startvite.config.tsThe Vite plugin that builds the graph
pagegraph/configpagegraph.config.tsCLI policy and the graph loader
pagegraphCLI, on Buncheck, graph, audit, links verify

See all 13 entries

Five steps to a checked graph.

The tutorial adds PageGraph to an existing TanStack Start app.

  1. Bind your siteOrigin, name and organization, once. Route files never see them.lib/seo.ts
  2. Declare each pageCrawl policy and head together, on the route.staticData.seo
  3. Add the pluginIt builds the graph inside your Vite pipeline.vite.config.ts
  4. Serve robots and sitemapOne line each, as server routes.robots[.]txt.ts
  5. Gate CIThe CLI reads the same graph.pagegraph check

Start the tutorial

Read this site's own output.

Each file comes from the declarations in site/src/routes. CI runs pagegraph check on every push.