20 Integrations
Integrations
Connect with the tools you already use
Coming Soon
Airtable
Build custom workflows with your data
Productivity
Available soon
Coming Soon
Linear
Streamline issue tracking and project management
Development
Available soon
Coming Soon
Discord
Get updates in your Discord server
Communication
Available soon
Don't see your tool?
We're always adding new integrations. Let us know what you need.
Request an integrationInstallation
Install dependencies
npm install lucide-reactCopy and paste the following code into your project.
"use client";
import React, { useState } from "react";
import { Sparkles, ArrowRight, Zap } from "lucide-react";
interface Integration {
id: string;
name: string;
description: string;
logo: string;
category: string;
comingSoon?: boolean;
popular?: boolean;
href?: string;
}
interface IntegrationGridProps {
title?: string;
description?: string;
integrations: Integration[];
categories?: string[];
showFilter?: boolean;
className?: string;
}
export function IntegrationGrid({
title = "Integrations",
description = "Connect with the tools you already use",
integrations,
categories = [],
showFilter = true,
className = "",
}: IntegrationGridProps) {
const [selectedCategory, setSelectedCategory] = useState<string>("all");
const allCategories = categories.length
? categories
: Array.from(new Set(integrations.map((i) => i.category)));
const filteredIntegrations =
selectedCategory === "all"
? integrations
: integrations.filter((i) => i.category === selectedCategory);
return (
<section className={`relative w-full overflow-hidden py-24 ${className}`}>
<div className="absolute inset-0 -z-10 bg-gradient-to-b from-slate-50/50 via-white to-white dark:from-slate-950/20 dark:via-zinc-950 dark:to-zinc-950" />
<div className="absolute left-1/4 top-0 -z-10 h-96 w-96 rounded-full bg-gradient-to-br from-slate-400/10 to-zinc-400/10 blur-3xl" />
<div className="absolute bottom-0 right-1/4 -z-10 h-96 w-96 rounded-full bg-gradient-to-br from-zinc-400/10 to-slate-400/10 blur-3xl" />
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="mb-12 text-center">
<div className="mb-4 inline-flex items-center gap-2 rounded-full border border-zinc-200 bg-zinc-50 px-4 py-1.5 text-sm font-semibold text-zinc-700 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-300">
<Zap className="h-4 w-4" />
{filteredIntegrations.length} Integrations
</div>
<h2 className="mb-4 text-4xl font-bold tracking-tight text-zinc-900 dark:text-white sm:text-5xl">
{title}
</h2>
<p className="mx-auto max-w-2xl text-lg text-zinc-600 dark:text-zinc-400">
{description}
</p>
</div>
{showFilter && allCategories.length > 0 && (
<div className="mb-12 flex flex-wrap justify-center gap-2">
<button
onClick={() => setSelectedCategory("all")}
className={`rounded-lg px-4 py-2 text-sm font-semibold transition-all ${
selectedCategory === "all"
? "bg-zinc-900 text-white shadow-lg dark:bg-white dark:text-zinc-900"
: "bg-white text-zinc-700 hover:bg-zinc-50 dark:bg-zinc-800 dark:text-zinc-300 dark:hover:bg-zinc-700"
}`}
>
All
</button>
{allCategories.map((category) => (
<button
key={category}
onClick={() => setSelectedCategory(category)}
className={`rounded-lg px-4 py-2 text-sm font-semibold transition-all ${
selectedCategory === category
? "bg-zinc-900 text-white shadow-lg dark:bg-white dark:text-zinc-900"
: "bg-white text-zinc-700 hover:bg-zinc-50 dark:bg-zinc-800 dark:text-zinc-300 dark:hover:bg-zinc-700"
}`}
>
{category}
</button>
))}
</div>
)}
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{filteredIntegrations.map((integration, index) => (
<div
key={integration.id}
className="group relative overflow-hidden rounded-2xl border border-zinc-200/50 bg-white/80 p-6 backdrop-blur-sm transition-all hover:border-zinc-300 hover:shadow-2xl dark:border-zinc-800/50 dark:bg-zinc-900/80 dark:hover:border-zinc-700"
style={{
animationDelay: `${index * 50}ms`,
}}
>
<div className="absolute inset-0 -z-10 bg-gradient-to-br from-zinc-500/5 via-slate-500/5 to-transparent opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
{integration.popular && (
<div className="absolute right-4 top-4 z-10">
<span className="inline-flex items-center gap-1 rounded-full bg-zinc-900 px-2.5 py-1 text-xs font-bold text-white shadow-lg dark:bg-white dark:text-zinc-900">
<Sparkles className="h-3 w-3" />
Popular
</span>
</div>
)}
{integration.comingSoon && (
<div className="absolute right-4 top-4 z-10">
<span className="inline-flex items-center rounded-full border border-zinc-300 bg-white/90 px-2.5 py-1 text-xs font-semibold text-zinc-700 backdrop-blur-sm dark:border-zinc-700 dark:bg-zinc-800/90 dark:text-zinc-300">
Coming Soon
</span>
</div>
)}
<div className="relative mb-4">
<div className="flex h-20 w-20 items-center justify-center rounded-2xl border border-zinc-200/50 bg-gradient-to-br from-white to-zinc-50 p-4 shadow-sm transition-all group-hover:scale-110 group-hover:shadow-lg dark:border-zinc-800/50 dark:from-zinc-900 dark:to-zinc-800">
<img
src={integration.logo}
alt={`${integration.name} logo`}
className="h-full w-full object-contain"
/>
</div>
<div className="absolute inset-0 -z-10 rounded-2xl bg-gradient-to-br from-zinc-400/20 to-slate-400/20 opacity-0 blur-xl transition-opacity duration-500 group-hover:opacity-100" />
</div>
<div className="mb-4">
<h3 className="mb-2 text-lg font-bold text-zinc-900 dark:text-white">
{integration.name}
</h3>
<p className="text-sm leading-relaxed text-zinc-600 dark:text-zinc-400">
{integration.description}
</p>
</div>
<div className="mb-4">
<span className="inline-block rounded-lg border border-zinc-200 bg-zinc-50 px-3 py-1 text-xs font-medium text-zinc-700 dark:border-zinc-800 dark:bg-zinc-800 dark:text-zinc-300">
{integration.category}
</span>
</div>
{integration.href && !integration.comingSoon && (
<a
href={integration.href}
className="inline-flex items-center gap-2 text-sm font-semibold text-zinc-900 transition-colors hover:text-zinc-600 dark:text-white dark:hover:text-zinc-300"
>
Learn more
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</a>
)}
{integration.comingSoon && (
<div className="text-sm font-semibold text-zinc-400 dark:text-zinc-600">
Available soon
</div>
)}
<div className="absolute bottom-0 left-0 h-1 w-full scale-x-0 bg-gradient-to-r from-zinc-600 via-zinc-800 to-zinc-900 transition-transform duration-500 group-hover:scale-x-100 dark:from-zinc-400 dark:via-zinc-300 dark:to-white" />
</div>
))}
</div>
{filteredIntegrations.length === 0 && (
<div className="py-12 text-center">
<p className="text-zinc-600 dark:text-zinc-400">
No integrations found in this category.
</p>
</div>
)}
<div className="mt-16 rounded-2xl border border-zinc-200 bg-gradient-to-br from-zinc-50 to-slate-50 p-8 text-center dark:border-zinc-800 dark:from-zinc-900 dark:to-zinc-950">
<h3 className="mb-2 text-xl font-bold text-zinc-900 dark:text-white">
Don't see your tool?
</h3>
<p className="mb-6 text-sm text-zinc-600 dark:text-zinc-400">
We're always adding new integrations. Let us know what you need.
</p>
<a
href="#"
className="inline-flex items-center gap-2 rounded-lg bg-zinc-900 px-6 py-3 text-sm font-semibold text-white shadow-lg transition-all hover:bg-zinc-800 hover:shadow-xl dark:bg-white dark:text-zinc-900 dark:hover:bg-zinc-100"
>
Request an integration
<ArrowRight className="h-4 w-4" />
</a>
</div>
</div>
</section>
);
}Features
- ✅ Professional design - Clean monochrome/grayscale theme
- ✅ Category filtering - Filter integrations by category
- ✅ Popular badges - Highlight most-used integrations
- ✅ Coming soon tags - Show upcoming integrations
- ✅ Hover effects - Subtle glow and scale animations
- ✅ Responsive grid - 1-2-3-4 column layout
- ✅ Logo support - Display integration logos with glow effect
- ✅ External links - Link to integration docs
- ✅ Empty states - Handle no results gracefully
- ✅ CTA section - Request new integrations
- ✅ Dark mode ready - Beautiful in both themes
Usage
Basic Usage
import IntegrationGrid from "@/components/ui/integration-grid";
const integrations = [
{
id: "1",
name: "Slack",
description: "Get notifications in your Slack workspace",
logo: "/logos/slack.svg",
category: "Communication",
popular: true,
href: "/integrations/slack",
},
{
id: "2",
name: "Stripe",
description: "Accept payments seamlessly",
logo: "/logos/stripe.svg",
category: "Payments",
popular: true,
href: "/integrations/stripe",
},
];
export default function Page() {
return <IntegrationGrid integrations={integrations} />;
}With Category Filter
<IntegrationGrid
title="Integrations"
description="Connect with the tools you already use"
integrations={integrations}
categories={["Communication", "Payments", "Development", "CRM"]}
showFilter={true}
/>Coming Soon Integrations
const integrations = [
{
id: "1",
name: "Linear",
description: "Streamline issue tracking",
logo: "/logos/linear.svg",
category: "Development",
comingSoon: true, // Shows "Coming Soon" badge
},
];Props
IntegrationGridProps
| Prop | Type | Default | Description |
|---|---|---|---|
integrations | Integration[] | Required | Array of integrations |
title | string | "Integrations" | Section title |
description | string | "Connect with the tools..." | Section description |
categories | string[] | Auto-extracted | Category filter options |
showFilter | boolean | true | Show category filter |
className | string | "" | Additional CSS classes |
Integration
| Prop | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier |
name | string | Yes | Integration name |
description | string | Yes | Short description |
logo | string | Yes | Logo URL or path |
category | string | Yes | Category name |
popular | boolean | No | Show "Popular" badge |
comingSoon | boolean | No | Show "Coming Soon" badge |
href | string | No | Link to integration page |
TypeScript Interface
interface Integration {
id: string;
name: string;
description: string;
logo: string;
category: string;
comingSoon?: boolean;
popular?: boolean;
href?: string;
}
interface IntegrationGridProps {
title?: string;
description?: string;
integrations: Integration[];
categories?: string[];
showFilter?: boolean;
className?: string;
}Use Cases
Perfect for:
- Integration pages - Dedicated integrations showcase
- Landing pages - Show ecosystem strength
- Product pages - Highlight compatibility
- Marketing pages - Build trust with logos
- Documentation - Link to integration guides
- Partner pages - Showcase partnerships
- Comparison pages - Show more integrations than competitors
- Pricing pages - Show value through integrations
Common Patterns
Communication Tools
const communicationIntegrations = [
{
id: "slack",
name: "Slack",
description: "Get notifications in your Slack workspace",
logo: "/logos/slack.svg",
category: "Communication",
popular: true,
href: "/integrations/slack",
},
{
id: "teams",
name: "Microsoft Teams",
description: "Collaborate with your team",
logo: "/logos/teams.svg",
category: "Communication",
href: "/integrations/teams",
},
{
id: "discord",
name: "Discord",
description: "Get updates in your Discord server",
logo: "/logos/discord.svg",
category: "Communication",
comingSoon: true,
},
];Developer Tools
const devIntegrations = [
{
id: "github",
name: "GitHub",
description: "Sync repositories and automate workflows",
logo: "/logos/github.svg",
category: "Development",
popular: true,
href: "/integrations/github",
},
{
id: "gitlab",
name: "GitLab",
description: "Integrate with your GitLab projects",
logo: "/logos/gitlab.svg",
category: "Development",
href: "/integrations/gitlab",
},
{
id: "jira",
name: "Jira",
description: "Track issues and manage projects",
logo: "/logos/jira.svg",
category: "Development",
href: "/integrations/jira",
},
];Payment Processors
const paymentIntegrations = [
{
id: "stripe",
name: "Stripe",
description: "Accept payments and manage subscriptions",
logo: "/logos/stripe.svg",
category: "Payments",
popular: true,
href: "/integrations/stripe",
},
{
id: "paypal",
name: "PayPal",
description: "Process payments with PayPal",
logo: "/logos/paypal.svg",
category: "Payments",
href: "/integrations/paypal",
},
];Customization
Change Grid Columns
{/* 3 columns max */}
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
{/* 5 columns max */}
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5">
{/* 6 columns max */}
<div className="grid gap-4 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6">Add Color Accents
{
/* Add colored filter buttons */
}
<button
className={`rounded-lg px-4 py-2 text-sm font-semibold transition-all ${
selectedCategory === "all"
? "bg-gradient-to-r from-blue-600 to-cyan-600 text-white shadow-lg"
: "bg-white text-zinc-700 hover:bg-zinc-50"
}`}
>
All
</button>;
{
/* Add colored bottom border */
}
<div className="absolute bottom-0 left-0 h-1 w-full scale-x-0 bg-gradient-to-r from-blue-500 via-cyan-500 to-teal-500 transition-transform duration-500 group-hover:scale-x-100" />;Custom Badge Colors
{
/* Popular badge - default is black/white */
}
<span className="bg-zinc-900 text-white dark:bg-white dark:text-zinc-900">
Popular
</span>;
{
/* Change to colored badge */
}
<span className="bg-gradient-to-r from-blue-600 to-cyan-600 text-white">
Popular
</span>;
{
/* Coming soon badge */
}
<span className="border border-zinc-300 bg-white/90 text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800/90 dark:text-zinc-300">
Coming Soon
</span>;Add Search
const [searchQuery, setSearchQuery] = useState("");
const filteredIntegrations = integrations.filter((integration) =>
integration.name.toLowerCase().includes(searchQuery.toLowerCase())
);
<input
type="text"
placeholder="Search integrations..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="mb-8 w-full rounded-lg border px-4 py-2"
/>;Add Integration Count
<div className="mb-8 text-center">
<p className="text-sm text-zinc-600 dark:text-zinc-400">
{filteredIntegrations.length} integrations available
</p>
</div>Integration
With CMS
async function getIntegrations() {
const response = await fetch("/api/integrations");
const data = await response.json();
return data.integrations.map((item) => ({
id: item.id,
name: item.name,
description: item.description,
logo: item.logoUrl,
category: item.category,
popular: item.isPopular,
comingSoon: item.status === "coming_soon",
href: `/integrations/${item.slug}`,
}));
}With Analytics
const trackIntegrationClick = (integrationName: string) => {
// Track with your analytics tool
analytics.track("Integration Clicked", {
integration: integrationName,
category: selectedCategory,
});
};
<a
href={integration.href}
onClick={() => trackIntegrationClick(integration.name)}
>
Learn more
</a>;Dynamic Categories
// Auto-extract categories from integrations
const categories = Array.from(
new Set(integrations.map((i) => i.category))
).sort();
// Count integrations per category
const categoryCounts = categories.reduce((acc, cat) => {
acc[cat] = integrations.filter((i) => i.category === cat).length;
return acc;
}, {});Advanced Features
With Tabs Instead of Filters
<Tabs defaultValue="all">
<TabsList>
<TabsTrigger value="all">All</TabsTrigger>
<TabsTrigger value="communication">Communication</TabsTrigger>
<TabsTrigger value="development">Development</TabsTrigger>
</TabsList>
<TabsContent value="all">{/* All integrations */}</TabsContent>
</Tabs>With Modal Details
const [selectedIntegration, setSelectedIntegration] = useState(null);
<Dialog
open={!!selectedIntegration}
onOpenChange={() => setSelectedIntegration(null)}
>
<DialogContent>
<DialogTitle>{selectedIntegration?.name}</DialogTitle>
<DialogDescription>{selectedIntegration?.description}</DialogDescription>
{/* More details */}
</DialogContent>
</Dialog>;With Sorting
const [sortBy, setSortBy] = useState("popular");
const sortedIntegrations = [...integrations].sort((a, b) => {
if (sortBy === "popular") return b.popular ? 1 : -1;
if (sortBy === "name") return a.name.localeCompare(b.name);
return 0;
});