# Add a Sitemap to a Gatsby Blog

Yes. An agent adds gatsby-plugin-sitemap to your Gatsby 5 blog, points robots.txt at the index it generates, builds the site to check it and opens a pull request.

[Run this on Rush](https://cloud.getrush.ai/run/add-sitemap/gatsby/), in a Project that has your repository.

## What the agent does

The agent clones the site into its own cloud sandbox and reads `gatsby-config.js` before it adds anything. In a blog like gatsbyjs/gatsby-starter-blog, `siteMetadata.siteUrl` is already set, which `gatsby-plugin-sitemap` needs for absolute URLs, and the plugin list holds `gatsby-plugin-feed` for `/rss.xml`, `gatsby-plugin-manifest`, `gatsby-plugin-image`, `gatsby-plugin-sharp`, `gatsby-transformer-sharp`, `gatsby-source-filesystem` for `content/blog` and `src/images`, and `gatsby-transformer-remark` with its image, iframe and Prism plugins. There is no sitemap plugin. `static/robots.txt` is two lines, `User-agent: *` and `Disallow:`, with no `Sitemap:` directive, and `src/components/seo.js` writes the title, description, Open Graph and Twitter tags but no canonical link.

Then it reads how pages come to exist, because a sitemap is only as good as the page list behind it. `gatsby-node.js` queries `allMarkdownRemark` sorted by date and creates one page per post at `fields.slug`, which `onCreateNode` sets from `createFilePath`, using `src/templates/blog-post.js`. The other pages are files under `src/pages`: `index.js`, `404.js` and `using-typescript.tsx`. The agent installs `gatsby-plugin-sitemap` at the major that matches `gatsby` `^5.14.6` with npm, since the repository has a `package-lock.json`, and adds it to the plugin list with the default `output`, so the build writes `/sitemap-index.xml` and the numbered sitemap files it refers to.

It then decides what the sitemap should leave out. The plugin excludes Gatsby's own 404 and dev pages by default; the agent checks the generated files for `using-typescript`, which is a starter demo page rather than content, and asks in the pull request whether to add it to `excludes` rather than deciding alone. It changes `static/robots.txt` to add a `Sitemap:` line built from the same `siteUrl`, keeping the permissive `Disallow:` as it is, and leaves `seo.js` alone, since a canonical tag is a separate change with its own trade-offs for a site that may be served from more than one host.

Finally it runs `npm run build` in the sandbox, reads `public/sitemap-index.xml` and the sitemap it names, and checks that every post slug from `content/blog` appears exactly once with the `siteUrl` prefix and that `/404/` does not. `package.json` has `format` set to `prettier --write` with `.prettierrc` asking for no semicolons and `arrowParens: avoid`, so the agent formats the config change the way the rest of the repository is written. The repository's `test` script only prints a reminder and exits 1, so the build and the generated files are the check.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Add a sitemap to this Gatsby 5 blog. Read gatsby-config.js (siteMetadata.siteUrl and the plugin list), gatsby-node.js (how post pages are created from allMarkdownRemark and fields.slug), src/pages, static/robots.txt and package.json. Install gatsby-plugin-sitemap at the major matching the gatsby version with npm, add it to the plugins with the default output, and add a Sitemap: line to static/robots.txt using siteUrl. Do not add a canonical tag to src/components/seo.js. Run npm run build, then read public/sitemap-index.xml and the sitemap it points to and confirm every post slug under content/blog appears once with the siteUrl prefix and the 404 page does not. Run npm run format on the files you changed. Open a pull request that quotes the generated sitemap entries and asks whether the using-typescript demo page should be excluded.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is a pull request with four changed files: `package.json` and `package-lock.json` with the new dependency, `gatsby-config.js` with the plugin entry, and `static/robots.txt` with its `Sitemap:` line. The description quotes the `<loc>` entries the sandbox build produced, so a reviewer sees the post URLs without building the site, and ends with the one open question about the demo page.

A reviewer checks three things: that `siteUrl` in `gatsby-config.js` is the production host and not the starter's placeholder, since the sitemap and the robots line both derive from it; that the plugin version matches the Gatsby major; and that the entries quoted in the description are the pages they expect. If the site is deployed with a trailing-slash rule, the reviewer compares a sitemap URL with a real page URL once.

The session keeps the `npm install` and `npm run build` output and the files the agent read under `public/`, so a sitemap that later lists a page it should not can be traced to the build that first produced it. A follow-up on the same session can add `excludes` or a per-page `changefreq` without starting over.

## Run it on every Linear issue labelled agent

In the console, add an automation to the Project with this prompt and a `linear` trigger on `linear.issue.labeled`, filtered to the `agent` label. When someone on the team labels an issue such as "Search Console says no sitemap", the trigger puts the issue after the prompt and starts a run in the site's repository; the pull request links back to the issue. Only label changes made by a person in your Rush org fire it, never changes made by an app integration.

The same body can be sent from a script with `POST /o/{org}/sessions`, with the issue's URL in `resources` beside the repository so the agent reads it through your Linear connection. A key's `webhook_url` reports when a run it started finishes; a run an automation starts is listed in the Project instead.

## Why run it on Rush?

A sitemap change is small and easy to get subtly wrong: the wrong plugin major for the Gatsby version, a `siteUrl` with a trailing slash that doubles up, a 404 page listed. The agent builds the site in its own sandbox and reads the generated XML before the pull request exists, so what the description quotes is what the build wrote, not what the plugin's README promises.

Running it on Rush also keeps the record. The transcript has the install, the build and the generated entries, and the reviewer gets a diff plus the evidence rather than a note saying it was tested locally. Several sites can be done at once, each in its own sandbox, and a follow-up refines the exclusions on the same run.

## Frequently asked questions

### Will it change my RSS feed or the manifest?

No. `gatsby-plugin-feed` and `gatsby-plugin-manifest` stay as they are. The only change to `gatsby-config.js` is the new plugin entry, and the agent formats it with the repository's Prettier settings so the diff is one block.

### What if siteUrl is still the starter's placeholder?

The agent uses whatever `siteMetadata.siteUrl` says and names it in the pull request, because the sitemap and the `robots.txt` line both come from it. If it is still `gatsbystarterblogsource.gatsbyjs.io` or similar, the description says so and asks for the production host; it does not guess one.

### Does it exclude the 404 page and draft posts?

The plugin excludes Gatsby's 404 and development pages by default, and the agent confirms that in the generated file. The starter has no draft flag in its frontmatter, so every post under `content/blog` is listed; a site with a `draft` field gets a `query` and `filterPages` configuration in a follow-up, named in the pull request.

### Can it add canonical links too?

Not in this run. `src/components/seo.js` has no canonical tag, and adding one touches every page's head and interacts with how the site is hosted, so the prompt rules it out. Ask for it as a separate issue, or as a follow-up on this session once the sitemap is merged.
