Skip to content
This repository was archived by the owner on Oct 27, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions app/_components/coming-soon-context.tsx

This file was deleted.

1 change: 0 additions & 1 deletion app/_lib/integration-catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ const toCatalogToolkit = ({
relativeDocsLink: new URL(metadata.docsLink).pathname,
type: metadata.type,
category: metadata.category,
isComingSoon: metadata.isComingSoon,
isHidden: metadata.isHidden,
});

Expand Down
36 changes: 10 additions & 26 deletions app/_lib/integration-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,16 @@ export function toIntegrationLink(toolkit: {
return `${INTEGRATIONS_BASE}/${category}/${slug}`;
}

export type ResolvedIndexToolkit = ToolkitWithDocsLink & { hasPage: boolean };
export type ResolvedIndexToolkit = ToolkitWithDocsLink & { link: string };

/**
* Decide which catalog toolkits the integrations index should render, and
* whether each one links to a real page.
* Decide which catalog toolkits the integrations index should render, and the
* page each card links to.
*
* The design-system catalog carries legacy bare-name entries (e.g. "Datadog"
* alongside "DatadogApi") and doc-less placeholders (e.g. "Discord") that have
* no generated docs page — linking to them 404s. Given the set of links that
* actually resolve (`validLinks`: dynamic toolkit routes + authored static
* pages), this:
* - drops a bare entry when its `-api` sibling owns the real page (collapses
* Datadog/DatadogApi, Vercel/VercelApi, Ashby/AshbyApi, Customerio/...),
* - de-dupes entries that resolve to the same URL (e.g. Notion/NotionToolkit),
* - flags the rest with `hasPage` so the caller can render doc-less toolkits
* as non-clickable cards instead of as broken links.
* Given the set of links that actually resolve (`validLinks`: dynamic toolkit
* routes + authored static pages), this:
* - drops toolkits without a page, so no card links to a 404,
* - de-dupes entries that resolve to the same URL (e.g. Notion/NotionToolkit).
*/
export function resolveIndexToolkits(
toolkits: ToolkitWithDocsLink[],
Expand All @@ -52,21 +46,11 @@ export function resolveIndexToolkits(
}

const link = toIntegrationLink(toolkit);
const hasPage = link !== null && validLinks.has(link);

// A bare duplicate of a real "-api" toolkit: drop it; the real card stays.
if (link && !hasPage && validLinks.has(`${link}-api`)) {
if (link === null || !validLinks.has(link) || seen.has(link)) {
continue;
}

// Collapse multiple catalog entries that point at the same URL.
if (link) {
if (seen.has(link)) {
continue;
}
seen.add(link);
}
resolved.push({ ...toolkit, hasPage });
seen.add(link);
resolved.push({ ...toolkit, link });
}

return resolved;
Expand Down
2 changes: 1 addition & 1 deletion app/_lib/toolkit-slug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { Toolkit } from "@arcadeai/design-system";
* render a Partner badge on cards). This type makes the properties explicit
* so both server and client code can share it.
*/
export type ToolkitWithDocsLink = Toolkit & {
export type ToolkitWithDocsLink = Omit<Toolkit, "isComingSoon"> & {
docsLink?: string | null;
isPartner?: boolean;
};
138 changes: 0 additions & 138 deletions app/en/resources/integrations/components/coming-soon-modal.tsx

This file was deleted.

66 changes: 6 additions & 60 deletions app/en/resources/integrations/components/tool-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@ import { Handshake, Package } from "lucide-react";
import Link from "next/link";
import posthog from "posthog-js";
import type React from "react";
import { useState } from "react";
import { ComingSoonModal } from "./coming-soon-modal";
import { TOOL_CARD_TYPE_CONFIG } from "./type-config";

type ToolCardProps = {
name: string;
icon?: React.ComponentType<React.SVGProps<SVGSVGElement>> | null;
iconUrl?: string;
link?: string;
link: string;
type: ToolkitType;
isComingSoon?: boolean;
isByoc?: boolean;
isPro?: boolean;
isPartner?: boolean;
Expand All @@ -35,44 +32,29 @@ export const ToolCard: React.FC<ToolCardProps> = ({
iconUrl,
link,
type,
isComingSoon = false,
isByoc = false,
isPro = false,
isPartner = false,
}) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const {
className,
label,
icon: IconComponent,
color,
} = TOOL_CARD_TYPE_CONFIG[type];
const showHeaderBadges = isByoc || isPro || isPartner || isComingSoon;
const showHeaderBadges = isByoc || isPro || isPartner;

const trackToolCardClick = () => {
posthog.capture("Tool card clicked", {
tool_name: toolName,
tool_type: type,
tool_link: link,
is_coming_soon: isComingSoon,
is_byoc: isByoc,
is_pro: isPro,
is_partner: isPartner,
});
};

const handleCardClick = (e: React.MouseEvent | React.KeyboardEvent) => {
trackToolCardClick();
if (isComingSoon) {
e.preventDefault();
setIsModalOpen(true);
}
};

const handleModalClose = () => {
setIsModalOpen(false);
};

let iconNode: React.ReactNode;
if (ToolkitIcon) {
iconNode = <ToolkitIcon className="size-9" />;
Expand All @@ -94,8 +76,7 @@ export const ToolCard: React.FC<ToolCardProps> = ({
<Card
className={cn(
"flex h-full flex-col gap-1.5 border bg-white/90 py-3 backdrop-blur-sm transition-all duration-300 hover:shadow-lg dark:bg-gray-900/80",
className,
isComingSoon && "relative"
className
)}
>
<CardHeader>
Expand Down Expand Up @@ -124,14 +105,6 @@ export const ToolCard: React.FC<ToolCardProps> = ({
"gap-1.5"
)}
>
{isComingSoon && (
<Badge
className="shrink-0 whitespace-nowrap border-gray-400 bg-gray-200/70 text-gray-700 dark:border-gray-700 dark:bg-gray-800/70 dark:text-gray-300"
variant="outline"
>
Coming soon
</Badge>
)}
{isByoc && <ByocBadge className="gap-1.5 rounded-md" />}
{isPro && <ProBadge className="gap-1.5 rounded-md" />}
{isPartner && (
Expand All @@ -151,35 +124,8 @@ export const ToolCard: React.FC<ToolCardProps> = ({
);

return (
<>
{isComingSoon || !link ? (
<button
aria-label={`${toolName} - Coming Soon`}
className="w-full cursor-pointer text-left"
onClick={handleCardClick}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
handleCardClick(e);
}
}}
type="button"
>
{cardContent}
</button>
) : (
<Link href={link} onClick={trackToolCardClick}>
{cardContent}
</Link>
)}

{isComingSoon && (
<ComingSoonModal
isOpen={isModalOpen}
onClose={handleModalClose}
toolkitName={toolName}
/>
)}
</>
<Link href={link} onClick={trackToolCardClick}>
{cardContent}
</Link>
);
};
Loading
Loading