---
id: 12646
title: Add PR and Discussion routes to generated SEO outputs
state: CLOSED
labels:
  - enhancement
  - ai
  - build
assignees:
  - neo-gpt
createdAt: '2026-06-06T17:17:46Z'
updatedAt: '2026-06-06T17:53:37Z'
githubUrl: 'https://github.com/neomjs/neo/issues/12646'
author: neo-gpt
commentsCount: 0
parentIssue: null
subIssues: []
subIssuesCompleted: 0
subIssuesTotal: 0
blockedBy: []
blocking: []
closedAt: '2026-06-06T17:53:37Z'
---
# Add PR and Discussion routes to generated SEO outputs

## Context

Issue #10056 originally asked the Portal News section to surface Pull Requests and Discussions in the app and in generated SEO outputs. Current `dev` reality has moved on: Epic #12204 superseded #10056 in planning and is now closed complete with 19/19 sub-issues complete, and #12210 closed the PR/Discussion index-generator prerequisite.

The stale broad ticket should not be re-used as an implementation lane, because most of its body is already delivered. The remaining observed gap is narrower and machine-facing: `buildScripts/docs/seo/generate.mjs` still does not enumerate PR or Discussion content routes for sitemap / `llms.txt` generation.

## The Problem

V-B-A on current source shows the Portal app has the PR/Discussion view/data surfaces, but the SEO generator still only treats issues and release notes as GitHub News content:

- `apps/portal/view/news/TabContainer.mjs` includes `/news/pulls` and `/news/discussions` tabs.
- `apps/portal/view/news/pulls/` and `apps/portal/view/news/discussions/` exist with route controllers and lazy tree consumers.
- `buildScripts/docs/index/pulls.mjs` and `buildScripts/docs/index/discussions.mjs` exist and emit chunked JSON data under `apps/portal/resources/data/{pulls,discussions}/`.
- `buildScripts/docs/seo/generate.mjs` currently has `collectReleaseRoutes()` and `collectIssueRoutes()`, but no PR or Discussion route collectors.
- `collectAllRoutes()` currently includes top-level, learn-tree content, examples, releases, and issues only.
- `getLlmsTxt()` currently groups `release-notes`, `tickets`, examples, top-level pages, and learn-tree content; it does not include GitHub Pull Requests or GitHub Discussions sections.

Reproducer evidence:

```bash
node buildScripts/docs/seo/generate.mjs --format urls --base-url https://neomjs.com | rg "/news/(pulls|discussions)"
# no output

node buildScripts/docs/seo/generate.mjs --format llms --base-url https://neomjs.com | rg "Pull Requests|Discussions|GitHub Tickets|news/pulls|news/discussions"
# only the GitHub Tickets section is present
```

## The Architectural Reality

The owning substrate is `buildScripts/docs/seo/generate.mjs`, not generated files such as `apps/portal/llms.txt` or `apps/portal/sitemap.xml`. This matches the generated-output rule already used by #12225 / #12253 / #12259.

The source content already exists in synced markdown:

- Active PR files: `resources/content/pulls/**/pr-*.md`
- Archived PR files: `resources/content/archive/pulls/**/pr-*.md`
- Active Discussion files: `resources/content/discussions/**/discussion-*.md`
- Archived Discussion files: `resources/content/archive/discussions/**/discussion-*.md`

The route shape should mirror the shipped Portal routes:

- PR route id: `/news/pulls/<number>`
- Discussion route id: `/news/discussions/<number>`

## The Fix

Add PR and Discussion route support to the SEO generator:

1. Add `collectPullRoutes()` scanning active and archived `pr-*.md` files and producing `{category: 'pull-requests', filePath, id: '/news/pulls/<number>', pullNum}` records sorted newest/highest number first.
2. Add `collectDiscussionRoutes()` scanning active and archived `discussion-*.md` files and producing `{category: 'discussions', filePath, id: '/news/discussions/<number>', discussionNum}` records sorted newest/highest number first.
3. Wire both collectors into `collectAllRoutes()` so `getSitemapXml()`, URL output, object output, and `llms.txt` consume the same route set.
4. Extend `getPriority()` for `/news/pulls/` and `/news/discussions/` per #10056's original SEO intent, with current priority values verified in the PR body.
5. Extend `getLlmsTxt()` with explicit GitHub Pull Requests and GitHub Discussions sections that map to raw markdown URLs, mirroring the GitHub Tickets section.
6. Regenerate generated SEO outputs only if the established release/build workflow for this repo expects generated files to be committed for this surface; otherwise document why the generator-only change is sufficient.

## Contract Ledger Matrix

| Target Surface | Source of Authority | Proposed Behavior | Fallback | Docs | Evidence |
|---|---|---|---|---|---|
| `buildScripts/docs/seo/generate.mjs` route collection | #10056 residual + current Portal route controllers | Include PR and Discussion markdown as `/news/pulls/<number>` and `/news/discussions/<number>` routes | Current generator omits them from sitemap / URL output | JSDoc on the new collectors | `--format urls` emits PR/Discussion routes |
| `getLlmsTxt()` machine-reader output | #10056 SEO/LLM value + existing `GitHub Tickets` section | Include Pull Requests and Discussions sections with raw markdown URLs | Current output lists tickets only | Generator source, not hand-edited output | `--format llms` contains the new sections |
| Sitemap priority | #10056 priority intent + current `getPriority()` route classifier | Assign specific priorities for `/news/pulls/*` and `/news/discussions/*` | Fall back to `DEFAULT_PRIORITY` | `getPriority()` comments / PR body | `--format xml` spot-check or unit/assertion evidence |

## Decision Record Impact

None. This is aligned with the existing generated-SEO-source discipline from #12225 / #12253 / #12259 and with #12204's Portal News route architecture.

## Acceptance Criteria

- [ ] `node buildScripts/docs/seo/generate.mjs --format urls --base-url https://neomjs.com | rg "/news/pulls/"` returns PR routes.
- [ ] `node buildScripts/docs/seo/generate.mjs --format urls --base-url https://neomjs.com | rg "/news/discussions/"` returns Discussion routes.
- [ ] `node buildScripts/docs/seo/generate.mjs --format llms --base-url https://neomjs.com` contains explicit GitHub Pull Requests and GitHub Discussions sections.
- [ ] `getPriority()` classifies `/news/pulls/*` and `/news/discussions/*` explicitly rather than relying on `DEFAULT_PRIORITY`.
- [ ] The PR documents whether generated `apps/portal/llms.txt` / sitemap output is committed or intentionally left to the release pipeline.

## Out of Scope

- Rebuilding the Portal PR/Discussion UI. That work was delivered under #12204 and follow-up tickets.
- Changing the synced markdown grammar for PRs or Discussions.
- Reworking the chunked Portal data index generators.
- Editing generated SEO files by hand.
- General SEO identity-copy changes unrelated to PR/Discussion route discovery.

## Avoided Traps

- Reusing #10056 as-is. It now bundles mostly delivered work and would mislead future agents into rebuilding closed #12204 scope.
- Hand-editing `apps/portal/llms.txt` or sitemap output. The generator owns the durable behavior.
- Adding a new Portal app tab or data generator. Those exist already.

## Duplicate Sweep

- Live latest-open sweep: checked latest 20 open GitHub issues on 2026-06-06 via `gh issue list --state open --limit 20 --json number,title,author,labels,url`; no equivalent PR/Discussion SEO route ticket found.
- Knowledge Base semantic sweep attempted with `ask_knowledge_base("Portal News Pull Requests Discussions issue 10056 current implementation")`, but the KB collection is currently unavailable (`collection not found`). KB silence was not treated as evidence.
- Local exact sweep across `resources/content/issues`, `resources/content/archive/issues`, `resources/content/pulls`, and `resources/content/discussions` found the successor chain #12204, #12210, #12219, #12300 and adjacent SEO work #12225 / #12253 / #12255 / #12259, but no open equivalent for adding PR/Discussion route collectors to `generate.mjs`.
- GitHub Search API endpoint returned 404 through this shell path; live issue-list + local synced corpus were used as the reliable duplicate sweep.

## Related

- Supersedes the residual SEO portion of #10056.
- #12204 closed complete — Portal news PR/Discussion views + chunked lazy-load tree.
- #12210 closed — PR/Discussion index generators.
- #12225 / #12253 / #12255 / #12259 — adjacent generated SEO source discipline.

Origin Session ID: 019e98ad-5af5-7981-be15-dfc740a81d46

Handoff Retrieval Hint: "#10056 portal news PR Discussion generated SEO routes collectPullRoutes collectDiscussionRoutes llms sitemap"

## Timeline

- 2026-06-06T17:17:47Z @neo-gpt assigned to @neo-gpt
- 2026-06-06T17:17:47Z @neo-gpt added the `enhancement` label
- 2026-06-06T17:17:47Z @neo-gpt added the `ai` label
- 2026-06-06T17:17:48Z @neo-gpt added the `build` label
- 2026-06-06T17:18:08Z @neo-gpt cross-referenced by #10056
- 2026-06-06T17:29:00Z @neo-gpt cross-referenced by PR #12647
- 2026-06-06T17:53:37Z @tobiu referenced in commit `0e12ce6` - "feat(seo): add PR and Discussion news routes (#12646) (#12647)"
- 2026-06-06T17:53:37Z @tobiu closed this issue

