Skip to content

Improve SEO: rich bill metadata, sitemap, robots, JSON-LD - #74

Open
mikaalnaik wants to merge 2 commits into
mainfrom
mikaal/seo
Open

Improve SEO: rich bill metadata, sitemap, robots, JSON-LD#74
mikaalnaik wants to merge 2 commits into
mainfrom
mikaal/seo

Conversation

@mikaalnaik

Copy link
Copy Markdown
Collaborator

Context

The bills app had solid baseline metadata (per-page OG/Twitter tags, dynamic OG images) but several gaps limited search visibility: bill pages had generic titles/descriptions, there was no sitemap, and the static robots.txt pointed at the wrong app's sitemap. This PR is a full SEO pass.

Changes

Content metadata

  • Bill pages now use descriptive titles (C-11: Military Justice System Modernization Act · Builder MP) and meta descriptions derived from the real AI summary (markdown-stripped, truncated to ~155 chars), plus keywords from genres.
  • Not-found bills return robots: noindex,nofollow.
  • Memoized the bill resolver with React cache() (src/server/get-unified-bill.ts) so generateMetadata and the page component share a single fetch.

Discoverability

  • New dynamic src/app/sitemap.ts lists home + every bill with lastModified, using absolute canonical URLs. Wrapped in try/catch so a data outage can't 500 it.
  • Replaced static robots.txt (which referenced the wrong app's sitemap) with src/app/robots.ts pointing at the app's own sitemap and disallowing non-public routes.
  • Extracted shared bill-merge logic into src/server/get-merged-bills.ts (used by home + sitemap).

Structured data

  • New src/components/JsonLd.tsx helper. Bill pages emit schema.org Legislation + BreadcrumbList; home emits WebSite.

Hygiene

  • Added src/utils/seo.ts (getCanonicalOrigin, stripMarkdown, truncate) for a single deterministic canonical origin (https://www.buildcanada.com); set metadataBase fallback.
  • Removed redundant hand-rolled twitter:* meta tags across layout/home/bill pages.

Verification

  • tsc --noEmit clean; biome check clean; unit tests pass (pre-commit hook).
  • Ran the dev server and confirmed:
    • /bills/robots.txt and /bills/sitemap.xml render with canonical https://www.buildcanada.com/bills/... URLs.
    • Bill page: rich title, truncated description, keywords, correct canonical, exactly one twitter:card, 2 JSON-LD blocks.
    • Non-existent bill → <meta name="robots" content="noindex">.
    • Home page → WebSite JSON-LD.

Deployment note

Because the app runs under the /bills basePath, its robots.txt/sitemap.xml are served at /bills/.... Crawlers honor robots.txt only at the host root, so the root buildcanada.com/robots.txt should reference https://www.buildcanada.com/bills/sitemap.xml (or submit the sitemap directly in Search Console).

🤖 Generated with Claude Code

- Bill pages now use real titles ("C-11: <name>") and meta descriptions
  derived from the bill summary, plus keywords from genres; not-found bills
  return noindex
- Memoize the bill resolver (React cache) so generateMetadata and the page
  share a single fetch (src/server/get-unified-bill.ts)
- Add dynamic sitemap.ts listing home + all bills with canonical URLs
- Replace static robots.txt (wrong sitemap target) with robots.ts pointing at
  the app's own sitemap and disallowing non-public routes
- Add schema.org JSON-LD: Legislation + BreadcrumbList on bill pages,
  WebSite on home (src/components/JsonLd.tsx)
- Add src/utils/seo.ts (getCanonicalOrigin, stripMarkdown, truncate) for a
  single deterministic canonical origin; set metadataBase fallback
- Extract shared bill-merge logic to src/server/get-merged-bills.ts
- Remove redundant hand-rolled twitter:* meta tags

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mikaalnaik mikaalnaik self-assigned this Jun 30, 2026
@mikaalnaik
mikaalnaik requested a review from xrendan June 30, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant