Built for modern teams
Everything you need to build, ship, and scale your product. Powerful features that help you move faster.
Lightning Fast
Optimized for speed with edge computing, intelligent caching, and global CDN distribution for instant load times.
Secure by Default
Enterprise-grade security with SOC 2 compliance, end-to-end encryption, and advanced threat protection.
AI-Powered
Leverage cutting-edge AI to automate workflows, boost productivity, and make smarter decisions faster.
Deploy Instantly
Push to production in seconds with zero-downtime deployments, automatic rollbacks, and instant previews.
Global Scale
Serve millions of users worldwide with 99.99% uptime guarantee and automatic scaling infrastructure.
Developer Friendly
Clean APIs, comprehensive documentation, and SDKs for every platform. Built by developers, for developers.
Features
- ✅ Spotlight Effect - Mouse-following gradient reveal on hover
- ✅ Premium Animations - Staggered entrance and smooth transitions
- ✅ Glassmorphism - Modern frosted glass look with backdrop blur
- ✅ Interactive Elements - Hover scaling and clickable CTA links
- ✅ Responsive Grid - Adapts seamlessly from mobile to desktop
- ✅ Rich Content - Support for icons, titles, descriptions, and actions
- ✅ TypeScript Support - Full type safety
- ✅ Customizable - Easy to style and extend via className
Installation
Install dependencies
npm install framer-motion lucide-react clsx tailwind-mergeCopy and paste the following code into your project.
"use client";
import { motion, useMotionTemplate, useMotionValue } from "framer-motion";
import { LucideIcon } from "lucide-react";
import { MouseEvent } from "react";
import { cn } from "@/lib/utils";
interface Feature {
icon: LucideIcon;
title: string;
description: string;
href?: string;
cta?: string;
}
interface FeatureGrid3ColProps {
badge?: string;
headline: string;
description?: string;
features: Feature[];
className?: string;
}
function FeatureCard({ feature, index }: { feature: Feature; index: number }) {
const mouseX = useMotionValue(0);
const mouseY = useMotionValue(0);
function handleMouseMove({ currentTarget, clientX, clientY }: MouseEvent) {
const { left, top } = currentTarget.getBoundingClientRect();
mouseX.set(clientX - left);
mouseY.set(clientY - top);
}
const Icon = feature.icon;
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="group relative border border-zinc-800 bg-zinc-900/50 overflow-hidden rounded-3xl"
onMouseMove={handleMouseMove}
>
<motion.div
className="pointer-events-none absolute -inset-px rounded-3xl opacity-0 transition duration-300 group-hover:opacity-100"
style={{
background: useMotionTemplate`
radial-gradient(
650px circle at ${mouseX}px ${mouseY}px,
rgba(255,255,255,0.1),
transparent 80%
)
`,
}}
/>
<div className="relative h-full p-8">
<div className="mb-6 inline-flex items-center justify-center rounded-xl border border-zinc-800 bg-zinc-900/50 p-3 shadow-lg backdrop-blur-sm transition-transform duration-300 group-hover:scale-110 group-hover:border-zinc-700">
<Icon className="h-6 w-6 text-zinc-100" />
</div>
<h3 className="mb-3 text-xl font-semibold text-zinc-100">
{feature.title}
</h3>
<p className="mb-6 text-zinc-400 leading-relaxed">
{feature.description}
</p>
{feature.cta && (
<div className="flex items-center text-sm font-medium text-zinc-300 transition-colors group-hover:text-white">
{feature.cta}
<svg
className="ml-2 h-4 w-4 transition-transform duration-300 group-hover:translate-x-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M17 8l4 4m0 0l-4 4m4-4H3"
/>
</svg>
</div>
)}
</div>
</motion.div>
);
}
export function FeatureGrid3Col({
badge,
headline,
description,
features,
className,
}: FeatureGrid3ColProps) {
return (
<section
className={cn(
"relative overflow-hidden bg-black py-24 sm:py-32",
className,
)}
>
{/* Background Gradients */}
<div className="absolute inset-0 -z-10">
<div className="absolute left-1/2 top-0 -z-10 h-[1000px] w-[1000px] -translate-x-1/2 rounded-full bg-blue-500/10 blur-[100px]" />
<div className="absolute bottom-0 right-0 -z-10 h-[800px] w-[800px] rounded-full bg-purple-500/10 blur-[100px]" />
</div>
<div className="container mx-auto px-6">
<div className="mx-auto mb-16 max-w-3xl text-center">
{badge && (
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="mb-6 inline-flex"
>
<span className="rounded-full border border-zinc-800 bg-zinc-900/50 px-4 py-1.5 text-sm font-medium text-zinc-300 backdrop-blur-md">
<span className="mr-2 inline-block h-2 w-2 rounded-full bg-blue-500 animate-pulse" />
{badge}
</span>
</motion.div>
)}
<motion.h2
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.1 }}
className="mb-6 text-4xl font-bold tracking-tight text-white sm:text-5xl md:text-6xl"
>
{headline}
</motion.h2>
{description && (
<motion.p
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.2 }}
className="text-lg text-zinc-400 sm:text-xl"
>
{description}
</motion.p>
)}
</div>
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
{features.map((feature, index) => (
<FeatureCard key={index} feature={feature} index={index} />
))}
</div>
</div>
</section>
);
}Usage
Basic Usage
import FeatureGrid3Col from "@/components/ui/feature-grid-3col";
import { Zap, Shield, Sparkles } from "lucide-react";
export default function FeaturesPage() {
return (
<FeatureGrid3Col
headline="Why choose us"
features={[
{
icon: Zap,
title: "Lightning Fast",
description: "Optimized for speed and performance.",
},
{
icon: Shield,
title: "Secure",
description: "Enterprise-grade security built-in.",
},
{
icon: Sparkles,
title: "AI-Powered",
description: "Leverage cutting-edge AI technology.",
},
]}
/>
);
}With Badge and CTAs
<FeatureGrid3Col
badge="Features"
headline="Everything you need to succeed"
description="Powerful features to help you build, ship, and scale your product."
features={[
{
icon: Zap,
title: "Fast",
description: "Super fast.",
cta: "Learn more",
href: "/performance",
},
// ...
]}
/>Props
FeatureGrid3ColProps
| Prop | Type | Default | Description |
|---|---|---|---|
badge | string | undefined | Optional badge text above headline |
headline | string | Required | Main section headline |
description | string | undefined | Optional description below headline |
features | Feature[] | Required | Array of feature objects |
className | string | undefined | Optional class name for the section |
Feature Object
| Prop | Type | Description |
|---|---|---|
icon | LucideIcon | Icon component from lucide-react |
title | string | Feature title |
description | string | Feature description |
cta | string | Optional Call to Action text |
href | string | Optional link URL |
TypeScript Interface
import { LucideIcon } from "lucide-react";
interface Feature {
icon: LucideIcon;
title: string;
description: string;
href?: string;
cta?: string;
}
interface FeatureGrid3ColProps {
badge?: string;
headline: string;
description?: string;
features: Feature[];
className?: string;
}Customization
Adjust Spotlight Size
You can customize the spotlight size by modifying the radial-gradient in the FeatureCard component:
style={{
background: useMotionTemplate`
radial-gradient(
650px circle at ${mouseX}px ${mouseY}px,
rgba(255,255,255,0.1),
transparent 80%
)
`,
}}Change Animation Timing
Adjust the transition prop in the motion.div to change the entrance animation speed or delay:
transition={{ duration: 0.5, delay: index * 0.1 }}Use Cases
Perfect for:
- SaaS Feature sections
- Product capability showcases
- Service offerings
- Benefit displays
- Value propositions
- Technology showcases