Skip to content

Commit f0802f1

Browse files
committed
feat(web): bias Google Sitelinks toward Extension, Cloud, Docs, Pricing
- Add /extension canonical page with metadata and BreadcrumbList JSON-LD - Header: change 'Extension' to link /extension (desktop & mobile) - Home hero: add above-the-fold Docs/Pricing links - Footer: add Cloud and Pricing under Product - Sitemap: prioritize /extension (0.9), /cloud & /pricing (0.8); fix additionalPaths; reduce /enterprise - Robots: publish roocode.com and docs.roocode.com sitemaps - Structured data: add SiteNavigationElement; per-page BreadcrumbList - Ensure explicit metadata on Cloud/Pricing/Extension; fix rel for target=_blank
1 parent f30caf2 commit f0802f1

File tree

9 files changed

+197
-29
lines changed

9 files changed

+197
-29
lines changed

apps/web-roo-code/next-sitemap.config.cjs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,18 @@ module.exports = {
3333
if (path === '/') {
3434
priority = 1.0;
3535
changefreq = 'yearly';
36-
} else if (path === '/enterprise' || path === '/evals') {
36+
} else if (path === '/extension') {
37+
priority = 0.9;
38+
changefreq = 'monthly';
39+
} else if (path === '/cloud' || path === '/pricing') {
3740
priority = 0.8;
3841
changefreq = 'monthly';
42+
} else if (path === '/enterprise') {
43+
priority = 0.5;
44+
changefreq = 'yearly';
45+
} else if (path === '/evals') {
46+
priority = 0.6;
47+
changefreq = 'monthly';
3948
} else if (path === '/privacy' || path === '/terms') {
4049
priority = 0.5;
4150
changefreq = 'yearly';
@@ -50,24 +59,20 @@ module.exports = {
5059
};
5160
},
5261
additionalPaths: async (config) => {
53-
// Add any additional paths that might not be automatically discovered
54-
// This is useful for dynamic routes or API-generated pages
55-
// Add the /evals page since it's a dynamic route
56-
return [{
57-
loc: '/evals',
58-
changefreq: 'monthly',
59-
priority: 0.8,
60-
lastmod: new Date().toISOString(),
61-
}];
62-
63-
// Add the /evals page since it's a dynamic route
64-
result.push({
65-
loc: '/evals',
66-
changefreq: 'monthly',
67-
priority: 0.8,
68-
lastmod: new Date().toISOString(),
69-
});
70-
71-
return result;
62+
// Explicitly include dynamic or non-file-system paths
63+
return [
64+
{
65+
loc: '/evals',
66+
changefreq: 'monthly',
67+
priority: 0.6,
68+
lastmod: new Date().toISOString(),
69+
},
70+
{
71+
loc: '/extension',
72+
changefreq: 'monthly',
73+
priority: 0.9,
74+
lastmod: new Date().toISOString(),
75+
},
76+
];
7277
},
7378
};

apps/web-roo-code/src/app/cloud/page.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,17 @@ const cloudFeatures: Feature[] = [
119119
import screenshotDark from "/public/heroes/cloud-screen.png"
120120

121121
export default function CloudPage() {
122+
const breadcrumbLd = {
123+
"@context": "https://schema.org",
124+
"@type": "BreadcrumbList",
125+
itemListElement: [
126+
{ "@type": "ListItem", position: 1, name: "Home", item: SEO.url },
127+
{ "@type": "ListItem", position: 2, name: "Cloud", item: `${SEO.url}${PATH}` },
128+
],
129+
}
122130
return (
123131
<>
132+
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbLd) }} />
124133
<section className="relative flex md:h-[calc(80vh-theme(spacing.12))] items-center overflow-hidden">
125134
<AnimatedBackground />
126135
<div className="container relative flex items-center h-full z-10 mx-auto px-4 sm:px-6 lg:px-8">
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { ArrowRight } from "lucide-react"
2+
import type { Metadata } from "next"
3+
import Link from "next/link"
4+
5+
import { Button } from "@/components/ui"
6+
import { AnimatedBackground } from "@/components/homepage"
7+
import { SEO } from "@/lib/seo"
8+
import { EXTERNAL_LINKS } from "@/lib/constants"
9+
10+
const TITLE = "Roo Code Extension"
11+
const DESCRIPTION = "Open-source VS Code extension that turns your editor into an AI dev team. Works with any model."
12+
const PATH = "/extension"
13+
const OG_IMAGE = SEO.ogImage
14+
15+
export const metadata: Metadata = {
16+
title: TITLE,
17+
description: DESCRIPTION,
18+
alternates: { canonical: `${SEO.url}${PATH}` },
19+
openGraph: {
20+
title: TITLE,
21+
description: DESCRIPTION,
22+
url: `${SEO.url}${PATH}`,
23+
siteName: SEO.name,
24+
images: [{ url: OG_IMAGE.url, width: OG_IMAGE.width, height: OG_IMAGE.height, alt: OG_IMAGE.alt }],
25+
locale: SEO.locale,
26+
type: "website",
27+
},
28+
twitter: {
29+
card: SEO.twitterCard,
30+
title: TITLE,
31+
description: DESCRIPTION,
32+
images: [OG_IMAGE.url],
33+
},
34+
keywords: [...SEO.keywords, "VS Code extension", "Roo Code extension"],
35+
}
36+
37+
export default function ExtensionPage() {
38+
const breadcrumbLd = {
39+
"@context": "https://schema.org",
40+
"@type": "BreadcrumbList",
41+
itemListElement: [
42+
{ "@type": "ListItem", position: 1, name: "Home", item: SEO.url },
43+
{ "@type": "ListItem", position: 2, name: "Extension", item: `${SEO.url}${PATH}` },
44+
],
45+
}
46+
47+
return (
48+
<>
49+
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbLd) }} />
50+
<section className="relative flex md:h-[calc(80vh-theme(spacing.12))] items-center overflow-hidden">
51+
<AnimatedBackground />
52+
<div className="container relative flex items-center h-full z-10 mx-auto px-4 sm:px-6 lg:px-8">
53+
<div className="grid h-full relative gap-8 lg:grid-cols-2">
54+
<div className="flex flex-col px-4 justify-center space-y-6 sm:space-y-8">
55+
<div>
56+
<h1 className="text-4xl font-bold tracking-tight mt-8 text-center md:text-left md:text-4xl lg:text-5xl lg:mt-0">
57+
Roo Code Extension
58+
</h1>
59+
<p className="mt-4 max-w-md text-lg text-muted-foreground text-center md:text-left sm:mt-6">
60+
Open-source AI coding agent that lives in VS Code. Multi-step, project‑wide context,
61+
and works with any model.
62+
</p>
63+
</div>
64+
<div className="flex flex-col space-y-3 sm:flex-row sm:space-x-4 sm:space-y-0">
65+
<Button
66+
size="lg"
67+
className="w-full hover:bg-gray-200 dark:bg-white dark:text-black sm:w-auto">
68+
<a
69+
href={EXTERNAL_LINKS.MARKETPLACE}
70+
target="_blank"
71+
rel="noreferrer"
72+
className="flex w-full items-center justify-center">
73+
Install VS Code Extension
74+
<ArrowRight className="ml-2" />
75+
</a>
76+
</Button>
77+
<Button
78+
variant="outline"
79+
size="lg"
80+
className="w-full sm:w-auto bg-white/20 dark:bg-white/10 backdrop-blur-sm border border-black/40 dark:border-white/30 hover:border-blue-400 hover:bg-white/30 dark:hover:bg-white/20 hover:shadow-[0_0_20px_rgba(59,130,246,0.5)] transition-all duration-300">
81+
<a
82+
href={EXTERNAL_LINKS.DOCUMENTATION}
83+
target="_blank"
84+
rel="noreferrer"
85+
className="flex w-full items-center justify-center">
86+
Docs
87+
<ArrowRight className="ml-2" />
88+
</a>
89+
</Button>
90+
</div>
91+
<div className="text-sm text-muted-foreground text-center md:text-left">
92+
<Link href="/pricing" className="underline underline-offset-4 hover:text-foreground">
93+
Pricing
94+
</Link>
95+
</div>
96+
</div>
97+
</div>
98+
</div>
99+
</section>
100+
</>
101+
)
102+
}

apps/web-roo-code/src/app/page.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from "@/components/homepage"
1515
import { EXTERNAL_LINKS } from "@/lib/constants"
1616
import { ArrowRight } from "lucide-react"
17+
import Link from "next/link"
1718
import { StructuredData } from "@/components/structured-data"
1819

1920
// Invalidate cache when a request comes in, at most once every hour.
@@ -64,6 +65,19 @@ export default async function Home() {
6465
</a>
6566
</Button>
6667
</div>
68+
<div className="text-sm text-muted-foreground text-center md:text-left">
69+
<a
70+
href={EXTERNAL_LINKS.DOCUMENTATION}
71+
target="_blank"
72+
rel="noopener noreferrer"
73+
className="underline underline-offset-4 hover:text-foreground">
74+
Docs
75+
</a>
76+
<span className="mx-2"></span>
77+
<Link href="/pricing" className="underline underline-offset-4 hover:text-foreground">
78+
Pricing
79+
</Link>
80+
</div>
6781
<CompanyLogos />
6882
</div>
6983
<div className="relative flex items-center mx-auto h-full mt-8 lg:mt-0">

apps/web-roo-code/src/app/pricing/page.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,18 @@ const pricingTiers: PricingTier[] = [
132132
]
133133

134134
export default function PricingPage() {
135+
const breadcrumbLd = {
136+
"@context": "https://schema.org",
137+
"@type": "BreadcrumbList",
138+
itemListElement: [
139+
{ "@type": "ListItem", position: 1, name: "Home", item: SEO.url },
140+
{ "@type": "ListItem", position: 2, name: "Pricing", item: `${SEO.url}${PATH}` },
141+
],
142+
}
135143
return (
136144
<>
137145
<AnimatedBackground />
146+
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbLd) }} />
138147

139148
{/* Hero Section */}
140149
<section className="relative overflow-hidden pt-16 pb-12">

apps/web-roo-code/src/app/robots.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default function robots(): MetadataRoute.Robots {
77
userAgent: "*",
88
allow: "/",
99
},
10-
sitemap: `${SEO.url}/sitemap.xml`,
10+
sitemap: [`${SEO.url}/sitemap.xml`, "https://docs.roocode.com/sitemap.xml"],
1111
host: SEO.url,
1212
}
1313
}

apps/web-roo-code/src/components/chromes/footer.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ export function Footer() {
7878
Docs
7979
</a>
8080
</li>
81+
<li>
82+
<Link
83+
href="/cloud"
84+
className="text-sm leading-6 text-muted-foreground transition-colors hover:text-foreground">
85+
Cloud
86+
</Link>
87+
</li>
88+
<li>
89+
<Link
90+
href="/pricing"
91+
className="text-sm leading-6 text-muted-foreground transition-colors hover:text-foreground">
92+
Pricing
93+
</Link>
94+
</li>
8195
<li>
8296
<a
8397
href={EXTERNAL_LINKS.CHANGELOG}

apps/web-roo-code/src/components/chromes/nav-bar.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ export function NavBar({ stars, downloads }: NavBarProps) {
3535

3636
{/* Desktop Navigation */}
3737
<nav className="grow ml-6 hidden text-sm font-medium md:flex md:items-center">
38-
<ScrollButton
39-
targetId="product"
38+
<Link
39+
href="/extension"
4040
className="text-muted-foreground px-4 py-6 transition-transform duration-200 hover:scale-105 hover:text-foreground max-lg:hidden">
4141
Extension
42-
</ScrollButton>
42+
</Link>
4343
<Link
4444
href="/cloud"
4545
className="text-muted-foreground px-4 py-6 transition-transform duration-200 hover:scale-105 hover:text-foreground">
@@ -141,12 +141,12 @@ export function NavBar({ stars, downloads }: NavBarProps) {
141141
<nav className="flex flex-col justify-between h-full pb-16 overflow-y-auto bg-background pointer-events-auto">
142142
{/* Main navigation items */}
143143
<div className="grow-1 py-4 font-semibold text-lg">
144-
<ScrollButton
145-
targetId="product"
144+
<Link
145+
href="/extension"
146146
className="block w-full p-5 py-3 text-left text-foreground active:opacity-50"
147147
onClick={() => setIsMenuOpen(false)}>
148148
Extension
149-
</ScrollButton>
149+
</Link>
150150
<Link
151151
href="/cloud"
152152
className="block w-full p-5 text-left text-foreground active:opacity-50"

apps/web-roo-code/src/lib/structured-data.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,17 @@ interface SoftwareApplication {
4747
publisher: { "@id": string }
4848
}
4949

50+
interface SiteNavigationElement {
51+
"@type": "SiteNavigationElement"
52+
name: string
53+
url: string
54+
}
55+
56+
type GraphNode = Organization | WebSite | SoftwareApplication | SiteNavigationElement
57+
5058
interface StructuredDataGraph {
5159
"@context": "https://schema.org"
52-
"@graph": [Organization, WebSite, SoftwareApplication]
60+
"@graph": GraphNode[]
5361
}
5462

5563
/**
@@ -115,9 +123,16 @@ export function getStructuredData(): StructuredDataGraph {
115123
publisher: { "@id": orgId },
116124
}
117125

126+
const siteNavigation: SiteNavigationElement[] = [
127+
{ "@type": "SiteNavigationElement", name: "Extension", url: `${SEO.url}/extension` },
128+
{ "@type": "SiteNavigationElement", name: "Cloud", url: `${SEO.url}/cloud` },
129+
{ "@type": "SiteNavigationElement", name: "Docs", url: EXTERNAL_LINKS.DOCUMENTATION },
130+
{ "@type": "SiteNavigationElement", name: "Pricing", url: `${SEO.url}/pricing` },
131+
]
132+
118133
return {
119134
"@context": "https://schema.org",
120-
"@graph": [organization, website, softwareApplication],
135+
"@graph": [organization, website, softwareApplication, ...siteNavigation],
121136
}
122137
}
123138

0 commit comments

Comments
 (0)