diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index bacfe1e7fc..2ed5a8fc24 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -1877,6 +1877,17 @@ export function StagehandIcon(props: SVGProps) { ) } +export function BrandfetchIcon(props: SVGProps) { + return ( + + + + ) +} + export function BrowserUseIcon(props: SVGProps) { return ( = { asana: AsanaIcon, ashby: AshbyIcon, attio: AttioIcon, + brandfetch: BrandfetchIcon, browser_use: BrowserUseIcon, calcom: CalComIcon, calendly: CalendlyIcon, diff --git a/apps/docs/content/docs/en/tools/brandfetch.mdx b/apps/docs/content/docs/en/tools/brandfetch.mdx new file mode 100644 index 0000000000..148a6726d0 --- /dev/null +++ b/apps/docs/content/docs/en/tools/brandfetch.mdx @@ -0,0 +1,83 @@ +--- +title: Brandfetch +description: Look up brand assets, logos, colors, and company info +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +## Usage Instructions + +Integrate Brandfetch into your workflow. Retrieve brand logos, colors, fonts, and company data by domain, ticker, or name search. + + + +## Tools + +### `brandfetch_get_brand` + +Retrieve brand assets including logos, colors, fonts, and company info by domain, ticker, ISIN, or crypto symbol + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Brandfetch API key | +| `identifier` | string | Yes | Brand identifier: domain \(nike.com\), stock ticker \(NKE\), ISIN \(US6541061031\), or crypto symbol \(BTC\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Unique brand identifier | +| `name` | string | Brand name | +| `domain` | string | Brand domain | +| `claimed` | boolean | Whether the brand profile is claimed | +| `description` | string | Short brand description | +| `longDescription` | string | Detailed brand description | +| `links` | array | Social media and website links | +| ↳ `name` | string | Link name \(e.g., twitter, linkedin\) | +| ↳ `url` | string | Link URL | +| `logos` | array | Brand logos with formats and themes | +| ↳ `type` | string | Logo type \(logo, icon, symbol, other\) | +| ↳ `theme` | string | Logo theme \(light, dark\) | +| ↳ `formats` | array | Available formats with src URL, format, width, and height | +| `colors` | array | Brand colors with hex values and types | +| ↳ `hex` | string | Hex color code | +| ↳ `type` | string | Color type \(accent, dark, light, brand\) | +| ↳ `brightness` | number | Brightness value | +| `fonts` | array | Brand fonts with names and types | +| ↳ `name` | string | Font name | +| ↳ `type` | string | Font type \(title, body\) | +| ↳ `origin` | string | Font origin \(google, custom, system\) | +| `company` | json | Company firmographic data including employees, location, and industries | +| `qualityScore` | number | Data quality score from 0 to 1 | +| `isNsfw` | boolean | Whether the brand contains adult content | + +### `brandfetch_search` + +Search for brands by name and find their domains and logos + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Brandfetch API key | +| `name` | string | Yes | Company or brand name to search for | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `results` | array | List of matching brands | +| ↳ `brandId` | string | Unique brand identifier | +| ↳ `name` | string | Brand name | +| ↳ `domain` | string | Brand domain | +| ↳ `claimed` | boolean | Whether the brand profile is claimed | +| ↳ `icon` | string | Brand icon URL | + + diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index ff5cd4247c..b9a50d12db 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -13,6 +13,7 @@ "asana", "ashby", "attio", + "brandfetch", "browser_use", "calcom", "calendly", diff --git a/apps/sim/blocks/blocks/brandfetch.ts b/apps/sim/blocks/blocks/brandfetch.ts new file mode 100644 index 0000000000..a270ce45fe --- /dev/null +++ b/apps/sim/blocks/blocks/brandfetch.ts @@ -0,0 +1,97 @@ +import { BrandfetchIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import { AuthMode } from '@/blocks/types' +import type { BrandfetchGetBrandResponse, BrandfetchSearchResponse } from '@/tools/brandfetch/types' + +export const BrandfetchBlock: BlockConfig = { + type: 'brandfetch', + name: 'Brandfetch', + description: 'Look up brand assets, logos, colors, and company info', + longDescription: + 'Integrate Brandfetch into your workflow. Retrieve brand logos, colors, fonts, and company data by domain, ticker, or name search.', + docsLink: 'https://docs.sim.ai/tools/brandfetch', + category: 'tools', + bgColor: '#000000', + icon: BrandfetchIcon, + authMode: AuthMode.ApiKey, + + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + { label: 'Get Brand', id: 'get_brand' }, + { label: 'Search Brands', id: 'search' }, + ], + value: () => 'get_brand', + }, + { + id: 'identifier', + title: 'Identifier', + type: 'short-input', + placeholder: 'e.g., nike.com, NKE, BTC', + required: { field: 'operation', value: 'get_brand' }, + condition: { field: 'operation', value: 'get_brand' }, + }, + { + id: 'name', + title: 'Brand Name', + type: 'short-input', + placeholder: 'e.g., Nike', + required: { field: 'operation', value: 'search' }, + condition: { field: 'operation', value: 'search' }, + }, + { + id: 'apiKey', + title: 'API Key', + type: 'short-input', + placeholder: 'Enter your Brandfetch API key', + required: true, + password: true, + }, + ], + + tools: { + access: ['brandfetch_get_brand', 'brandfetch_search'], + config: { + tool: (params) => { + switch (params.operation) { + case 'get_brand': + return 'brandfetch_get_brand' + case 'search': + return 'brandfetch_search' + default: + return 'brandfetch_get_brand' + } + }, + }, + }, + + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + identifier: { + type: 'string', + description: 'Brand identifier (domain, ticker, ISIN, or crypto symbol)', + }, + name: { type: 'string', description: 'Brand name to search for' }, + apiKey: { type: 'string', description: 'Brandfetch API key' }, + }, + + outputs: { + id: { type: 'string', description: 'Unique brand identifier' }, + name: { type: 'string', description: 'Brand name' }, + domain: { type: 'string', description: 'Brand domain' }, + claimed: { type: 'boolean', description: 'Whether the brand profile is claimed' }, + description: { type: 'string', description: 'Short brand description' }, + longDescription: { type: 'string', description: 'Detailed brand description' }, + links: { type: 'array', description: 'Social media and website links' }, + logos: { type: 'array', description: 'Brand logos with formats and themes' }, + colors: { type: 'array', description: 'Brand colors with hex values' }, + fonts: { type: 'array', description: 'Brand fonts' }, + company: { type: 'json', description: 'Company firmographic data' }, + qualityScore: { type: 'number', description: 'Data quality score (0-1)' }, + isNsfw: { type: 'boolean', description: 'Adult content indicator' }, + results: { type: 'array', description: 'Search results with brand name, domain, and icon' }, + }, +} diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index 1794fb5afc..80d3822eab 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -13,6 +13,7 @@ import { ArxivBlock } from '@/blocks/blocks/arxiv' import { AsanaBlock } from '@/blocks/blocks/asana' import { AshbyBlock } from '@/blocks/blocks/ashby' import { AttioBlock } from '@/blocks/blocks/attio' +import { BrandfetchBlock } from '@/blocks/blocks/brandfetch' import { BrowserUseBlock } from '@/blocks/blocks/browser_use' import { CalComBlock } from '@/blocks/blocks/calcom' import { CalendlyBlock } from '@/blocks/blocks/calendly' @@ -206,6 +207,7 @@ export const registry: Record = { asana: AsanaBlock, ashby: AshbyBlock, attio: AttioBlock, + brandfetch: BrandfetchBlock, browser_use: BrowserUseBlock, calcom: CalComBlock, calendly: CalendlyBlock, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index bacfe1e7fc..2ed5a8fc24 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -1877,6 +1877,17 @@ export function StagehandIcon(props: SVGProps) { ) } +export function BrandfetchIcon(props: SVGProps) { + return ( + + + + ) +} + export function BrowserUseIcon(props: SVGProps) { return ( = { + id: 'brandfetch_get_brand', + name: 'Brandfetch Get Brand', + description: + 'Retrieve brand assets including logos, colors, fonts, and company info by domain, ticker, ISIN, or crypto symbol', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Brandfetch API key', + }, + identifier: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: + 'Brand identifier: domain (nike.com), stock ticker (NKE), ISIN (US6541061031), or crypto symbol (BTC)', + }, + }, + + request: { + url: (params) => + `https://api.brandfetch.io/v2/brands/${encodeURIComponent(params.identifier.trim())}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Brandfetch API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + + return { + success: true, + output: { + id: data.id ?? '', + name: data.name ?? null, + domain: data.domain ?? '', + claimed: data.claimed ?? false, + description: data.description ?? null, + longDescription: data.longDescription ?? null, + links: data.links ?? [], + logos: data.logos ?? [], + colors: data.colors ?? [], + fonts: data.fonts ?? [], + company: data.company ?? null, + qualityScore: data.qualityScore ?? null, + isNsfw: data.isNsfw ?? false, + }, + } + }, + + outputs: { + id: { + type: 'string', + description: 'Unique brand identifier', + }, + name: { + type: 'string', + description: 'Brand name', + optional: true, + }, + domain: { + type: 'string', + description: 'Brand domain', + }, + claimed: { + type: 'boolean', + description: 'Whether the brand profile is claimed', + }, + description: { + type: 'string', + description: 'Short brand description', + optional: true, + }, + longDescription: { + type: 'string', + description: 'Detailed brand description', + optional: true, + }, + links: { + type: 'array', + description: 'Social media and website links', + items: { + type: 'json', + properties: { + name: { type: 'string', description: 'Link name (e.g., twitter, linkedin)' }, + url: { type: 'string', description: 'Link URL' }, + }, + }, + }, + logos: { + type: 'array', + description: 'Brand logos with formats and themes', + items: { + type: 'json', + properties: { + type: { type: 'string', description: 'Logo type (logo, icon, symbol, other)' }, + theme: { type: 'string', description: 'Logo theme (light, dark)' }, + formats: { + type: 'array', + description: 'Available formats with src URL, format, width, and height', + }, + }, + }, + }, + colors: { + type: 'array', + description: 'Brand colors with hex values and types', + items: { + type: 'json', + properties: { + hex: { type: 'string', description: 'Hex color code' }, + type: { type: 'string', description: 'Color type (accent, dark, light, brand)' }, + brightness: { type: 'number', description: 'Brightness value' }, + }, + }, + }, + fonts: { + type: 'array', + description: 'Brand fonts with names and types', + items: { + type: 'json', + properties: { + name: { type: 'string', description: 'Font name' }, + type: { type: 'string', description: 'Font type (title, body)' }, + origin: { type: 'string', description: 'Font origin (google, custom, system)' }, + }, + }, + }, + company: { + type: 'json', + description: 'Company firmographic data including employees, location, and industries', + optional: true, + }, + qualityScore: { + type: 'number', + description: 'Data quality score from 0 to 1', + optional: true, + }, + isNsfw: { + type: 'boolean', + description: 'Whether the brand contains adult content', + }, + }, +} diff --git a/apps/sim/tools/brandfetch/index.ts b/apps/sim/tools/brandfetch/index.ts new file mode 100644 index 0000000000..e294bc1bf3 --- /dev/null +++ b/apps/sim/tools/brandfetch/index.ts @@ -0,0 +1,3 @@ +export { brandfetchGetBrandTool } from '@/tools/brandfetch/get_brand' +export { brandfetchSearchTool } from '@/tools/brandfetch/search' +export * from '@/tools/brandfetch/types' diff --git a/apps/sim/tools/brandfetch/search.ts b/apps/sim/tools/brandfetch/search.ts new file mode 100644 index 0000000000..2d2a73c5c5 --- /dev/null +++ b/apps/sim/tools/brandfetch/search.ts @@ -0,0 +1,78 @@ +import type { + BrandfetchSearchParams, + BrandfetchSearchResponse, + BrandfetchSearchResult, +} from '@/tools/brandfetch/types' +import type { ToolConfig } from '@/tools/types' + +export const brandfetchSearchTool: ToolConfig = { + id: 'brandfetch_search', + name: 'Brandfetch Search', + description: 'Search for brands by name and find their domains and logos', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Brandfetch API key', + }, + name: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Company or brand name to search for', + }, + }, + + request: { + url: (params) => + `https://api.brandfetch.io/v2/search/${encodeURIComponent(params.name.trim())}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + Accept: 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Brandfetch API error (${response.status}): ${errorText}`) + } + + const data = await response.json() + const results = Array.isArray(data) ? data : [] + + return { + success: true, + output: { + results: results.map((item: Partial) => ({ + brandId: item.brandId ?? '', + name: item.name ?? null, + domain: item.domain ?? '', + claimed: item.claimed ?? false, + icon: item.icon ?? null, + })), + }, + } + }, + + outputs: { + results: { + type: 'array', + description: 'List of matching brands', + items: { + type: 'json', + properties: { + brandId: { type: 'string', description: 'Unique brand identifier' }, + name: { type: 'string', description: 'Brand name' }, + domain: { type: 'string', description: 'Brand domain' }, + claimed: { type: 'boolean', description: 'Whether the brand profile is claimed' }, + icon: { type: 'string', description: 'Brand icon URL' }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/brandfetch/types.ts b/apps/sim/tools/brandfetch/types.ts new file mode 100644 index 0000000000..25c5ab64a4 --- /dev/null +++ b/apps/sim/tools/brandfetch/types.ts @@ -0,0 +1,97 @@ +import type { ToolResponse } from '@/tools/types' + +export interface BrandfetchGetBrandParams { + apiKey: string + identifier: string +} + +export interface BrandfetchSearchParams { + apiKey: string + name: string +} + +export interface BrandLink { + name: string + url: string +} + +export interface BrandLogo { + type: string + theme: string | null + formats: Array<{ + src: string + format: string + width: number | null + height: number | null + background: string | null + }> +} + +export interface BrandColor { + hex: string + type: string + brightness: number +} + +export interface BrandFont { + name: string | null + type: string + origin: string + originId: string | null + weights: number[] +} + +export interface BrandCompany { + employees: string | null + foundedYear: number | null + kind: string | null + location: { + city: string | null + country: string | null + countryCode: string | null + state: string | null + stateCode: string | null + region: string | null + subRegion: string | null + } | null + industries: Array<{ + score: number + id: string + name: string + emoji: string + slug: string + parent: { id: string; name: string; emoji: string; slug: string } | null + }> +} + +export interface BrandfetchGetBrandResponse extends ToolResponse { + output: { + id: string + name: string | null + domain: string + claimed: boolean + description: string | null + longDescription: string | null + links: BrandLink[] + logos: BrandLogo[] + colors: BrandColor[] + fonts: BrandFont[] + company: BrandCompany | null + qualityScore: number | null + isNsfw: boolean + } +} + +export interface BrandfetchSearchResult { + brandId: string + name: string | null + domain: string + claimed: boolean + icon: string | null +} + +export interface BrandfetchSearchResponse extends ToolResponse { + output: { + results: BrandfetchSearchResult[] + } +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index 26458f94f9..36a31e4bd0 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -152,6 +152,7 @@ import { attioUpdateTaskTool, attioUpdateWebhookTool, } from '@/tools/attio' +import { brandfetchGetBrandTool, brandfetchSearchTool } from '@/tools/brandfetch' import { browserUseRunTaskTool } from '@/tools/browser_use' import { calcomCancelBookingTool, @@ -2315,6 +2316,8 @@ export const tools: Record = { ashby_list_offers: ashbyListOffersTool, ashby_search_candidates: ashbySearchCandidatesTool, ashby_update_candidate: ashbyUpdateCandidateTool, + brandfetch_get_brand: brandfetchGetBrandTool, + brandfetch_search: brandfetchSearchTool, browser_use_run_task: browserUseRunTaskTool, openai_embeddings: openAIEmbeddingsTool, http_request: httpRequestTool,