Skip to content
Draft
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
45 changes: 45 additions & 0 deletions apps/web-roo-code/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,48 @@
@apply bg-background text-foreground;
}
}

/* Valentine's Day Theme Animations */
@keyframes heartbeat {
0%,
100% {
transform: scale(1);
}
15% {
transform: scale(1.2);
}
30% {
transform: scale(1);
}
45% {
transform: scale(1.15);
}
60% {
transform: scale(1);
}
}

@keyframes float-up {
0% {
transform: translateY(0) rotate(0deg);
opacity: 0;
}
10% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
transform: translateY(-100vh) rotate(360deg);
opacity: 0;
}
}

.animate-heartbeat {
animation: heartbeat 1.5s ease-in-out infinite;
}

.animate-float-up {
animation: float-up linear infinite;
}
76 changes: 62 additions & 14 deletions apps/web-roo-code/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,81 @@ import {
OptionOverviewSection,
PillarsSection,
UseExamplesSection,
FloatingHearts,
} from "@/components/homepage"
import { EXTERNAL_LINKS } from "@/lib/constants"
import { ArrowRight } from "lucide-react"
import { ArrowRight, Heart } from "lucide-react"
import { StructuredData } from "@/components/structured-data"

// Invalidate cache when a request comes in, at most once every hour.
export const revalidate = 3600

// Check if current date is Valentine's season (Feb 1-15)
function isValentinesSeason() {
const now = new Date()
const month = now.getMonth() // 0-indexed, so February is 1
const day = now.getDate()
return month === 1 && day >= 1 && day <= 15
}

export default async function Home() {
const isValentines = isValentinesSeason()
Comment on lines 17 to +28
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server-side isValentinesSeason() check is cached for up to 1 hour (revalidate = 3600), while client components (ValentinesBanner, FloatingHearts) independently check the date in real-time via useEffect. At date boundaries (Jan 31 -> Feb 1 or Feb 15 -> Feb 16), this can cause visual inconsistency where the background glow color (server-determined) doesn't match the banner/hearts visibility (client-determined). Consider passing the server-calculated isValentines value as a prop to client components, or accept this as an acceptable edge case at date boundaries.

Fix it with Roo Code or mention @roomote and request a fix.


return (
<>
<StructuredData />
<FloatingHearts />
<section className="relative flex flex-col items-center overflow-hidden pt-20 pb-12 md:pt-32 md:pb-16">
<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-violet-500/10 dark:bg-violet-700/20 blur-[140px]" />
<div
className={`absolute left-1/2 top-1/2 h-[400px] w-full -translate-x-1/2 -translate-y-1/2 rounded-full blur-[140px] ${
isValentines
? "bg-rose-500/15 dark:bg-rose-600/25"
: "bg-violet-500/10 dark:bg-violet-700/20"
}`}
/>
</div>
<div className="container relative z-10 mx-auto px-4 sm:px-6 lg:px-8 flex flex-col items-center text-center">
<h1 className="text-3xl md:text-4xl font-bold tracking-tight text-foreground max-w-4xl mb-6">
Your AI Software Engineering Team is here.
<br />
<span className="text-muted-foreground">Interactive in the IDE, autonomous in the cloud.</span>
{isValentines ? (
<>
<span className="inline-flex items-center gap-2">
Fall in{" "}
<Heart className="inline size-8 md:size-10 text-rose-500 fill-rose-500 animate-heartbeat" />{" "}
with coding again.
</span>
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-pink-500 via-rose-500 to-red-500">
Your AI pair that truly cares.
</span>
</>
) : (
<>
Your AI Software Engineering Team is here.
<br />
<span className="text-muted-foreground">
Interactive in the IDE, autonomous in the cloud.
</span>
</>
)}
</h1>
<div className="mt-2 max-w-3xl text-lg text-muted-foreground mb-10 space-y-3">
<p>
Use the <strong className="text-nowrap">Roo Code Extension</strong> on your computer for
full control, or delegate work to your{" "}
<strong className="text-nowrap">Roo Code Cloud Agents</strong> from the web, Slack, Github
or wherever your team is.
</p>
{isValentines ? (
<p>
This Valentine&apos;s season, let{" "}
<strong className="text-rose-500 text-nowrap">Roo Code</strong> be your perfect coding
companion. Use the <strong className="text-nowrap">Extension</strong> for hands-on
collaboration, or let your <strong className="text-nowrap">Cloud Agents</strong> handle
the heavy lifting while you focus on what you love.
</p>
) : (
<p>
Use the <strong className="text-nowrap">Roo Code Extension</strong> on your computer for
full control, or delegate work to your{" "}
<strong className="text-nowrap">Roo Code Cloud Agents</strong> from the web, Slack,
Github or wherever your team is.
</p>
)}
</div>
<div className="flex flex-col sm:flex-row gap-4 mb-16">
<div className="flex flex-col items-center gap-2">
Expand Down Expand Up @@ -65,9 +111,11 @@ export default async function Home() {
</div>
</div>

<div className="mb-12 px-4">
<CompanyLogos />
</div>
{!isValentines && (
<div className="mb-12 px-4">
<CompanyLogos />
</div>
)}
</div>
</section>

Expand Down
2 changes: 2 additions & 0 deletions apps/web-roo-code/src/app/shell.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getGitHubStars, getVSCodeDownloads } from "@/lib/stats"

import { NavBar, Footer } from "@/components/chromes"
import { ValentinesBanner } from "@/components/homepage"

// Invalidate cache when a request comes in, at most once every hour.
export const revalidate = 3600
Expand All @@ -10,6 +11,7 @@ export default async function Shell({ children }: { children: React.ReactNode })

return (
<div className="flex min-h-screen flex-col bg-background text-foreground">
<ValentinesBanner />
<NavBar stars={stars} downloads={downloads} />
<main className="flex-1">{children}</main>
<Footer />
Expand Down
61 changes: 61 additions & 0 deletions apps/web-roo-code/src/components/homepage/floating-hearts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"use client"

import { useEffect, useState } from "react"

interface FloatingHeart {
id: number
left: number
size: number
duration: number
delay: number
opacity: number
}

export function FloatingHearts() {
const [hearts, setHearts] = useState<FloatingHeart[]>([])
const [isVisible, setIsVisible] = useState(true)

useEffect(() => {
// Check if we're in the Valentine's date range (Feb 1-15)
const now = new Date()
const month = now.getMonth() // 0-indexed, so February is 1
const day = now.getDate()
const isValentinesSeason = month === 1 && day >= 1 && day <= 15
setIsVisible(isValentinesSeason)

if (!isValentinesSeason) return

// Generate random hearts
const generatedHearts: FloatingHeart[] = Array.from({ length: 15 }, (_, i) => ({
id: i,
left: Math.random() * 100,
size: 12 + Math.random() * 16,
duration: 8 + Math.random() * 12,
delay: Math.random() * 10,
opacity: 0.1 + Math.random() * 0.2,
}))
setHearts(generatedHearts)
}, [])

if (!isVisible || hearts.length === 0) return null

return (
<div className="pointer-events-none fixed inset-0 z-0 overflow-hidden" aria-hidden="true">
{hearts.map((heart) => (
<div
key={heart.id}
className="absolute animate-float-up text-rose-500/50 dark:text-rose-400/30"
style={{
left: `${heart.left}%`,
bottom: "-50px",
fontSize: `${heart.size}px`,
animationDuration: `${heart.duration}s`,
animationDelay: `${heart.delay}s`,
opacity: heart.opacity,
}}>
</div>
))}
</div>
)
}
2 changes: 2 additions & 0 deletions apps/web-roo-code/src/components/homepage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ export * from "./cloud-section"
export * from "./ecosystem-section"
export * from "./cta-section"
export * from "./use-examples-section"
export * from "./valentines-banner"
export * from "./floating-hearts"
46 changes: 46 additions & 0 deletions apps/web-roo-code/src/components/homepage/valentines-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use client"

import { Heart, Sparkles } from "lucide-react"
import { useEffect, useState } from "react"

export function ValentinesBanner() {
const [isVisible, setIsVisible] = useState(true)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initializing isVisible to true causes the banner to render on the server and during initial hydration. Outside Valentine's season (before Feb 1 or after Feb 15), the banner will flash briefly then disappear when the useEffect runs, causing both a visual flash and a layout shift as content below moves up. Consider initializing to false so the banner only appears after the date check confirms it's Valentine's season.

Suggested change
const [isVisible, setIsVisible] = useState(true)
const [isVisible, setIsVisible] = useState(false)

Fix it with Roo Code or mention @roomote and request a fix.


// Check if we're in the Valentine's date range (Feb 1-15)
useEffect(() => {
const now = new Date()
const month = now.getMonth() // 0-indexed, so February is 1
const day = now.getDate()
// Show banner from Feb 1-15
const isValentinesSeason = month === 1 && day >= 1 && day <= 15
setIsVisible(isValentinesSeason)
}, [])

if (!isVisible) return null

return (
<div className="relative overflow-hidden bg-gradient-to-r from-pink-500 via-rose-500 to-red-500 py-2.5 text-white">
{/* Animated sparkles background */}
<div className="absolute inset-0 overflow-hidden">
{[...Array(6)].map((_, i) => (
<Sparkles
key={i}
className="absolute animate-pulse text-white/30"
style={{
left: `${15 + i * 15}%`,
top: `${20 + (i % 3) * 20}%`,
animationDelay: `${i * 0.3}s`,
transform: `scale(${0.6 + (i % 3) * 0.2})`,
}}
/>
))}
</div>

<div className="container relative mx-auto flex items-center justify-center gap-3 px-4 text-center text-sm font-medium">
<Heart className="size-4 animate-heartbeat fill-current" />
<span>Happy Valentine&apos;s Day! Spread the love and build something amazing with Roo Code</span>
<Heart className="size-4 animate-heartbeat fill-current" style={{ animationDelay: "0.5s" }} />
</div>
</div>
)
}
Loading