forked from cline/cline
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
web: Landing page for the reviewerFirst pass #8740
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
Merged
Merged
Changes from 2 commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,266 @@ | ||
| import { ArrowRight, Blocks, BookMarked, ListChecks, LucideIcon } from "lucide-react" | ||
| import type { Metadata } from "next" | ||
|
|
||
| import { Button } from "@/components/ui" | ||
| import { AnimatedBackground } from "@/components/homepage" | ||
| import { AgentCarousel } from "@/components/reviewer/agent-carousel" | ||
| import { SEO } from "@/lib/seo" | ||
| import { EXTERNAL_LINKS } from "@/lib/constants" | ||
| import Image from "next/image" | ||
|
|
||
| const TITLE = "PR Reviewer · Roo Code Cloud" | ||
| const DESCRIPTION = | ||
| "Get comprehensive AI-powered PR reviews that save you time, not tokens. Bring your own API key and leverage advanced reasoning, repository-aware analysis, and actionable feedback to keep your PR queue moving." | ||
| const PATH = "/reviewer" | ||
| const OG_IMAGE = SEO.ogImage | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: TITLE, | ||
| description: DESCRIPTION, | ||
| alternates: { | ||
| canonical: `${SEO.url}${PATH}`, | ||
| }, | ||
| openGraph: { | ||
| title: TITLE, | ||
| description: DESCRIPTION, | ||
| url: `${SEO.url}${PATH}`, | ||
| siteName: SEO.name, | ||
| images: [ | ||
| { | ||
| url: OG_IMAGE.url, | ||
| width: OG_IMAGE.width, | ||
| height: OG_IMAGE.height, | ||
| alt: OG_IMAGE.alt, | ||
| }, | ||
| ], | ||
| locale: SEO.locale, | ||
| type: "website", | ||
| }, | ||
| twitter: { | ||
| card: SEO.twitterCard, | ||
| title: TITLE, | ||
| description: DESCRIPTION, | ||
| images: [OG_IMAGE.url], | ||
| }, | ||
| keywords: [ | ||
| ...SEO.keywords, | ||
| "PR reviewer", | ||
| "code review", | ||
| "pull request review", | ||
| "AI code review", | ||
| "GitHub PR review", | ||
| "automated code review", | ||
| "repository-aware review", | ||
| "bring your own key", | ||
| "BYOK AI", | ||
| "code quality", | ||
| "development workflow", | ||
| "cloud agents", | ||
| "AI development team", | ||
| ], | ||
| } | ||
|
|
||
| interface Feature { | ||
| icon: LucideIcon | ||
| title: string | ||
| description: string | React.ReactNode | ||
| logos?: string[] | ||
| } | ||
|
|
||
| const howItWorks: Feature[] = [ | ||
| { | ||
| icon: Blocks, | ||
| title: "Our agents, your provider keys", | ||
| description: ( | ||
| <> | ||
| <p> | ||
| We orchestrate the review, optimize the hell out of the prompts, integrate with GitHub, keep you | ||
| properly posted. | ||
| </p> | ||
| <p>We're thoughtful about token usage, but not incentivized to skimp to grow our margins.</p> | ||
| </> | ||
| ), | ||
| }, | ||
| { | ||
| icon: ListChecks, | ||
| title: "Advanced reasoning and workflows", | ||
| description: | ||
| "We optimize for state-of-the-art reasoning models and leverage powerful workflows (Diff analysis → Context Gathering → Impact Mapping → Contract checks) to produce crisp, actionable comments at the right level.", | ||
| }, | ||
| { | ||
| icon: BookMarked, | ||
| title: "Fully repository-aware", | ||
| description: | ||
| "Reviews traverse code ownership, dependency graphs, and historical patterns to surface risk and deviations, not noise.", | ||
| }, | ||
| ] | ||
|
|
||
| // Workaround for next/image choking on these for some reason | ||
| import hero from "/public/heroes/agent-reviewer.png" | ||
|
|
||
| export default function AgentReviewerPage() { | ||
| return ( | ||
| <> | ||
| <section className="relative flex md:h-[calc(70vh-theme(spacing.12))] items-center overflow-hidden"> | ||
| <AnimatedBackground /> | ||
| <div className="container relative flex items-center h-full z-10 mx-auto px-4 sm:px-6 lg:px-8"> | ||
| <div className="grid h-full relative gap-4 md:gap-20 lg:grid-cols-2"> | ||
| <div className="flex flex-col px-4 justify-center space-y-6 sm:space-y-8"> | ||
| <div> | ||
| <h1 className="text-3xl font-bold tracking-tight mt-8 md:text-left md:text-4xl lg:text-5xl lg:mt-0"> | ||
| Get comprehensive reviews that save you time, not tokens. | ||
| </h1> | ||
| <div className="mt-4 max-w-lg space-y-4 text-base text-muted-foreground md:text-left sm:mt-6"> | ||
| <p> | ||
| Regular AI code review tools cap model usage to protect their margins from fixed | ||
| monthly prices. That leads to shallow prompts, limited context, and missed | ||
| issues. | ||
| </p> | ||
| <p> | ||
| Roo Code's PR Reviewer flips the model: you bring your own key and leverage | ||
| it to the max – to find real issues, increase code quality and keep your PR | ||
| queue moving. | ||
| </p> | ||
| </div> | ||
| </div> | ||
| <div className="flex flex-col space-y-3 sm:flex-row sm:space-x-4 sm:space-y-0 md:items-center"> | ||
| <Button | ||
| size="lg" | ||
| 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"> | ||
| <a | ||
| href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP_PRO} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="flex w-full items-center justify-center"> | ||
| Start 14-day Free Trial | ||
| <ArrowRight className="ml-2" /> | ||
| </a> | ||
| </Button> | ||
| <span className="text-sm text-center md:text-left text-muted-foreground md:ml-2"> | ||
| (cancel anytime) | ||
| </span> | ||
| </div> | ||
| </div> | ||
| <div className="flex items-center justify-end mx-auto h-full mt-8 lg:mt-0"> | ||
| <div className="md:w-[800px] md:h-[474px] relative overflow-clip"> | ||
| <div className="block"> | ||
| <Image | ||
| src={hero} | ||
| alt="Example of a code review generated by Roo Code PR Reviewer" | ||
| className="max-w-full h-auto" | ||
| width={800} | ||
| height={474} | ||
| /> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </section> | ||
|
|
||
| <section className="relative overflow-hidden border-t border-border py-32"> | ||
| <div className="container relative z-10 mx-auto px-4 sm:px-6 lg:px-8"> | ||
| <div className="mx-auto mb-12 md:mb-24 max-w-5xl text-center"> | ||
| <div> | ||
| <h2 className="text-4xl font-bold tracking-tight sm:text-5xl"> | ||
| Why Roo's PR Reviewer is so much better | ||
| </h2> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className="relative mx-auto md:max-w-[1200px]"> | ||
| <ul className="grid grid-cols-1 place-items-center gap-6 md:grid-cols-2 lg:grid-cols-3 lg:gap-8"> | ||
| {howItWorks.map((feature, index) => { | ||
| const Icon = feature.icon | ||
| return ( | ||
| <li | ||
| key={index} | ||
| className="relative h-full border border-border rounded-2xl bg-background p-8 transition-all duration-300"> | ||
| <Icon className="size-6 text-foreground/80" /> | ||
| <h3 className="mb-3 mt-3 text-xl font-semibold text-foreground"> | ||
| {feature.title} | ||
| </h3> | ||
| <div className="leading-relaxed font-light text-muted-foreground space-y-2"> | ||
| {feature.description} | ||
| </div> | ||
| {feature.logos && ( | ||
| <div className="mt-4 flex flex-wrap items-center gap-4"> | ||
| {feature.logos.map((logo) => ( | ||
| <Image | ||
| key={logo} | ||
| width={20} | ||
| height={20} | ||
| className="w-5 h-5 overflow-clip opacity-50 dark:invert" | ||
| src={`/logos/${logo.toLowerCase()}.svg`} | ||
| alt={`${logo} Logo`} | ||
| /> | ||
| ))} | ||
| </div> | ||
| )} | ||
| </li> | ||
| ) | ||
| })} | ||
| </ul> | ||
| </div> | ||
| </div> | ||
| </section> | ||
|
|
||
| <section className="relative overflow-hidden border-t border-border py-32"> | ||
| <div className="container relative z-10 mx-auto px-4 sm:px-6 lg:px-8"> | ||
| <div className="mx-auto mb-12 max-w-4xl text-center"> | ||
| <div> | ||
| <h2 className="text-4xl font-bold tracking-tight sm:text-5xl"> | ||
| The first member of a whole new team | ||
| </h2> | ||
|
|
||
| <p className="mt-6 text-lg text-muted-foreground"> | ||
| Architecture, coding, reviewing, testing, debugging, documenting, designing –{" "} | ||
| <em>almost everything</em> we do today is mostly through our agents. Now we're | ||
| bringing them to you. | ||
| </p> | ||
| <p className="mt-2 text-lg text-muted-foreground"> | ||
| Roo's PR Reviewer isn't yet another single-purpose tool to add to your already | ||
| complicated stack. | ||
| <br /> | ||
| It's the first member of your AI-powered development team. More agents are shipping | ||
| soon. | ||
| </p> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className="relative mx-auto md:max-w-[1200px]"> | ||
| <AgentCarousel /> | ||
| </div> | ||
| </div> | ||
| </section> | ||
|
|
||
| {/* CTA Section */} | ||
| <section className="py-20"> | ||
| <div className="container mx-auto px-4 sm:px-6 lg:px-8"> | ||
| <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"> | ||
| <h2 className="mb-4 text-3xl font-bold tracking-tight sm:text-4xl">Stop wasting time.</h2> | ||
| <p className="mx-auto mb-8 max-w-2xl text-lg text-muted-foreground"> | ||
| Give Roo Code's PR Reviewer your model key at and turn painful reviews into a tangible | ||
| quality advantage. | ||
| </p> | ||
| <div className="flex flex-col justify-center space-y-4 sm:flex-row sm:space-x-4 sm:space-y-0"> | ||
| <Button | ||
| size="lg" | ||
| 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" | ||
| asChild> | ||
| <a | ||
| href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP_PRO} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="flex items-center justify-center"> | ||
| Start 14-day Free Trial | ||
| <ArrowRight className="ml-2 h-4 w-4" /> | ||
| </a> | ||
| </Button> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </section> | ||
| </> | ||
| ) | ||
| } | ||
125 changes: 125 additions & 0 deletions
125
apps/web-roo-code/src/components/reviewer/agent-carousel.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| "use client" | ||
|
|
||
| import { useEffect } from "react" | ||
| import { motion } from "framer-motion" | ||
| import useEmblaCarousel from "embla-carousel-react" | ||
| import AutoPlay from "embla-carousel-autoplay" | ||
| import { Bug, FileText, Gauge, Languages, Microscope, PocketKnife, TestTube, type LucideIcon } from "lucide-react" | ||
|
|
||
| // AI Agent types for the carousel | ||
| interface AIAgent { | ||
| icon: LucideIcon | ||
| name: string | ||
| } | ||
|
|
||
| const aiAgents: AIAgent[] = [ | ||
| { icon: PocketKnife, name: "Generalist" }, | ||
| { icon: Bug, name: "Bug Fixer" }, | ||
| { icon: TestTube, name: "Test Engineer" }, | ||
| { icon: Microscope, name: "Security Auditor" }, | ||
| { icon: Gauge, name: "Performance Optimizer" }, | ||
| { icon: FileText, name: "Documentation Writer" }, | ||
| { icon: Languages, name: "String Translator" }, | ||
| ] | ||
|
|
||
| export function AgentCarousel() { | ||
| const [emblaRef, emblaApi] = useEmblaCarousel( | ||
| { | ||
| loop: true, | ||
| align: "start", | ||
| watchDrag: true, | ||
| dragFree: false, | ||
| containScroll: false, | ||
| duration: 10000, | ||
| }, | ||
| [ | ||
| AutoPlay({ | ||
| playOnInit: true, | ||
| delay: 0, | ||
| stopOnInteraction: false, | ||
| stopOnMouseEnter: false, | ||
| stopOnFocusIn: false, | ||
| }), | ||
| ], | ||
| ) | ||
|
|
||
| // Continuous scrolling effect | ||
| useEffect(() => { | ||
| if (!emblaApi) return | ||
|
|
||
| const autoPlay = emblaApi?.plugins()?.autoPlay as | ||
| | { | ||
| play?: () => void | ||
| } | ||
| | undefined | ||
|
|
||
| if (autoPlay?.play) { | ||
| autoPlay.play() | ||
| } | ||
|
|
||
| // Set up continuous scrolling | ||
| const interval = setInterval(() => { | ||
| if (emblaApi) { | ||
| emblaApi.scrollNext() | ||
| } | ||
| }, 30) // Smooth continuous scroll | ||
|
|
||
| return () => clearInterval(interval) | ||
| }, [emblaApi]) | ||
|
|
||
| const containerVariants = { | ||
| hidden: { opacity: 0 }, | ||
| visible: { | ||
| opacity: 1, | ||
| transition: { | ||
| duration: 0.6, | ||
| ease: [0.21, 0.45, 0.27, 0.9], | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| // Duplicate the agents array for seamless infinite scroll | ||
| const displayAgents = [...aiAgents, ...aiAgents] | ||
|
|
||
| return ( | ||
| <motion.div | ||
| className="relative -mx-4 md:mx-auto max-w-[1400px]" | ||
| variants={containerVariants} | ||
| initial="hidden" | ||
| whileInView="visible" | ||
| viewport={{ once: true }}> | ||
| {/* Gradient Overlays */} | ||
| <div className="absolute inset-y-0 left-0 z-10 w-[10%] bg-gradient-to-r from-background to-transparent pointer-events-none md:w-[15%]" /> | ||
| <div className="absolute inset-y-0 right-0 z-10 w-[10%] bg-gradient-to-l from-background to-transparent pointer-events-none md:w-[15%]" /> | ||
|
|
||
| {/* Embla Carousel Container */} | ||
| <div className="overflow-hidden" ref={emblaRef}> | ||
| <div className="flex pb-4"> | ||
| {displayAgents.map((agent, index) => { | ||
| const Icon = agent.icon | ||
| return ( | ||
| <div | ||
| key={`${agent.name}-${index}`} | ||
| className="relative min-w-0 flex-[0_0_45%] px-2 md:flex-[0_0_30%] md:px-4 lg:flex-[0_0_15%]"> | ||
| <div className="group relative py-6 cursor-default"> | ||
| <div | ||
| className="relative flex flex-col items-center justify-center rounded-full w-[150px] h-[150px] border border-border bg-background p-6 transition-all duration-500 ease-out shadow-xl | ||
| hover:scale-110 hover:-translate-y-2 | ||
| hover:shadow-[0_20px_50px_rgba(39,110,226,0.25)] dark:hover:shadow-[0_20px_50px_rgba(59,130,246,0.25)]"> | ||
| <Icon | ||
| strokeWidth={1} | ||
| className="size-9 mb-2 text-foreground transition-colors duration-300" | ||
| /> | ||
| <h3 className="text-center leading-tight tracking-tight font-medium text-foreground/90 transition-colors duration-300 dark:text-foreground"> | ||
| {agent.name} | ||
| </h3> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ) | ||
| })} | ||
| </div> | ||
| </div> | ||
| </motion.div> | ||
| ) | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.