feat(web): add Valentines Day theme to homepage

This commit is contained in:
Roo Code 2026-02-04 23:44:44 +00:00
parent 1da2b1c457
commit 76a13a1e87
6 changed files with 213 additions and 11 deletions

View file

@ -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;
}

View file

@ -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()
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">

View file

@ -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
@ -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 />

View file

@ -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>
)
}

View file

@ -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"

View file

@ -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)
// 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>
)
}