Skip to content

Commit e8c06cf

Browse files
committed
feat(web): add /pr-fixer page, cross-links between Reviewer and Fixer, and Cloud Agents footer; fix lint issues by escaping apostrophes
1 parent ce88b02 commit e8c06cf

File tree

4 files changed

+352
-1
lines changed

4 files changed

+352
-1
lines changed
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
"use client"
2+
3+
import { ArrowRight, GitPullRequest, History, Key, MessageSquareCode, Wrench, type LucideIcon } from "lucide-react"
4+
import Image from "next/image"
5+
import Link from "next/link"
6+
7+
import { Button } from "@/components/ui"
8+
import { AnimatedBackground } from "@/components/homepage"
9+
import { EXTERNAL_LINKS } from "@/lib/constants"
10+
import { trackGoogleAdsConversion } from "@/lib/analytics/google-ads"
11+
12+
// Workaround for next/image choking on these for some reason
13+
import hero from "/public/heroes/agent-reviewer.png"
14+
15+
interface Feature {
16+
icon: LucideIcon
17+
title: string
18+
description: string | React.ReactNode
19+
logos?: string[]
20+
}
21+
22+
const workflowSteps: Feature[] = [
23+
{
24+
icon: GitPullRequest,
25+
title: "1. Work in your PR",
26+
description: "Open a pull request like usual. The PR Fixer seamlessly integrates into your existing workflow.",
27+
},
28+
{
29+
icon: MessageSquareCode,
30+
title: "2. Invoke from a comment",
31+
description:
32+
'Ask the agent to fix issues directly from GitHub PR comments (e.g. "roo: fix these review comments"). It’s fully aware of the entire comment history and latest diffs.',
33+
},
34+
{
35+
icon: Wrench,
36+
title: "3. Clean, scoped commits",
37+
description:
38+
"The agent proposes targeted changes and pushes concise commits or patch suggestions you can review and merge quickly.",
39+
},
40+
]
41+
42+
const howItWorks: Feature[] = [
43+
{
44+
icon: History,
45+
title: "Comment-history aware",
46+
description:
47+
"Understands the entire conversation on the PR – previous reviews, your replies, follow-ups – and uses that context to produce accurate fixes.",
48+
},
49+
{
50+
icon: Key,
51+
title: "Bring your own key",
52+
description:
53+
"Use your preferred models at full strength. We optimize prompts and execution without capping your model to protect our margins.",
54+
},
55+
{
56+
icon: GitPullRequest,
57+
title: "Repository- and diff-aware",
58+
description:
59+
"Analyzes the full repo context and the latest diff to ensure fixes align with project conventions and pass checks.",
60+
},
61+
]
62+
63+
export function PrFixerContent() {
64+
return (
65+
<>
66+
<section className="relative flex md:h-[calc(70vh-theme(spacing.12))] items-center overflow-hidden">
67+
<AnimatedBackground />
68+
<div className="container relative flex items-center h-full z-10 mx-auto px-4 sm:px-6 lg:px-8">
69+
<div className="grid h-full relative gap-4 md:gap-20 lg:grid-cols-2">
70+
<div className="flex flex-col px-4 justify-center space-y-6 sm:space-y-8">
71+
<div>
72+
<h1 className="text-3xl font-bold tracking-tight mt-8 md:text-left md:text-4xl lg:text-5xl lg:mt-0">
73+
Turn review feedback into clean commits — automatically.
74+
</h1>
75+
76+
{/* Cross-agent link */}
77+
<div className="mt-3">
78+
<Link
79+
href="/reviewer"
80+
className="inline-flex items-center rounded-full border border-blue-500/30 bg-blue-500/10 px-3 py-1 text-sm text-blue-600 backdrop-blur-sm transition-colors hover:bg-blue-500/20 dark:text-blue-400"
81+
aria-label="Works great with PR Reviewer">
82+
Works great with PR Reviewer
83+
<ArrowRight className="ml-2 h-4 w-4" />
84+
</Link>
85+
</div>
86+
87+
<div className="mt-4 max-w-lg space-y-4 text-base text-muted-foreground md:text-left sm:mt-6">
88+
<p>
89+
Roo Code{"'"}s PR Fixer applies high-quality changes to your PRs, right from
90+
GitHub. You can invoke it via PR comments and it will read the entire comment
91+
history to understand context, agreements, and tradeoffs — then implement the
92+
right fix.
93+
</p>
94+
<p>
95+
Because it{"'"}s repository- and diff-aware, it keeps changes tight, follows
96+
conventions, and plays nicely with your CI. You bring the model key; we
97+
orchestrate smart, efficient workflows.
98+
</p>
99+
</div>
100+
</div>
101+
102+
<div className="flex flex-col space-y-3 sm:flex-row sm:space-x-4 sm:space-y-0 md:items-center">
103+
<Button
104+
size="lg"
105+
className="w-full sm:w-auto backdrop-blur-sm border hover:shadow-[0_0_20px_rgba(59,130,246,0.5)] transition-all duration-300"
106+
asChild>
107+
<a
108+
href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP_PRO}
109+
target="_blank"
110+
rel="noopener noreferrer"
111+
onClick={trackGoogleAdsConversion}
112+
className="flex w-full items-center justify-center">
113+
Start 14-day Free Trial
114+
<ArrowRight className="ml-2" />
115+
</a>
116+
</Button>
117+
<span className="text-sm text-center md:text-left text-muted-foreground md:ml-2">
118+
(cancel anytime)
119+
</span>
120+
</div>
121+
</div>
122+
123+
<div className="flex items-center justify-end mx-auto h-full mt-8 lg:mt-0">
124+
<div className="md:w-[800px] md:h-[474px] relative overflow-clip">
125+
<div className="block">
126+
<Image
127+
src={hero}
128+
alt="Example of a PR Fixer applying changes from review comments"
129+
className="max-w-full h-auto"
130+
width={800}
131+
height={474}
132+
/>
133+
</div>
134+
</div>
135+
</div>
136+
</div>
137+
</div>
138+
</section>
139+
140+
{/* How It Works Section */}
141+
<section className="relative overflow-hidden border-t border-border py-32">
142+
<div className="container relative z-10 mx-auto px-4 sm:px-6 lg:px-8">
143+
<div className="mx-auto mb-12 md:mb-24 max-w-5xl text-center">
144+
<div>
145+
<h2 className="text-4xl font-bold tracking-tight sm:text-5xl">How It Works</h2>
146+
</div>
147+
</div>
148+
149+
<div className="relative mx-auto md:max-w-[1200px]">
150+
<ul className="grid grid-cols-1 place-items-center gap-6 md:grid-cols-3 lg:gap-8">
151+
{workflowSteps.map((step, index) => {
152+
const Icon = step.icon
153+
return (
154+
<li
155+
key={index}
156+
className="relative h-full border border-border rounded-2xl bg-background p-8 transition-all duration-300 hover:shadow-lg">
157+
<Icon className="size-6 text-foreground/80" />
158+
<h3 className="mb-3 mt-3 text-xl font-semibold text-foreground">
159+
{step.title}
160+
</h3>
161+
<div className="leading-relaxed font-light text-muted-foreground">
162+
{step.description}
163+
</div>
164+
</li>
165+
)
166+
})}
167+
</ul>
168+
</div>
169+
</div>
170+
</section>
171+
172+
<section className="relative overflow-hidden border-t border-border py-32">
173+
<div className="container relative z-10 mx-auto px-4 sm:px-6 lg:px-8">
174+
<div className="mx-auto mb-12 md:mb-24 max-w-5xl text-center">
175+
<div>
176+
<h2 className="text-4xl font-bold tracking-tight sm:text-5xl">
177+
Why Roo Code{"'"}s PR Fixer is different
178+
</h2>
179+
</div>
180+
</div>
181+
182+
<div className="relative mx-auto md:max-w-[1200px]">
183+
<ul className="grid grid-cols-1 place-items-center gap-6 md:grid-cols-2 lg:grid-cols-3 lg:gap-8">
184+
{howItWorks.map((feature, index) => {
185+
const Icon = feature.icon
186+
return (
187+
<li
188+
key={index}
189+
className="relative h-full border border-border rounded-2xl bg-background p-8 transition-all duration-300">
190+
<Icon className="size-6 text-foreground/80" />
191+
<h3 className="mb-3 mt-3 text-xl font-semibold text-foreground">
192+
{feature.title}
193+
</h3>
194+
<div className="leading-relaxed font-light text-muted-foreground space-y-2">
195+
{feature.description}
196+
</div>
197+
</li>
198+
)
199+
})}
200+
</ul>
201+
</div>
202+
</div>
203+
</section>
204+
205+
{/* CTA Section */}
206+
<section className="py-20">
207+
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
208+
<div className="mx-auto max-w-4xl rounded-3xl border border-border/50 bg-gradient-to-br from-blue-500/5 via-cyan-500/5 to-purple-500/5 p-8 text-center shadow-2xl backdrop-blur-xl dark:border-white/20 dark:bg-gradient-to-br dark:from-gray-800 dark:via-gray-900 dark:to-black sm:p-12">
209+
<h2 className="mb-4 text-3xl font-bold tracking-tight sm:text-4xl">
210+
Ship fixes, not follow-ups.
211+
</h2>
212+
<p className="mx-auto mb-8 max-w-2xl text-lg text-muted-foreground">
213+
Let Roo Code{"'"}s PR Fixer turn your review feedback into clean, ready-to-merge commits.
214+
</p>
215+
<div className="flex flex-col justify-center space-y-4 sm:flex-row sm:space-x-4 sm:space-y-0">
216+
<Button
217+
size="lg"
218+
className="bg-black text-white hover:bg-gray-800 hover:shadow-lg hover:shadow-black/20 dark:bg-white dark:text-black dark:hover:bg-gray-200 dark:hover:shadow-white/20 transition-all duration-300"
219+
asChild>
220+
<a
221+
href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP_PRO}
222+
target="_blank"
223+
rel="noopener noreferrer"
224+
onClick={trackGoogleAdsConversion}
225+
className="flex items-center justify-center">
226+
Start 14-day Free Trial
227+
<ArrowRight className="ml-2 h-4 w-4" />
228+
</a>
229+
</Button>
230+
</div>
231+
</div>
232+
</div>
233+
</section>
234+
</>
235+
)
236+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import type { Metadata } from "next"
2+
3+
import { SEO } from "@/lib/seo"
4+
import { ogImageUrl } from "@/lib/og"
5+
import { PrFixerContent } from "./PrFixerContent"
6+
7+
const TITLE = "PR Fixer"
8+
const DESCRIPTION =
9+
"Automatically apply high-quality fixes to your pull requests with comment-aware, GitHub-native workflows."
10+
const OG_DESCRIPTION = "Transform review feedback into clean commits"
11+
const PATH = "/pr-fixer"
12+
13+
export const metadata: Metadata = {
14+
title: TITLE,
15+
description: DESCRIPTION,
16+
alternates: {
17+
canonical: `${SEO.url}${PATH}`,
18+
},
19+
openGraph: {
20+
title: TITLE,
21+
description: DESCRIPTION,
22+
url: `${SEO.url}${PATH}`,
23+
siteName: SEO.name,
24+
images: [
25+
{
26+
url: ogImageUrl(TITLE, OG_DESCRIPTION),
27+
width: 1200,
28+
height: 630,
29+
alt: TITLE,
30+
},
31+
],
32+
locale: SEO.locale,
33+
type: "website",
34+
},
35+
twitter: {
36+
card: SEO.twitterCard,
37+
title: TITLE,
38+
description: DESCRIPTION,
39+
images: [ogImageUrl(TITLE, OG_DESCRIPTION)],
40+
},
41+
keywords: [
42+
...SEO.keywords,
43+
"PR fixer",
44+
"pull request fixes",
45+
"code fixes",
46+
"GitHub PR",
47+
"automated code fixes",
48+
"comment-aware agent",
49+
"repository-aware fixes",
50+
"bring your own key",
51+
"BYOK AI",
52+
"code quality",
53+
"cloud agents",
54+
"AI development team",
55+
],
56+
}
57+
58+
export default function AgentPrFixerPage() {
59+
return <PrFixerContent />
60+
}

apps/web-roo-code/src/app/reviewer/ReviewerContent.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
MessageSquareCode,
1212
} from "lucide-react"
1313
import Image from "next/image"
14+
import Link from "next/link"
1415

1516
import { Button } from "@/components/ui"
1617
import { AnimatedBackground } from "@/components/homepage"
@@ -88,6 +89,15 @@ export function ReviewerContent() {
8889
<h1 className="text-3xl font-bold tracking-tight mt-8 md:text-left md:text-4xl lg:text-5xl lg:mt-0">
8990
Get comprehensive code reviews that save you time, not&nbsp;tokens.
9091
</h1>
92+
<div className="mt-3">
93+
<Link
94+
href="/pr-fixer"
95+
className="inline-flex items-center rounded-full border border-blue-500/30 bg-blue-500/10 px-3 py-1 text-sm text-blue-600 backdrop-blur-sm transition-colors hover:bg-blue-500/20 dark:text-blue-400"
96+
aria-label="Works great with PR Fixer">
97+
Works great with PR Fixer
98+
<ArrowRight className="ml-2 h-4 w-4" />
99+
</Link>
100+
</div>
91101
<div className="mt-4 max-w-lg space-y-4 text-base text-muted-foreground md:text-left sm:mt-6">
92102
<p>
93103
Regular AI code review tools cap model usage to protect their margins from fixed

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

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,22 @@ import { ScrollButton } from "@/components/ui"
1212

1313
export function Footer() {
1414
const [privacyDropdownOpen, setPrivacyDropdownOpen] = useState(false)
15+
const [cloudDropdownOpen, setCloudDropdownOpen] = useState(false)
1516
const dropdownRef = useRef<HTMLDivElement>(null)
17+
const cloudDropdownRef = useRef<HTMLDivElement>(null)
1618
const logoSrc = useLogoSrc()
1719
const { resolvedTheme } = useTheme()
1820

1921
// Close dropdown when clicking outside
2022
useEffect(() => {
2123
function handleClickOutside(event: MouseEvent) {
22-
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
24+
const target = event.target as Node
25+
if (dropdownRef.current && !dropdownRef.current.contains(target)) {
2326
setPrivacyDropdownOpen(false)
2427
}
28+
if (cloudDropdownRef.current && !cloudDropdownRef.current.contains(target)) {
29+
setCloudDropdownOpen(false)
30+
}
2531
}
2632

2733
document.addEventListener("mousedown", handleClickOutside)
@@ -69,6 +75,45 @@ export function Footer() {
6975
Features
7076
</ScrollButton>
7177
</li>
78+
<li>
79+
<div className="relative z-10" ref={cloudDropdownRef}>
80+
<button
81+
onClick={() => setCloudDropdownOpen(!cloudDropdownOpen)}
82+
className="flex items-center text-sm leading-6 text-muted-foreground transition-colors hover:text-foreground"
83+
aria-expanded={cloudDropdownOpen}
84+
aria-haspopup="true">
85+
<span>Cloud Agents</span>
86+
<ChevronDown
87+
className={`ml-1 h-4 w-4 transition-transform ${cloudDropdownOpen ? "rotate-180" : ""}`}
88+
/>
89+
</button>
90+
91+
{cloudDropdownOpen && (
92+
<div className="absolute z-50 mt-2 w-44 origin-top-left scale-95 rounded-md border border-border bg-background shadow-lg ring-1 ring-black ring-opacity-5 transition-all duration-100 ease-out data-[state=open]:scale-100 max-xs:right-0 max-xs:origin-top-right xs:left-0">
93+
<div className="flex flex-col gap-1 p-2 text-sm text-muted-foreground">
94+
<Link
95+
href="/cloud"
96+
onClick={() => setCloudDropdownOpen(false)}
97+
className="rounded-md px-3 py-2 transition-colors hover:bg-accent/50 hover:text-foreground">
98+
Cloud
99+
</Link>
100+
<Link
101+
href="/reviewer"
102+
onClick={() => setCloudDropdownOpen(false)}
103+
className="rounded-md px-3 py-2 transition-colors hover:bg-accent/50 hover:text-foreground">
104+
PR Reviewer
105+
</Link>
106+
<Link
107+
href="/pr-fixer"
108+
onClick={() => setCloudDropdownOpen(false)}
109+
className="rounded-md px-3 py-2 transition-colors hover:bg-accent/50 hover:text-foreground">
110+
PR Fixer
111+
</Link>
112+
</div>
113+
</div>
114+
)}
115+
</div>
116+
</li>
72117
<li>
73118
<a
74119
href={EXTERNAL_LINKS.DOCUMENTATION}

0 commit comments

Comments
 (0)