-
Couldn't load subscription status.
- Fork 2.3k
Add structured data to the homepage #8427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
a1591f2
b2f273c
58d880a
2f7ed23
b7664ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,27 @@ | ||||||
| import { getStructuredData } from "@/lib/structured-data" | ||||||
|
|
||||||
| /** | ||||||
| * StructuredData Component | ||||||
| * | ||||||
| * Renders JSON-LD structured data in the document head for SEO. | ||||||
| * This component should only be used once per page, typically in the root layout. | ||||||
|
||||||
| * This component should only be used once per page, typically in the root layout. | |
| * Use once per page. For sitewide JSON-LD, include it in the root layout; for page-specific JSON-LD, include it in that page component. |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,127 @@ | ||||||
| import { SEO } from "./seo" | ||||||
| import { EXTERNAL_LINKS } from "./constants" | ||||||
|
|
||||||
| /** | ||||||
| * Type definitions for Schema.org structured data | ||||||
| */ | ||||||
| interface ImageObject { | ||||||
| "@type": "ImageObject" | ||||||
| url: string | ||||||
| width: number | ||||||
| height: number | ||||||
| } | ||||||
|
|
||||||
| interface Organization { | ||||||
| "@type": "Organization" | ||||||
| "@id": string | ||||||
| name: string | ||||||
| url: string | ||||||
| logo: ImageObject | ||||||
| alternateName: string[] | ||||||
| sameAs: string[] | ||||||
| } | ||||||
|
|
||||||
| interface WebSite { | ||||||
| "@type": "WebSite" | ||||||
| "@id": string | ||||||
| url: string | ||||||
| name: string | ||||||
| alternateName: string[] | ||||||
| publisher: { "@id": string } | ||||||
| } | ||||||
|
|
||||||
| interface SoftwareApplication { | ||||||
| "@type": "SoftwareApplication" | ||||||
| "@id": string | ||||||
| name: string | ||||||
| applicationCategory: string | ||||||
| operatingSystem: string | ||||||
| url: string | ||||||
| downloadUrl: string | ||||||
| offers: { | ||||||
| "@type": "Offer" | ||||||
| price: string | ||||||
| priceCurrency: string | ||||||
| } | ||||||
| isAccessibleForFree: boolean | ||||||
| publisher: { "@id": string } | ||||||
| } | ||||||
|
|
||||||
| interface StructuredDataGraph { | ||||||
| "@context": "https://schema.org" | ||||||
| "@graph": [Organization, WebSite, SoftwareApplication] | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Generates the complete JSON-LD structured data for SEO | ||||||
| * | ||||||
| * This includes: | ||||||
| * - Organization schema (brand identity, logo, social profiles) | ||||||
| * - WebSite schema (site name for Google Search) | ||||||
| * - SoftwareApplication schema (VS Code extension metadata) | ||||||
| * | ||||||
| * @returns Complete structured data object ready for JSON-LD injection | ||||||
| */ | ||||||
| export function getStructuredData(): StructuredDataGraph { | ||||||
| // Organization ID - used to link all entities | ||||||
| const orgId = `${SEO.url}#org` | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Ensure consistent @id with a single slash before the fragment and avoid double slashes if SEO.url ends with '/'.
Suggested change
|
||||||
|
|
||||||
| const organization: Organization = { | ||||||
| "@type": "Organization", | ||||||
| "@id": orgId, | ||||||
| name: SEO.name, | ||||||
| url: SEO.url, | ||||||
| logo: { | ||||||
| "@type": "ImageObject", | ||||||
| url: `${SEO.url}/android-chrome-512x512.png`, | ||||||
| width: 512, | ||||||
| height: 512, | ||||||
| }, | ||||||
| alternateName: ["RooCode", "Roo Code AI"], | ||||||
mrubens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| sameAs: [ | ||||||
| EXTERNAL_LINKS.GITHUB, | ||||||
| EXTERNAL_LINKS.MARKETPLACE, | ||||||
| EXTERNAL_LINKS.X, | ||||||
| EXTERNAL_LINKS.LINKEDIN, | ||||||
| EXTERNAL_LINKS.REDDIT, | ||||||
| EXTERNAL_LINKS.DISCORD, | ||||||
| EXTERNAL_LINKS.YOUTUBE, | ||||||
| ], | ||||||
| } | ||||||
|
|
||||||
| const website: WebSite = { | ||||||
| "@type": "WebSite", | ||||||
| "@id": `${SEO.url}#website`, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Normalize WebSite @id similar to org.
Suggested change
|
||||||
| url: SEO.url, | ||||||
| name: SEO.name, | ||||||
| alternateName: ["RooCode"], | ||||||
| publisher: { "@id": orgId }, | ||||||
| } | ||||||
|
|
||||||
| const softwareApplication: SoftwareApplication = { | ||||||
| "@type": "SoftwareApplication", | ||||||
| "@id": `${SEO.url}#vscode-extension`, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Normalize SoftwareApplication @id similar to org.
Suggested change
|
||||||
| name: "Roo Code (VS Code extension)", | ||||||
| applicationCategory: "DeveloperApplication", | ||||||
| operatingSystem: "Windows, macOS, Linux", | ||||||
| url: SEO.url, | ||||||
| downloadUrl: EXTERNAL_LINKS.MARKETPLACE, | ||||||
| offers: { | ||||||
| "@type": "Offer", | ||||||
| price: "0", | ||||||
| priceCurrency: "USD", | ||||||
| }, | ||||||
| isAccessibleForFree: true, | ||||||
| publisher: { "@id": orgId }, | ||||||
| } | ||||||
|
|
||||||
| return { | ||||||
| "@context": "https://schema.org", | ||||||
| "@graph": [organization, website, softwareApplication], | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Type export for use in components | ||||||
| */ | ||||||
| export type { StructuredDataGraph } | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: Optional: If you want JSON-LD on all routes, consider rendering StructuredData in the root layout instead of the home page to avoid duplication and ensure consistency.