Skip to content

feat(seo): site-wide SEO — metadata, sitemap, robots, OG images, JSON-LD#10

Merged
0xdevcollins merged 3 commits into
mainfrom
feat/seo
Jun 12, 2026
Merged

feat(seo): site-wide SEO — metadata, sitemap, robots, OG images, JSON-LD#10
0xdevcollins merged 3 commits into
mainfrom
feat/seo

Conversation

@0xdevcollins

@0xdevcollins 0xdevcollins commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Technical SEO foundation across the site:

  • robots.ts and sitemap.ts (marketing + discover + blog posts) with the authenticated app, auth flows, API and preview routes excluded.
  • metadataBase from NEXT_PUBLIC_APP_URL so canonical/OG URLs are absolute.
  • Shared buildPageMetadata helper (title, description, canonical, Open Graph, Twitter) used by the home page, all marketing pages, blog articles, and the discovery pages.
  • Home page metadata (previously missing).
  • Organization + WebSite JSON-LD site-wide; BlogPosting JSON-LD on articles.
  • Dynamic Open Graph images via next/og: site default, per-pillar (discover), and per-article (blog).

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Open Graph image previews when sharing pages on social media
    • Added website sitemap for search engine discovery
    • Added search engine crawl rules configuration
    • Added structured data markup for enhanced search results and rich preview cards
  • Refactor

    • Improved page metadata generation with consistent canonical URL support across all pages

Technical SEO foundation across the site:

- robots.ts and sitemap.ts (marketing + discover + blog posts) with the
  authenticated app, auth flows, API and preview routes excluded.
- metadataBase from NEXT_PUBLIC_APP_URL so canonical/OG URLs are absolute.
- Shared buildPageMetadata helper (title, description, canonical, Open Graph,
  Twitter) used by the home page, all marketing pages, blog articles, and the
  discovery pages.
- Home page metadata (previously missing).
- Organization + WebSite JSON-LD site-wide; BlogPosting JSON-LD on articles.
- Dynamic Open Graph images via next/og: site default, per-pillar (discover),
  and per-article (blog).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
boundless-v2 Ready Ready Preview, Comment Jun 12, 2026 1:51am

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@0xdevcollins, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 36 minutes and 17 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a9883abc-062a-43ab-bb8c-648cb6822581

📥 Commits

Reviewing files that changed from the base of the PR and between 9437582 and 023125c.

⛔ Files ignored due to path filters (2)
  • src/lib/og-fonts/plus-jakarta-sans-400.woff is excluded by !**/*.woff
  • src/lib/og-fonts/plus-jakarta-sans-700.woff is excluded by !**/*.woff
📒 Files selected for processing (15)
  • src/app/(public)/about/opengraph-image.tsx
  • src/app/(public)/blog/opengraph-image.tsx
  • src/app/(public)/brand-kit/opengraph-image.tsx
  • src/app/(public)/careers/opengraph-image.tsx
  • src/app/(public)/faq/opengraph-image.tsx
  • src/app/(public)/page.tsx
  • src/app/apple-icon.tsx
  • src/app/icon.tsx
  • src/app/layout.tsx
  • src/app/logo.png/route.ts
  • src/app/manifest.ts
  • src/app/robots.ts
  • src/app/sitemap.ts
  • src/components/seo/json-ld.tsx
  • src/lib/og-image.tsx
📝 Walkthrough

Walkthrough

This PR establishes complete SEO infrastructure for the Boundless application by introducing shared site constants, metadata builders, OG image rendering utilities, structured data components, crawler routes, and per-page metadata exports across all discover and public pages.

Changes

SEO & Open Graph Image System

Layer / File(s) Summary
SEO foundation & OG utilities
src/lib/site.ts, src/lib/seo.ts, src/lib/og-image.tsx
SITE_URL, SITE_NAME, SITE_DESCRIPTION, and SITE_SOCIALS constants are defined; buildPageMetadata helper generates Next.js Metadata with title templating, canonical paths, and Open Graph/Twitter fields; OG_SIZE, OG_CONTENT_TYPE, and renderOgImage provide shared OG image rendering with branded layout.
Root layout metadata base & structured data
src/app/layout.tsx, src/components/seo/json-ld.tsx
Root layout sets metadataBase from NEXT_PUBLIC_APP_URL; JsonLd component builds Organization and WebSite JSON-LD schemas from site constants and is injected into the layout.
Root-level Open Graph image
src/app/opengraph-image.tsx
Exports default OG image route with branded title and subtitle text.
Robots & sitemap routes
src/app/robots.ts, src/app/sitemap.ts
robots() allows public crawling from root while disallowing dashboard/auth/API/preview paths and points to sitemap; sitemap() generates entries for static marketing pages, dynamic discover pillar pages, and blog posts with per-post lastModified dates.
Discover pages metadata & OG images
src/app/(discover)/seo.ts, src/app/(discover)/{bounties,crowdfunding,explore,grants,hackathons}/*
All discover pillar pages export metadata via discoverMetadata helper; each pillar receives its own opengraph-image.tsx route that renders OG images using pillar heading and subtext.
Public pages metadata & blog OG/structured data
src/app/(public)/{about,brand-kit,careers,faq,page}.tsx, src/app/(public)/blog/*
Public pages refactored to use buildPageMetadata with explicit path fields; blog list page and /blog/${slug} page both export metadata; blog post OG images include truncated excerpt as subtitle; blog post page injects BlogPosting JSON-LD with publication date, author, and article URL.

Sequence Diagram

sequenceDiagram
  participant Browser
  participant RootLayout
  participant BuildPageMetadata
  participant RenderOgImage
  participant JsonLd

  Browser->>RootLayout: Request page
  RootLayout->>BuildPageMetadata: Generate metadata
  BuildPageMetadata->>Browser: Return page metadata + canonicals + OG tags
  RootLayout->>JsonLd: Render schema
  JsonLd->>Browser: Inject Organization/WebSite schemas
  Browser->>RenderOgImage: Request /opengraph-image
  RenderOgImage->>Browser: Return branded OG image (1200x630)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 Whiskers twitch with SEO glee,
Metadata flows like morning tea,
OG images shine bright and wide,
With structured data by our side,
Crawlers now find every page,
Boundless blooms on the web's grand stage!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly and comprehensively summarizes the main changes: comprehensive site-wide SEO enhancements including metadata, sitemap, robots configuration, Open Graph images, and JSON-LD structured data.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/seo

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(public)/page.tsx:
- Line 19: The homepage title string currently uses an em dash; update the
user-facing title in page.tsx (the metadata/title or exported title value on the
page component) to replace the em dash with an allowed separator such as "|" or
":" (e.g., "Boundless | Hackathons, Bounties, Grants & Crowdfunding on Stellar")
so it complies with the no-em-dash copy rule.

In `@src/app/robots.ts`:
- Line 27: Replace manual string concatenation with URL resolution: in the
robots.ts sitemap property (currently using `${SITE_URL}/sitemap.xml`) and in
src/app/sitemap.ts where individual entry URLs are built, use new
URL('sitemap.xml', SITE_URL) and new URL(pathOrFilename, SITE_URL) respectively
so URLs are constructed via the URL constructor to avoid trailing-slash and
edge-case bugs; locate the sitemap property in robots.ts and the sitemap
entry-building logic in sitemap.ts and update those call sites to use new
URL(..., SITE_URL).

In `@src/app/sitemap.ts`:
- Around line 7-10: The parseDate function is using new Date(value) which is
implementation-defined for non-ISO strings; update handling so parsing is
deterministic: either require/convert post.publishedDate to an ISO format (e.g.,
YYYY-MM-DD or full ISO 8601) before calling parseDate, or change parseDate to
parse the known human format explicitly (e.g., split "DD Month YYYY" and
construct a Date using UTC components) and return fallback only on truly invalid
input; locate the parseDate function and its caller lastModified:
parseDate(post.publishedDate, now) to implement the chosen deterministic parsing
strategy and ensure consistent Date construction across environments.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8d91dca5-552c-4275-bd78-7f7e2082677f

📥 Commits

Reviewing files that changed from the base of the PR and between 70e4e72 and 9437582.

📒 Files selected for processing (27)
  • src/app/(discover)/bounties/opengraph-image.tsx
  • src/app/(discover)/bounties/page.tsx
  • src/app/(discover)/crowdfunding/opengraph-image.tsx
  • src/app/(discover)/crowdfunding/page.tsx
  • src/app/(discover)/explore/opengraph-image.tsx
  • src/app/(discover)/explore/page.tsx
  • src/app/(discover)/grants/opengraph-image.tsx
  • src/app/(discover)/grants/page.tsx
  • src/app/(discover)/hackathons/opengraph-image.tsx
  • src/app/(discover)/hackathons/page.tsx
  • src/app/(discover)/seo.ts
  • src/app/(public)/about/page.tsx
  • src/app/(public)/blog/[slug]/opengraph-image.tsx
  • src/app/(public)/blog/[slug]/page.tsx
  • src/app/(public)/blog/page.tsx
  • src/app/(public)/brand-kit/page.tsx
  • src/app/(public)/careers/page.tsx
  • src/app/(public)/faq/page.tsx
  • src/app/(public)/page.tsx
  • src/app/layout.tsx
  • src/app/opengraph-image.tsx
  • src/app/robots.ts
  • src/app/sitemap.ts
  • src/components/seo/json-ld.tsx
  • src/lib/og-image.tsx
  • src/lib/seo.ts
  • src/lib/site.ts

Comment thread src/app/(public)/page.tsx Outdated
Comment thread src/app/robots.ts Outdated
'/get-started-modal-preview',
],
},
sitemap: `${SITE_URL}/sitemap.xml`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Shared root cause: manual SITE_URL concatenation in src/app/robots.ts and src/app/sitemap.ts can generate malformed URLs.

Both src/app/robots.ts (sitemap URL) and src/app/sitemap.ts (entry URLs) concatenate strings instead of resolving with URL. Switching both call sites to new URL(..., SITE_URL) removes trailing-slash edge cases consistently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/robots.ts` at line 27, Replace manual string concatenation with URL
resolution: in the robots.ts sitemap property (currently using
`${SITE_URL}/sitemap.xml`) and in src/app/sitemap.ts where individual entry URLs
are built, use new URL('sitemap.xml', SITE_URL) and new URL(pathOrFilename,
SITE_URL) respectively so URLs are constructed via the URL constructor to avoid
trailing-slash and edge-case bugs; locate the sitemap property in robots.ts and
the sitemap entry-building logic in sitemap.ts and update those call sites to
use new URL(..., SITE_URL).

Comment thread src/app/sitemap.ts
…page OG

- Bake the brand font (Plus Jakarta Sans, bundled .woff) into all generated
  Open Graph images via next/og.
- Add a raster PNG brand logo at /logo.png and use it as the Organization
  logo in JSON-LD (search engines prefer raster).
- Add app icons (icon, apple-icon) and a web app manifest.
- Add per-page Open Graph images for the marketing pages (home/discover/blog
  already had their own) so each gets a distinct share preview instead of the
  site default.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dates

- Home title uses "|" instead of an em dash (house copy rule).
- Build sitemap/robots URLs with new URL(..., SITE_URL) to avoid
  trailing-slash edge cases.
- Parse the "DD Month YYYY" blog date explicitly in UTC instead of relying on
  implementation-defined new Date(string).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@0xdevcollins 0xdevcollins merged commit 06239bb into main Jun 12, 2026
5 checks passed
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