Features / Bento
Integrations directory with filter
Searchable logo grid grouped by purpose
Searchable logo grid grouped by purpose
Build an integrations directory with Tailwind CSS. Start with a heading, a muted subline giving the count of available integrations, and a controls row holding a search input with a magnifier glyph on the left and a set of filter chips — All, Data, Comms, Deploy, Billing — where the active chip is dark. Below, a responsive grid of integration cards, three or four across: each card is a rounded-xl bordered tile with a square logo placeholder holding a monogram, the product name, a one-line description, and a footer row with a small category label and either a muted "Connected" state with a green dot or a neutral "Connect" text button. Include ten cards across the categories. Under the grid, a centred bordered strip inviting people to request an integration with a small link. Then add JavaScript that filters the cards by chip category and by a case-insensitive match on the name and description, shows a "no matches" line when the grid empties, and keeps the count in the subline accurate. <section class="mx-auto max-w-6xl px-6 py-16">
<div class="max-w-2xl">
<h2 class="text-3xl font-semibold tracking-tight text-neutral-900">Works with the tools already on your desk</h2>
<p class="mt-3 text-neutral-500"><span id="integrationCount">10</span> integrations, each set up in under a minute.</p>
</div>
<div class="mt-8 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div class="relative sm:w-72">
<span class="pointer-events-none absolute left-3.5 top-1/2 -translate-y-1/2 text-neutral-400"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" class="inline-block h-[1em] w-[1em] shrink-0 align-[-0.125em] transition-transform"><circle cx="11" cy="11" r="7"/><path d="m16 16 4 4"/></svg></span>
<input id="integrationSearch" type="search" placeholder="Search integrations…"
class="w-full rounded-xl border border-neutral-200 py-2.5 pl-10 pr-3.5 text-sm outline-none transition focus:border-neutral-900 focus:ring-4 focus:ring-neutral-900/10" />
</div>
<div id="integrationChips" class="flex flex-wrap gap-2">
<button data-filter="all" class="chip rounded-full bg-neutral-900 px-3.5 py-1.5 text-xs font-medium text-white">All</button>
<button data-filter="data" class="chip rounded-full border border-neutral-200 px-3.5 py-1.5 text-xs font-medium text-neutral-600 transition hover:bg-neutral-50">Data</button>
<button data-filter="comms" class="chip rounded-full border border-neutral-200 px-3.5 py-1.5 text-xs font-medium text-neutral-600 transition hover:bg-neutral-50">Comms</button>
<button data-filter="deploy" class="chip rounded-full border border-neutral-200 px-3.5 py-1.5 text-xs font-medium text-neutral-600 transition hover:bg-neutral-50">Deploy</button>
<button data-filter="billing" class="chip rounded-full border border-neutral-200 px-3.5 py-1.5 text-xs font-medium text-neutral-600 transition hover:bg-neutral-50">Billing</button>
</div>
</div>
<div id="integrationGrid" class="mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<article data-cat="comms" data-name="slack channel alerts" class="integration rounded-xl border border-neutral-200 bg-white p-5 transition hover:border-neutral-300">
<div class="flex items-start justify-between">
<span class="grid h-11 w-11 place-items-center rounded-xl bg-neutral-900 text-sm font-semibold text-white">SL</span>
<span class="flex items-center gap-1.5 text-xs text-neutral-500"><span class="h-1.5 w-1.5 rounded-full bg-green-500"></span>Connected</span>
</div>
<h3 class="mt-4 text-sm font-semibold text-neutral-900">Slack</h3>
<p class="mt-1 text-sm leading-relaxed text-neutral-500">Route alerts to a channel and acknowledge without leaving the thread.</p>
<p class="mt-4 text-[11px] uppercase tracking-widest text-neutral-400">Comms</p>
</article>
<article data-cat="data" data-name="snowflake warehouse sync" class="integration rounded-xl border border-neutral-200 bg-white p-5 transition hover:border-neutral-300">
<div class="flex items-start justify-between">
<span class="grid h-11 w-11 place-items-center rounded-xl bg-blue-50 text-sm font-semibold text-blue-700">SF</span>
<button class="text-xs font-medium text-neutral-600 underline-offset-4 hover:text-neutral-900 hover:underline">Connect</button>
</div>
<h3 class="mt-4 text-sm font-semibold text-neutral-900">Snowflake</h3>
<p class="mt-1 text-sm leading-relaxed text-neutral-500">Stream every event into your warehouse on a five minute schedule.</p>
<p class="mt-4 text-[11px] uppercase tracking-widest text-neutral-400">Data</p>
</article>
<article data-cat="deploy" data-name="github actions checks" class="integration rounded-xl border border-neutral-200 bg-white p-5 transition hover:border-neutral-300">
<div class="flex items-start justify-between">
<span class="grid h-11 w-11 place-items-center rounded-xl bg-neutral-100 text-neutral-900"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" class="inline-block h-[1em] w-[1em] shrink-0 align-[-0.125em] transition-transform"><path d="M15 21v-3.5c0-1 .1-1.4-.5-2 2.8-.3 5.7-1.4 5.7-6.2 0-1.4-.5-2.5-1.3-3.4.1-.3.6-1.7-.1-3.4 0 0-1.1-.3-3.6 1.3a12.4 12.4 0 0 0-6.5 0C6.2 2.2 5.1 2.5 5.1 2.5c-.7 1.7-.2 3.1-.1 3.4a5 5 0 0 0-1.3 3.4c0 4.8 2.9 5.9 5.7 6.2-.5.5-.6 1-.5 2V21"/><path d="M9 18c-2.7.8-2.7-1.3-3.8-1.6"/></svg></span>
<span class="flex items-center gap-1.5 text-xs text-neutral-500"><span class="h-1.5 w-1.5 rounded-full bg-green-500"></span>Connected</span>
</div>
<h3 class="mt-4 text-sm font-semibold text-neutral-900">GitHub</h3>
<p class="mt-1 text-sm leading-relaxed text-neutral-500">Post a status check on every pull request before it can merge.</p>
<p class="mt-4 text-[11px] uppercase tracking-widest text-neutral-400">Deploy</p>
</article>
<article data-cat="billing" data-name="stripe invoices and usage" class="integration rounded-xl border border-neutral-200 bg-white p-5 transition hover:border-neutral-300">
<div class="flex items-start justify-between">
<span class="grid h-11 w-11 place-items-center rounded-xl bg-purple-50 text-sm font-semibold text-purple-700">ST</span>
<button class="text-xs font-medium text-neutral-600 underline-offset-4 hover:text-neutral-900 hover:underline">Connect</button>
</div>
<h3 class="mt-4 text-sm font-semibold text-neutral-900">Stripe</h3>
<p class="mt-1 text-sm leading-relaxed text-neutral-500">Bill on measured usage without writing a metering pipeline.</p>
<p class="mt-4 text-[11px] uppercase tracking-widest text-neutral-400">Billing</p>
</article>
<article data-cat="data" data-name="postgres direct connection" class="integration rounded-xl border border-neutral-200 bg-white p-5 transition hover:border-neutral-300">
<div class="flex items-start justify-between">
<span class="grid h-11 w-11 place-items-center rounded-xl bg-neutral-100 text-neutral-700"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" class="inline-block h-[1em] w-[1em] shrink-0 align-[-0.125em] transition-transform"><rect x="4" y="3" width="16" height="7" rx="2"/><rect x="4" y="14" width="16" height="7" rx="2"/><path d="M8 6.5h.01M8 17.5h.01M12 6.5h5M12 17.5h5"/></svg></span>
<button class="text-xs font-medium text-neutral-600 underline-offset-4 hover:text-neutral-900 hover:underline">Connect</button>
</div>
<h3 class="mt-4 text-sm font-semibold text-neutral-900">Postgres</h3>
<p class="mt-1 text-sm leading-relaxed text-neutral-500">Read replicas, connection pooling and schema introspection built in.</p>
<p class="mt-4 text-[11px] uppercase tracking-widest text-neutral-400">Data</p>
</article>
<article data-cat="comms" data-name="linear issue sync" class="integration rounded-xl border border-neutral-200 bg-white p-5 transition hover:border-neutral-300">
<div class="flex items-start justify-between">
<span class="grid h-11 w-11 place-items-center rounded-xl bg-neutral-900 text-sm font-semibold text-white">LN</span>
<button class="text-xs font-medium text-neutral-600 underline-offset-4 hover:text-neutral-900 hover:underline">Connect</button>
</div>
<h3 class="mt-4 text-sm font-semibold text-neutral-900">Linear</h3>
<p class="mt-1 text-sm leading-relaxed text-neutral-500">Turn a triaged alert into an issue with the timeline attached.</p>
<p class="mt-4 text-[11px] uppercase tracking-widest text-neutral-400">Comms</p>
</article>
<article data-cat="deploy" data-name="vercel preview deployments" class="integration rounded-xl border border-neutral-200 bg-white p-5 transition hover:border-neutral-300">
<div class="flex items-start justify-between">
<span class="grid h-11 w-11 place-items-center rounded-xl bg-neutral-100 text-neutral-900"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" class="inline-block h-[1em] w-[1em] shrink-0 align-[-0.125em] transition-transform"><path d="m12 4 9 16H3l9-16Z"/></svg></span>
<button class="text-xs font-medium text-neutral-600 underline-offset-4 hover:text-neutral-900 hover:underline">Connect</button>
</div>
<h3 class="mt-4 text-sm font-semibold text-neutral-900">Vercel</h3>
<p class="mt-1 text-sm leading-relaxed text-neutral-500">Attach performance budgets to every preview deployment.</p>
<p class="mt-4 text-[11px] uppercase tracking-widest text-neutral-400">Deploy</p>
</article>
<article data-cat="billing" data-name="quickbooks ledger export" class="integration rounded-xl border border-neutral-200 bg-white p-5 transition hover:border-neutral-300">
<div class="flex items-start justify-between">
<span class="grid h-11 w-11 place-items-center rounded-xl bg-green-50 text-sm font-semibold text-green-700">QB</span>
<button class="text-xs font-medium text-neutral-600 underline-offset-4 hover:text-neutral-900 hover:underline">Connect</button>
</div>
<h3 class="mt-4 text-sm font-semibold text-neutral-900">QuickBooks</h3>
<p class="mt-1 text-sm leading-relaxed text-neutral-500">Push monthly revenue into the ledger with tax codes intact.</p>
<p class="mt-4 text-[11px] uppercase tracking-widest text-neutral-400">Billing</p>
</article>
<article data-cat="data" data-name="segment event forwarding" class="integration rounded-xl border border-neutral-200 bg-white p-5 transition hover:border-neutral-300">
<div class="flex items-start justify-between">
<span class="grid h-11 w-11 place-items-center rounded-xl bg-neutral-100 text-neutral-700"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" class="inline-block h-[1em] w-[1em] shrink-0 align-[-0.125em] transition-transform"><path d="M3 12h4l2.5-7 5 14 2.5-7h4"/></svg></span>
<span class="flex items-center gap-1.5 text-xs text-neutral-500"><span class="h-1.5 w-1.5 rounded-full bg-green-500"></span>Connected</span>
</div>
<h3 class="mt-4 text-sm font-semibold text-neutral-900">Segment</h3>
<p class="mt-1 text-sm leading-relaxed text-neutral-500">Forward events you already collect, no extra SDK on the client.</p>
<p class="mt-4 text-[11px] uppercase tracking-widest text-neutral-400">Data</p>
</article>
<article data-cat="comms" data-name="pagerduty on call escalation" class="integration rounded-xl border border-neutral-200 bg-white p-5 transition hover:border-neutral-300">
<div class="flex items-start justify-between">
<span class="grid h-11 w-11 place-items-center rounded-xl bg-green-50 text-green-700"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" class="inline-block h-[1em] w-[1em] shrink-0 align-[-0.125em] transition-transform"><path d="M3 12h4l2.5-7 5 14 2.5-7h4"/></svg></span>
<button class="text-xs font-medium text-neutral-600 underline-offset-4 hover:text-neutral-900 hover:underline">Connect</button>
</div>
<h3 class="mt-4 text-sm font-semibold text-neutral-900">PagerDuty</h3>
<p class="mt-1 text-sm leading-relaxed text-neutral-500">Escalate anything still unacknowledged after five minutes.</p>
<p class="mt-4 text-[11px] uppercase tracking-widest text-neutral-400">Comms</p>
</article>
</div>
<p id="integrationEmpty" class="mt-10 hidden text-center text-sm text-neutral-500">Nothing matches that search yet.</p>
<div class="mt-10 rounded-xl border border-dashed border-neutral-300 px-6 py-5 text-center text-sm text-neutral-500">
Missing something you rely on? <a href="#" class="font-medium text-neutral-900 underline underline-offset-4">Request an integration</a> — we ship the most-asked-for one each month.
</div>
</section> var cards = Array.prototype.slice.call(document.querySelectorAll(".integration"));
var chips = Array.prototype.slice.call(document.querySelectorAll(".chip"));
var search = document.getElementById("integrationSearch");
var empty = document.getElementById("integrationEmpty");
var count = document.getElementById("integrationCount");
var filter = "all";
function apply() {
var q = search.value.trim().toLowerCase();
var shown = 0;
cards.forEach(function (card) {
var byCat = filter === "all" || card.dataset.cat === filter;
var byText = !q || card.dataset.name.indexOf(q) !== -1 || card.textContent.toLowerCase().indexOf(q) !== -1;
var visible = byCat && byText;
card.classList.toggle("hidden", !visible);
if (visible) shown += 1;
});
empty.classList.toggle("hidden", shown !== 0);
count.textContent = shown;
}
chips.forEach(function (chip) {
chip.addEventListener("click", function () {
filter = chip.dataset.filter;
chips.forEach(function (c) {
var on = c === chip;
c.classList.toggle("bg-neutral-900", on);
c.classList.toggle("text-white", on);
c.classList.toggle("border", !on);
c.classList.toggle("border-neutral-200", !on);
c.classList.toggle("text-neutral-600", !on);
});
apply();
});
});
search.addEventListener("input", apply);
apply();