({
+ resolver: zodResolver(linkupApiFormSchema),
+ defaultValues: {
+ name: "Linkup API Connector",
+ api_key: "",
+ },
+ });
+
+ // Handle form submission
+ const onSubmit = async (values: LinkupApiFormValues) => {
+ setIsSubmitting(true);
+ try {
+ await createConnector({
+ name: values.name,
+ connector_type: "LINKUP_API",
+ config: {
+ LINKUP_API_KEY: values.api_key,
+ },
+ is_indexable: false,
+ last_indexed_at: null,
+ });
+
+ toast.success("Linkup API connector created successfully!");
+
+ // Navigate back to connectors page
+ router.push(`/dashboard/${searchSpaceId}/connectors`);
+ } catch (error) {
+ console.error("Error creating connector:", error);
+ toast.error(error instanceof Error ? error.message : "Failed to create connector");
+ } finally {
+ setIsSubmitting(false);
+ }
+ };
+
+ return (
+
+
+
+
+
+
+ Connect Linkup API
+
+ Integrate with Linkup API to enhance your search capabilities with AI-powered search results.
+
+
+
+
+
+ API Key Required
+
+ You'll need a Linkup API key to use this connector. You can get one by signing up at{" "}
+
+ linkup.so
+
+
+
+
+
+
+
+
+ What you get with Linkup API:
+
+ - AI-powered search results tailored to your queries
+ - Real-time information from the web
+ - Enhanced search capabilities for your projects
+
+
+
+
+
+ );
+}
diff --git a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx
index 1f7490270..c04dae645 100644
--- a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx
+++ b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx
@@ -16,6 +16,7 @@ import {
IconWorldWww,
IconTicket,
IconLayoutKanban,
+ IconLinkPlus,
} from "@tabler/icons-react";
import { AnimatePresence, motion } from "framer-motion";
import Link from "next/link";
@@ -50,7 +51,13 @@ const connectorCategories: ConnectorCategory[] = [
icon: ,
status: "available",
},
- // Add other search engine connectors like Tavily, Serper if they have UI config
+ {
+ id: "linkup-api",
+ title: "Linkup API",
+ description: "Search the web using the Linkup API",
+ icon: ,
+ status: "available",
+ },
],
},
{
diff --git a/surfsense_web/components/ModernHeroWithGradients.tsx b/surfsense_web/components/ModernHeroWithGradients.tsx
index 052c993da..b30c4bc82 100644
--- a/surfsense_web/components/ModernHeroWithGradients.tsx
+++ b/surfsense_web/components/ModernHeroWithGradients.tsx
@@ -36,7 +36,7 @@ export function ModernHeroWithGradients() {
- A Customizable AI Research Agent just like NotebookLM or Perplexity, but connected to external sources such as search engines (Tavily), Slack, Linear, Notion, YouTube, GitHub and more.
+ A Customizable AI Research Agent just like NotebookLM or Perplexity, but connected to external sources such as search engines (Tavily, LinkUp), Slack, Linear, Notion, YouTube, GitHub and more.
{
const iconProps = { className: "h-4 w-4" };
switch(connectorType) {
+ case 'LINKUP_API':
+ return ;
case 'LINEAR_CONNECTOR':
return ;
case 'GITHUB_CONNECTOR':
diff --git a/surfsense_web/components/editConnector/types.ts b/surfsense_web/components/editConnector/types.ts
index 364f23526..cc43e1c81 100644
--- a/surfsense_web/components/editConnector/types.ts
+++ b/surfsense_web/components/editConnector/types.ts
@@ -30,5 +30,6 @@ export const editConnectorSchema = z.object({
SERPER_API_KEY: z.string().optional(),
TAVILY_API_KEY: z.string().optional(),
LINEAR_API_KEY: z.string().optional(),
+ LINKUP_API_KEY: z.string().optional(),
});
export type EditConnectorFormValues = z.infer;
diff --git a/surfsense_web/hooks/useConnectorEditPage.ts b/surfsense_web/hooks/useConnectorEditPage.ts
index d7672025d..7e81c5524 100644
--- a/surfsense_web/hooks/useConnectorEditPage.ts
+++ b/surfsense_web/hooks/useConnectorEditPage.ts
@@ -59,7 +59,8 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string)
NOTION_INTEGRATION_TOKEN: config.NOTION_INTEGRATION_TOKEN || "",
SERPER_API_KEY: config.SERPER_API_KEY || "",
TAVILY_API_KEY: config.TAVILY_API_KEY || "",
- LINEAR_API_KEY: config.LINEAR_API_KEY || ""
+ LINEAR_API_KEY: config.LINEAR_API_KEY || "",
+ LINKUP_API_KEY: config.LINKUP_API_KEY || ""
});
if (currentConnector.connector_type === 'GITHUB_CONNECTOR') {
const savedRepos = config.repo_full_names || [];
@@ -164,6 +165,12 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string)
newConfig = { LINEAR_API_KEY: formData.LINEAR_API_KEY };
}
break;
+ case 'LINKUP_API':
+ if (formData.LINKUP_API_KEY !== originalConfig.LINKUP_API_KEY) {
+ if (!formData.LINKUP_API_KEY) { toast.error("Linkup API Key cannot be empty."); setIsSaving(false); return; }
+ newConfig = { LINKUP_API_KEY: formData.LINKUP_API_KEY };
+ }
+ break;
}
if (newConfig !== null) {
@@ -203,6 +210,8 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string)
editForm.setValue('TAVILY_API_KEY', newlySavedConfig.TAVILY_API_KEY || "");
} else if(connector.connector_type === 'LINEAR_CONNECTOR') {
editForm.setValue('LINEAR_API_KEY', newlySavedConfig.LINEAR_API_KEY || "");
+ } else if(connector.connector_type === 'LINKUP_API') {
+ editForm.setValue('LINKUP_API_KEY', newlySavedConfig.LINKUP_API_KEY || "");
}
}
if (connector.connector_type === 'GITHUB_CONNECTOR') {
diff --git a/surfsense_web/lib/connectors/utils.ts b/surfsense_web/lib/connectors/utils.ts
index 5efc59386..f93bd3f82 100644
--- a/surfsense_web/lib/connectors/utils.ts
+++ b/surfsense_web/lib/connectors/utils.ts
@@ -7,6 +7,7 @@ export const getConnectorTypeDisplay = (type: string): string => {
"NOTION_CONNECTOR": "Notion",
"GITHUB_CONNECTOR": "GitHub",
"LINEAR_CONNECTOR": "Linear",
+ "LINKUP_API": "Linkup",
};
return typeMap[type] || type;
};