Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions apps/web-roo-code/src/app/slack/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import type { Metadata } from "next"

import { StructuredData } from "@/components/structured-data"
import { SEO } from "@/lib/seo"
import { ogImageUrl } from "@/lib/og"

import { SlackHeroSection } from "./slack-hero-section"
import { SlackValuePropsSection } from "./slack-value-props-section"
import { ThreadToFeatureWorkflow } from "./thread-to-feature-workflow"
import { SlackOnboardingSteps } from "./slack-onboarding-steps"
import { SlackCTASection } from "./slack-cta-section"

const TITLE = "Roo Code for Slack"
const DESCRIPTION =
"Summon agents to explain code, plan new features, or execute coding tasks without leaving Slack. Your AI team in your team's workspace."
const OG_DESCRIPTION = "@Roomote: Your AI Team in Slack"
const PATH = "/slack"

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: ogImageUrl(TITLE, OG_DESCRIPTION),
width: 1200,
height: 630,
alt: TITLE,
},
],
locale: SEO.locale,
type: "website",
},
twitter: {
card: SEO.twitterCard,
title: TITLE,
description: DESCRIPTION,
images: [ogImageUrl(TITLE, OG_DESCRIPTION)],
},
keywords: [
...SEO.keywords,
"Slack integration",
"team collaboration",
"Slack bot",
"AI Slack assistant",
"@Roomote",
"Slack agents",
],
}

export default function SlackPage() {
return (
<>
<StructuredData />
<SlackHeroSection />
<SlackValuePropsSection />
<ThreadToFeatureWorkflow />
<SlackOnboardingSteps />
<SlackCTASection />
</>
)
}
36 changes: 36 additions & 0 deletions apps/web-roo-code/src/app/slack/slack-cta-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ArrowRight } from "lucide-react"

import { Button } from "@/components/ui"
import { EXTERNAL_LINKS } from "@/lib/constants"

export function SlackCTASection() {
return (
<section className="py-24">
<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-violet-500/10 via-purple-500/5 to-blue-500/5 p-8 text-center shadow-2xl backdrop-blur-xl dark:border-white/10 sm:p-16">
<h2 className="mb-6 text-3xl font-bold tracking-tight sm:text-4xl">
Start using Roo Code in Slack
</h2>
<p className="mx-auto mb-10 max-w-2xl text-lg text-muted-foreground">
Start with a free 14-day Team Plan trial.
</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-foreground text-background hover:bg-foreground/90 transition-all duration-300"
asChild>
<a
href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center">
Get Started
<ArrowRight className="ml-2 h-4 w-4" />
</a>
</Button>
</div>
</div>
</div>
</section>
)
}
48 changes: 48 additions & 0 deletions apps/web-roo-code/src/app/slack/slack-hero-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ArrowRight, ExternalLink } from "lucide-react"

import { Button } from "@/components/ui"
import { AnimatedBackground } from "@/components/homepage"
import { EXTERNAL_LINKS } from "@/lib/constants"

export function SlackHeroSection() {
return (
<section className="relative flex pt-32 pb-20 items-center overflow-hidden">
<AnimatedBackground />
<div className="container relative flex flex-col items-center h-full z-10 mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center max-w-4xl mx-auto mb-12">
<h1 className="text-4xl font-bold tracking-tight mb-6 md:text-5xl lg:text-6xl">
<span className="text-violet-500">@Roomote</span>: Your AI Team in Slack
</h1>
<p className="text-xl text-muted-foreground mb-8 max-w-2xl mx-auto">
Summon agents to explain code, plan new features, or execute coding tasks without leaving Slack.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button
size="xl"
className="bg-violet-600 hover:bg-violet-700 text-white transition-all duration-300 shadow-lg hover:shadow-violet-500/25"
asChild>
<a
href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center">
Get Started
<ArrowRight className="ml-2 size-5" />
</a>
</Button>
<Button variant="outline" size="xl" className="backdrop-blur-sm" asChild>
<a
href={EXTERNAL_LINKS.SLACK_INTEGRATION_DOCS}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center">
Read the Docs
<ExternalLink className="ml-2 size-4" />
</a>
</Button>
</div>
</div>
</div>
</section>
)
}
104 changes: 104 additions & 0 deletions apps/web-roo-code/src/app/slack/slack-onboarding-steps.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { Settings, Link2, Hash, CreditCard, LucideIcon } from "lucide-react"

import { EXTERNAL_LINKS } from "@/lib/constants"

interface OnboardingStep {
step: number
icon: LucideIcon
title: string
description: string
link?: {
href: string
text: string
}
}

const onboardingSteps: OnboardingStep[] = [
{
step: 1,
icon: CreditCard,
title: "Get a Team Plan",
description: "Slack requires a Team Plan.",
link: {
href: EXTERNAL_LINKS.CLOUD_APP_TEAM_TRIAL,
text: "Start a free 14-day trial",
},
},
{
step: 2,
icon: Settings,
title: "Connect Slack",
description: 'Go to Organization Settings and click "Connect" under Integrations.',
},
{
step: 3,
icon: Link2,
title: "Authorize",
description: "Complete the OAuth flow to connect your workspace.",
},
{
step: 4,
icon: Hash,
title: "Add to channels",
description: "Add @Roomote to the channels where you want it available.",
},
]

export function SlackOnboardingSteps() {
return (
<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="absolute inset-y-0 left-1/2 h-full w-full max-w-[1200px] -translate-x-1/2 z-1">
<div className="absolute left-1/2 top-1/2 h-[400px] w-full -translate-x-1/2 -translate-y-1/2 rounded-full bg-blue-500/10 dark:bg-blue-700/20 blur-[140px]" />
</div>

<div className="mx-auto mb-12 md:mb-24 max-w-5xl text-center">
<div>
<h2 className="text-3xl font-bold tracking-tight sm:text-5xl mb-4">Get started in minutes</h2>
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
Connect your Slack workspace and start working with AI agents.
</p>
</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-4 lg:gap-8">
{onboardingSteps.map((step) => {
const Icon = step.icon
return (
<li
key={step.step}
className="relative h-full w-full border border-border rounded-2xl bg-background p-8 transition-all duration-300 hover:shadow-lg">
<div className="flex items-center gap-3 mb-3">
<div className="bg-violet-100 dark:bg-violet-900/20 w-10 h-10 rounded-full flex items-center justify-center">
<span className="text-violet-600 dark:text-violet-400 font-bold">
{step.step}
</span>
</div>
<Icon className="size-5 text-foreground/60" />
</div>
<h3 className="mb-3 text-xl font-semibold text-foreground">{step.title}</h3>
<div className="leading-relaxed font-light text-muted-foreground">
{step.description}
{step.link && (
<>
{" "}
<a
href={step.link.href}
target="_blank"
rel="noopener noreferrer"
className="text-violet-600 dark:text-violet-400 hover:underline">
{step.link.text}
</a>
</>
)}
</div>
</li>
)
})}
</ul>
</div>
</div>
</section>
)
}
80 changes: 80 additions & 0 deletions apps/web-roo-code/src/app/slack/slack-value-props-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { MessageSquare, Brain, GitBranch, Users, GraduationCap, Shield, LucideIcon } from "lucide-react"

interface ValueProp {
icon: LucideIcon
title: string
description: string
}

const valueProps: ValueProp[] = [
{
icon: MessageSquare,
title: "Discussion to feature.",
description:
"Your team discusses a feature in Slack. @Roomote turns the discussion into a plan. Then builds it. All without leaving the conversation.",
},
{
icon: Brain,
title: "Full thread context.",
description:
"@Roomote reads the conversation before responding. Ask 'why is this happening?' after a team discussion and it understands.",
},
{
icon: GitBranch,
title: "Chain agents together.",
description:
"Start with a Planner to spec it out. Then call the Coder to build it. Multi-step workflows, one Slack thread.",
},
{
icon: Users,
title: "Anyone can contribute.",
description:
"PMs, CSMs, and Sales can ask @Roomote to explain code, prototype features, or build internal tools. No engineering bottleneck.",
},
{
icon: GraduationCap,
title: "Team learning, built in.",
description: "Public channel mentions show everyone how to leverage agents. Learn by watching.",
},
{
icon: Shield,
title: "Safe by design.",
description: "Agents never touch main/master directly. They produce branches and PRs. You approve.",
},
]

export function SlackValuePropsSection() {
return (
<section className="py-24 bg-muted/30">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 relative">
<div className="absolute inset-y-0 left-1/2 h-full w-full max-w-[1200px] -translate-x-1/2 z-1">
<div className="absolute left-1/2 top-1/2 h-[800px] w-full -translate-x-1/2 -translate-y-1/2 rounded-full bg-violet-500/10 dark:bg-violet-700/20 blur-[140px]" />
</div>
<div className="text-center mb-16">
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
Why teams love working with @Roomote
</h2>
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
AI agents that understand context, chain together for complex work, and keep you in control.
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 max-w-6xl mx-auto relative">
{valueProps.map((prop, index) => {
const Icon = prop.icon
return (
<div
key={index}
className="bg-background p-8 rounded-2xl border border-border hover:shadow-lg transition-all duration-300">
<div className="bg-violet-100 dark:bg-violet-900/20 w-12 h-12 rounded-lg flex items-center justify-center mb-6">
<Icon className="size-6 text-violet-600 dark:text-violet-400" />
</div>
<h3 className="text-xl font-semibold mb-3">{prop.title}</h3>
<p className="text-muted-foreground leading-relaxed">{prop.description}</p>
</div>
)
})}
</div>
</div>
</section>
)
}
Loading
Loading