Developer-First Infrastructure
A complete toolkit for building modern applications. Scalable, secure, and designed for developer productivity.
Edge Functions
Run code at the edge with zero cold starts and global distribution.
Global Database
Serverless database with automatic replication and instant branching.
Enterprise Auth
Secure authentication with SAML, SSO, and MFA out of the box.
Auto-Scaling
Infrastructure that scales automatically with your traffic spikes.
Preview Deploys
Automatic preview environments for every pull request you make.
Instant Rollbacks
Revert to any previous deployment version in milliseconds.
Serverless Compute
Run complex workloads without managing a single server.
Global CDN
Deliver content faster with our intelligent global edge network.
Installation
Copy and paste the following code into your project.
"use client";
import { motion, useMotionTemplate, useMotionValue } from "framer-motion";
import { ArrowRight, LucideIcon } from "lucide-react";
import { MouseEvent } from "react";
import { cn } from "@/lib/utils";
interface Feature {
icon: LucideIcon;
title: string;
description: string;
badge?: string;
href?: string;
cta?: string;
}
interface FeatureGrid4ColProps {
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.05 }}
className="group relative h-full"
onMouseMove={handleMouseMove}
>
<div className="relative h-full overflow-hidden rounded-2xl border border-zinc-800 bg-zinc-900/30 p-6 transition-colors hover:bg-zinc-900/50">
{/* Hover Glow Effect */}
<motion.div
className="pointer-events-none absolute -inset-px opacity-0 transition duration-300 group-hover:opacity-100"
style={{
background: useMotionTemplate`
radial-gradient(
350px circle at ${mouseX}px ${mouseY}px,
rgba(59, 130, 246, 0.1),
transparent 80%
)
`,
}}
/>
{/* Border Gradient on Hover */}
<motion.div
className="pointer-events-none absolute -inset-px rounded-2xl opacity-0 transition duration-300 group-hover:opacity-100"
style={{
background: useMotionTemplate`
radial-gradient(
600px circle at ${mouseX}px ${mouseY}px,
rgba(59, 130, 246, 0.4),
transparent 40%
)
`,
maskImage:
"linear-gradient(black, black) content-box, linear-gradient(black, black)",
maskComposite: "exclude",
WebkitMaskComposite: "xor",
padding: "1px",
}}
/>
<div className="relative z-10 flex h-full flex-col">
<div className="mb-4 flex items-center justify-between">
<div className="inline-flex items-center justify-center rounded-lg bg-zinc-800/50 p-2 ring-1 ring-white/10 transition-transform duration-300 group-hover:scale-110 group-hover:bg-blue-500/20 group-hover:ring-blue-500/50">
<Icon className="h-5 w-5 text-zinc-300 transition-colors group-hover:text-blue-400" />
</div>
{feature.badge && (
<span className="rounded-full bg-blue-500/10 px-2 py-0.5 text-xs font-medium text-blue-400 ring-1 ring-blue-500/20">
{feature.badge}
</span>
)}
</div>
<h3 className="mb-2 text-lg font-semibold text-white transition-colors group-hover:text-blue-100">
{feature.title}
</h3>
<p className="mb-6 flex-grow text-sm leading-relaxed text-zinc-400">
{feature.description}
</p>
{feature.cta && (
<div className="flex items-center text-xs font-medium text-zinc-500 transition-colors group-hover:text-blue-400">
{feature.cta}
<ArrowRight className="ml-1 h-3 w-3 transition-transform group-hover:translate-x-1" />
</div>
)}
</div>
</div>
</motion.div>
);
}
export function FeatureGrid4Col({
badge,
headline,
description,
features,
className,
}: FeatureGrid4ColProps) {
return (
<section
className={cn(
"relative overflow-hidden bg-black py-24 sm:py-32",
className,
)}
>
{/* Background Pattern */}
<div className="absolute inset-0 -z-10 h-full w-full bg-[linear-gradient(to_right,#8080800a_1px,transparent_1px),linear-gradient(to_bottom,#8080800a_1px,transparent_1px)] bg-[size:24px_24px]" />
<div className="absolute left-0 right-0 top-0 -z-10 m-auto h-[310px] w-[310px] rounded-full bg-blue-500/20 opacity-20 blur-[100px]" />
<div className="container mx-auto px-4 md: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-4 inline-flex items-center rounded-full border border-zinc-800 bg-zinc-900/50 px-3 py-1 text-sm font-medium text-zinc-300 backdrop-blur-md"
>
<span className="mr-2 h-1.5 w-1.5 rounded-full bg-blue-500 animate-pulse" />
{badge}
</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-4 text-3xl font-bold tracking-tight text-white sm:text-4xl md:text-5xl"
>
{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="mx-auto max-w-2xl text-lg text-zinc-400"
>
{description}
</motion.p>
)}
</div>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
{features.map((feature, index) => (
<FeatureCard key={index} feature={feature} index={index} />
))}
</div>
</div>
</section>
);
}Update the import paths to match your project setup.
Features
- ✅ Professional design - Clean cards with elegant spacing
- ✅ Gradient icons - Beautiful gradient backgrounds for all icons
- ✅ Optional metrics - Show growth stats (e.g., "+127%")
- ✅ Feature badges - "Popular", "New", "Enterprise" labels
- ✅ Interactive links - "Learn more" links with hover effects
- ✅ Hover animations - Icon scales, card lifts, gradient reveals
- ✅ Bottom CTA card - Professional call-to-action section
- ✅ Responsive grid - 4 columns → 2 columns → 1 column
- ✅ Shadcn components - Built with Card, Badge, Button
- ✅ TypeScript support - Full type safety
- ✅ Production-ready - Copy and paste to use
Usage
Basic Usage
import FeatureGrid4Col from "@/components/ui/feature-grid-4col";
import { Terminal, Database, Cloud } from "lucide-react";
export default function FeaturesPage() {
return (
<FeatureGrid4Col
headline="Platform Features"
features={[
{
icon: Terminal,
title: "Edge Functions",
description: "Run code at the edge globally.",
},
{
icon: Database,
title: "Database",
description: "Serverless storage for your data.",
},
// ... more features
]}
/>
);
}With Badges and CTAs
<FeatureGrid4Col
badge="New"
headline="Advanced Capabilities"
description="Explore our latest features designed for scale."
features={[
{
icon: Cloud,
title: "Auto-Scaling",
description: "Scale automatically with traffic.",
badge: "Beta",
cta: "Learn more",
href: "/scaling",
},
// ...
]}
/>Props
FeatureGrid4ColProps
| 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 |
badge | string | Optional small badge on the card |
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;
badge?: string;
href?: string;
cta?: string;
}
interface FeatureGrid4ColProps {
badge?: string;
headline: string;
description?: string;
features: Feature[];
className?: string;
}Customization
import { Card } from "@/components/ui/card";
<Card className="rounded-2xl border-2 p-8 hover:shadow-2xl">
{/* content */}
</Card>;Hide CTA Section
Simply omit the cta prop:
<FeatureGrid4Col
headline="Features"
features={
[
/* ... */
]
}
// No cta prop
/>Use Cases
Perfect for:
- Product feature pages
- SaaS platform capabilities
- Service offerings
- Tool comparisons
- Benefits sections
- Technology showcases
- Integration displays
- API features
Best Practices
- Optimal feature count - 8-12 features work best for 4-column layout
- Use metrics wisely - Only add metrics where relevant (growth, speed, etc.)
- Badge sparingly - Highlight 2-3 key features with badges
- Consistent descriptions - Keep similar length (1-2 sentences)
- Relevant icons - Choose icons that clearly represent the feature
- Test interactions - Ensure all links and CTAs work properly
- Mobile optimization - Test on mobile devices