diff --git a/public/icons/abstract-company-enrichment.svg b/public/icons/abstract-company-enrichment.svg deleted file mode 100644 index 9e350650..00000000 --- a/public/icons/abstract-company-enrichment.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/abstract-email-reputation.svg b/public/icons/abstract-email-reputation.svg deleted file mode 100644 index 9e350650..00000000 --- a/public/icons/abstract-email-reputation.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/abstract-exchange-rates.svg b/public/icons/abstract-exchange-rates.svg deleted file mode 100644 index 9e350650..00000000 --- a/public/icons/abstract-exchange-rates.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/abstract-holidays.svg b/public/icons/abstract-holidays.svg deleted file mode 100644 index 9e350650..00000000 --- a/public/icons/abstract-holidays.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/abstract-iban-validation.svg b/public/icons/abstract-iban-validation.svg deleted file mode 100644 index 9e350650..00000000 --- a/public/icons/abstract-iban-validation.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/abstract-ip-intelligence.svg b/public/icons/abstract-ip-intelligence.svg deleted file mode 100644 index 9e350650..00000000 --- a/public/icons/abstract-ip-intelligence.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/abstract-phone-intelligence.svg b/public/icons/abstract-phone-intelligence.svg deleted file mode 100644 index 9e350650..00000000 --- a/public/icons/abstract-phone-intelligence.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/abstract-timezone.svg b/public/icons/abstract-timezone.svg deleted file mode 100644 index 9e350650..00000000 --- a/public/icons/abstract-timezone.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/abstract-vat.svg b/public/icons/abstract-vat.svg deleted file mode 100644 index 9e350650..00000000 --- a/public/icons/abstract-vat.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/abstract-web-scraping.svg b/public/icons/abstract-web-scraping.svg deleted file mode 100644 index 9e350650..00000000 --- a/public/icons/abstract-web-scraping.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/agentmail.svg b/public/icons/agentmail.svg deleted file mode 100644 index d00c65f9..00000000 --- a/public/icons/agentmail.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/icons/alchemy.svg b/public/icons/alchemy.svg deleted file mode 100644 index a6c357eb..00000000 --- a/public/icons/alchemy.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/allium.svg b/public/icons/allium.svg deleted file mode 100644 index 672645eb..00000000 --- a/public/icons/allium.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/alphavantage.svg b/public/icons/alphavantage.svg deleted file mode 100644 index eaca4b1c..00000000 --- a/public/icons/alphavantage.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/anthropic.svg b/public/icons/anthropic.svg deleted file mode 100644 index 6f481ffc..00000000 --- a/public/icons/anthropic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/apollo.svg b/public/icons/apollo.svg deleted file mode 100644 index c4f70f8e..00000000 --- a/public/icons/apollo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/aviationstack.svg b/public/icons/aviationstack.svg deleted file mode 100644 index 9738be41..00000000 --- a/public/icons/aviationstack.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/billboard.svg b/public/icons/billboard.svg deleted file mode 100644 index a64eed46..00000000 --- a/public/icons/billboard.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/brave.svg b/public/icons/brave.svg deleted file mode 100644 index 1a44afd7..00000000 --- a/public/icons/brave.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/browser-use.svg b/public/icons/browser-use.svg deleted file mode 100644 index c5653e9a..00000000 --- a/public/icons/browser-use.svg +++ /dev/null @@ -1 +0,0 @@ -B \ No newline at end of file diff --git a/public/icons/browserbase.svg b/public/icons/browserbase.svg deleted file mode 100644 index d85ebcbc..00000000 --- a/public/icons/browserbase.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/builtwith.svg b/public/icons/builtwith.svg deleted file mode 100644 index c5653e9a..00000000 --- a/public/icons/builtwith.svg +++ /dev/null @@ -1 +0,0 @@ -B \ No newline at end of file diff --git a/public/icons/clado.svg b/public/icons/clado.svg deleted file mode 100644 index 6397c9fe..00000000 --- a/public/icons/clado.svg +++ /dev/null @@ -1 +0,0 @@ -C \ No newline at end of file diff --git a/public/icons/codestorage.svg b/public/icons/codestorage.svg deleted file mode 100644 index 76563d7a..00000000 --- a/public/icons/codestorage.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/codex.svg b/public/icons/codex.svg deleted file mode 100644 index 82eeef0a..00000000 --- a/public/icons/codex.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/coingecko.svg b/public/icons/coingecko.svg deleted file mode 100644 index 266feb4f..00000000 --- a/public/icons/coingecko.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/deepgram.svg b/public/icons/deepgram.svg deleted file mode 100644 index 5238f9c9..00000000 --- a/public/icons/deepgram.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/deepl.svg b/public/icons/deepl.svg deleted file mode 100644 index 12cbf5ba..00000000 --- a/public/icons/deepl.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/deepseek.svg b/public/icons/deepseek.svg deleted file mode 100644 index 316491dd..00000000 --- a/public/icons/deepseek.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/diffbot-kg.svg b/public/icons/diffbot-kg.svg deleted file mode 100644 index 4b7c2804..00000000 --- a/public/icons/diffbot-kg.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/diffbot-nl.svg b/public/icons/diffbot-nl.svg deleted file mode 100644 index 4b7c2804..00000000 --- a/public/icons/diffbot-nl.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/diffbot.svg b/public/icons/diffbot.svg deleted file mode 100644 index 4e7b94c5..00000000 --- a/public/icons/diffbot.svg +++ /dev/null @@ -1 +0,0 @@ -D \ No newline at end of file diff --git a/public/icons/digitalocean.svg b/public/icons/digitalocean.svg deleted file mode 100644 index d881184d..00000000 --- a/public/icons/digitalocean.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/dune.svg b/public/icons/dune.svg deleted file mode 100644 index 587d4d77..00000000 --- a/public/icons/dune.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/edgar-search.svg b/public/icons/edgar-search.svg deleted file mode 100644 index c3759c30..00000000 --- a/public/icons/edgar-search.svg +++ /dev/null @@ -1 +0,0 @@ -E \ No newline at end of file diff --git a/public/icons/edgar.svg b/public/icons/edgar.svg deleted file mode 100644 index c3759c30..00000000 --- a/public/icons/edgar.svg +++ /dev/null @@ -1 +0,0 @@ -E \ No newline at end of file diff --git a/public/icons/exa.svg b/public/icons/exa.svg deleted file mode 100644 index d04f2bfd..00000000 --- a/public/icons/exa.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/fal.svg b/public/icons/fal.svg deleted file mode 100644 index 5c02f15f..00000000 --- a/public/icons/fal.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/firecrawl.svg b/public/icons/firecrawl.svg deleted file mode 100644 index 6907d7c5..00000000 --- a/public/icons/firecrawl.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/flightapi.svg b/public/icons/flightapi.svg deleted file mode 100644 index 01dc2714..00000000 --- a/public/icons/flightapi.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/gemini.svg b/public/icons/gemini.svg deleted file mode 100644 index c3cf32ff..00000000 --- a/public/icons/gemini.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/goflightlabs.svg b/public/icons/goflightlabs.svg deleted file mode 100644 index ab1d5e43..00000000 --- a/public/icons/goflightlabs.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-aerialview.svg b/public/icons/googlemaps-aerialview.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-aerialview.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-airquality.svg b/public/icons/googlemaps-airquality.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-airquality.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-geolocation.svg b/public/icons/googlemaps-geolocation.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-geolocation.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-places-v2.svg b/public/icons/googlemaps-places-v2.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-places-v2.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-pollen.svg b/public/icons/googlemaps-pollen.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-pollen.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-roads.svg b/public/icons/googlemaps-roads.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-roads.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-routes.svg b/public/icons/googlemaps-routes.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-routes.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-solar.svg b/public/icons/googlemaps-solar.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-solar.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-tiles.svg b/public/icons/googlemaps-tiles.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-tiles.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-validation.svg b/public/icons/googlemaps-validation.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-validation.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps-weather.svg b/public/icons/googlemaps-weather.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps-weather.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/googlemaps.svg b/public/icons/googlemaps.svg deleted file mode 100644 index 3e648350..00000000 --- a/public/icons/googlemaps.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/grok.svg b/public/icons/grok.svg deleted file mode 100644 index 0c11bd10..00000000 --- a/public/icons/grok.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/groq.svg b/public/icons/groq.svg deleted file mode 100644 index a429691e..00000000 --- a/public/icons/groq.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/hunter.svg b/public/icons/hunter.svg deleted file mode 100644 index 8c41e70b..00000000 --- a/public/icons/hunter.svg +++ /dev/null @@ -1 +0,0 @@ -H \ No newline at end of file diff --git a/public/icons/ipinfo.svg b/public/icons/ipinfo.svg deleted file mode 100644 index 7f3aaeb9..00000000 --- a/public/icons/ipinfo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/judge0.svg b/public/icons/judge0.svg deleted file mode 100644 index 9ae294e1..00000000 --- a/public/icons/judge0.svg +++ /dev/null @@ -1 +0,0 @@ -J \ No newline at end of file diff --git a/public/icons/kicksdb.svg b/public/icons/kicksdb.svg deleted file mode 100644 index 1fa9baef..00000000 --- a/public/icons/kicksdb.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/laso.svg b/public/icons/laso.svg deleted file mode 100644 index cd907823..00000000 --- a/public/icons/laso.svg +++ /dev/null @@ -1 +0,0 @@ -L \ No newline at end of file diff --git a/public/icons/mapbox.svg b/public/icons/mapbox.svg deleted file mode 100644 index 79660ad7..00000000 --- a/public/icons/mapbox.svg +++ /dev/null @@ -1 +0,0 @@ -M \ No newline at end of file diff --git a/public/icons/mathpix.svg b/public/icons/mathpix.svg deleted file mode 100644 index 79660ad7..00000000 --- a/public/icons/mathpix.svg +++ /dev/null @@ -1 +0,0 @@ -M \ No newline at end of file diff --git a/public/icons/mistral.svg b/public/icons/mistral.svg deleted file mode 100644 index 3499c0b2..00000000 --- a/public/icons/mistral.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/modal.svg b/public/icons/modal.svg deleted file mode 100644 index 21a8c394..00000000 --- a/public/icons/modal.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/openai.svg b/public/icons/openai.svg deleted file mode 100644 index b4839440..00000000 --- a/public/icons/openai.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/openrouter.svg b/public/icons/openrouter.svg deleted file mode 100644 index e54129b5..00000000 --- a/public/icons/openrouter.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/openweather.svg b/public/icons/openweather.svg deleted file mode 100644 index f8aae7c1..00000000 --- a/public/icons/openweather.svg +++ /dev/null @@ -1 +0,0 @@ -O \ No newline at end of file diff --git a/public/icons/oxylabs.svg b/public/icons/oxylabs.svg deleted file mode 100644 index 07b28f27..00000000 --- a/public/icons/oxylabs.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/parallel.svg b/public/icons/parallel.svg deleted file mode 100644 index 97fe9a0f..00000000 --- a/public/icons/parallel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/perplexity.svg b/public/icons/perplexity.svg deleted file mode 100644 index 9ab6ffe6..00000000 --- a/public/icons/perplexity.svg +++ /dev/null @@ -1 +0,0 @@ -P \ No newline at end of file diff --git a/public/icons/postalform.svg b/public/icons/postalform.svg deleted file mode 100644 index 761d0e3c..00000000 --- a/public/icons/postalform.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/prospect-butcher.svg b/public/icons/prospect-butcher.svg deleted file mode 100644 index a3c13bea..00000000 --- a/public/icons/prospect-butcher.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/rentcast.svg b/public/icons/rentcast.svg deleted file mode 100644 index 71c4d653..00000000 --- a/public/icons/rentcast.svg +++ /dev/null @@ -1 +0,0 @@ -R \ No newline at end of file diff --git a/public/icons/replicate.svg b/public/icons/replicate.svg deleted file mode 100644 index 71c4d653..00000000 --- a/public/icons/replicate.svg +++ /dev/null @@ -1 +0,0 @@ -R \ No newline at end of file diff --git a/public/icons/rpc.svg b/public/icons/rpc.svg deleted file mode 100644 index b8f129fc..00000000 --- a/public/icons/rpc.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/screenshotone.svg b/public/icons/screenshotone.svg deleted file mode 100644 index b3983bcc..00000000 --- a/public/icons/screenshotone.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/serpapi.svg b/public/icons/serpapi.svg deleted file mode 100644 index 9b7df559..00000000 --- a/public/icons/serpapi.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/spyfu.svg b/public/icons/spyfu.svg deleted file mode 100644 index 6af3dc90..00000000 --- a/public/icons/spyfu.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/stability-ai.svg b/public/icons/stability-ai.svg deleted file mode 100644 index cc0f3225..00000000 --- a/public/icons/stability-ai.svg +++ /dev/null @@ -1 +0,0 @@ -S \ No newline at end of file diff --git a/public/icons/stableemail.svg b/public/icons/stableemail.svg deleted file mode 100644 index 5d460b33..00000000 --- a/public/icons/stableemail.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/stableenrich.svg b/public/icons/stableenrich.svg deleted file mode 100644 index 93178e6d..00000000 --- a/public/icons/stableenrich.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/stablephone.svg b/public/icons/stablephone.svg deleted file mode 100644 index 0cd08f22..00000000 --- a/public/icons/stablephone.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/stablesocial.svg b/public/icons/stablesocial.svg deleted file mode 100644 index cce5f112..00000000 --- a/public/icons/stablesocial.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/stablestudio.svg b/public/icons/stablestudio.svg deleted file mode 100644 index a3af1f40..00000000 --- a/public/icons/stablestudio.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/stabletravel.svg b/public/icons/stabletravel.svg deleted file mode 100644 index 2978ab75..00000000 --- a/public/icons/stabletravel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/stableupload.svg b/public/icons/stableupload.svg deleted file mode 100644 index 4d54842c..00000000 --- a/public/icons/stableupload.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/storage.svg b/public/icons/storage.svg deleted file mode 100644 index b8f129fc..00000000 --- a/public/icons/storage.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/stripe-climate.svg b/public/icons/stripe-climate.svg deleted file mode 100644 index 54a0fba9..00000000 --- a/public/icons/stripe-climate.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/suno.svg b/public/icons/suno.svg deleted file mode 100644 index cc0f3225..00000000 --- a/public/icons/suno.svg +++ /dev/null @@ -1 +0,0 @@ -S \ No newline at end of file diff --git a/public/icons/tavily.svg b/public/icons/tavily.svg deleted file mode 100644 index c787c223..00000000 --- a/public/icons/tavily.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/twitter.svg b/public/icons/twitter.svg deleted file mode 100644 index 6c9879b1..00000000 --- a/public/icons/twitter.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/twocaptcha.svg b/public/icons/twocaptcha.svg deleted file mode 100644 index d637f6b3..00000000 --- a/public/icons/twocaptcha.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/wolframalpha.svg b/public/icons/wolframalpha.svg deleted file mode 100644 index 3a9deb1a..00000000 --- a/public/icons/wolframalpha.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/scripts/generate-og-descriptions.ts b/scripts/generate-og-descriptions.ts index 04e4dc95..ee58407a 100644 --- a/scripts/generate-og-descriptions.ts +++ b/scripts/generate-og-descriptions.ts @@ -11,7 +11,7 @@ function extractOgDescription(content: string): string | null { const match = content.match(/^---\s*\n([\s\S]*?)\n---/); if (!match) return null; const fm = match[1]; - const descMatch = fm.match(/^ogDescription:\s*"(.+)"\s*$/m); + const descMatch = fm.match(/^imageDescription:\s*"(.+)"\s*$/m); return descMatch ? descMatch[1] : null; } diff --git a/scripts/sync-logos.ts b/scripts/sync-logos.ts index 80588fab..d59db780 100644 --- a/scripts/sync-logos.ts +++ b/scripts/sync-logos.ts @@ -6,7 +6,9 @@ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; +import * as zlib from "node:zlib"; import { put } from "@vercel/blob"; +import { logoDevUrl } from "../src/lib/logodev.ts"; // --------------------------------------------------------------------------- // Types @@ -58,7 +60,7 @@ const DOMAIN_OVERRIDES: Record = { // --------------------------------------------------------------------------- function decodePngPixels(buf: ArrayBuffer) { - const { inflateSync } = require("node:zlib") as typeof import("node:zlib"); + const { inflateSync } = zlib; const bytes = new Uint8Array(buf); if (bytes.length < 26) return null; const colorType = bytes[25]; @@ -184,7 +186,7 @@ function domainForService(svc: ServiceEntry): string | null { } function logoUrl(domain: string): string { - return `https://img.logo.dev/${domain}?token=${LOGODEV_PK}&format=png&size=256&greyscale=true&theme=dark&fallback=monogram&retina=true`; + return logoDevUrl(domain, { token: LOGODEV_PK! }); } // --------------------------------------------------------------------------- diff --git a/src/components/NotFoundPage.tsx b/src/components/NotFoundPage.tsx index ac8c4a13..d15004d3 100644 --- a/src/components/NotFoundPage.tsx +++ b/src/components/NotFoundPage.tsx @@ -161,7 +161,7 @@ export function NotFoundPage() { className="overflow-hidden max-w-full mb-8" style={{ fontFamily: "monospace", - lineHeight: 1.15, + lineHeight: 1.8, whiteSpace: "pre", letterSpacing: "1px", color: "var(--vocs-text-color-heading)", @@ -169,7 +169,7 @@ export function NotFoundPage() { }} >
{mppLines.map((mppLine, lineIdx) => { diff --git a/src/components/ServiceDiscovery.tsx b/src/components/ServiceDiscovery.tsx index 439d19e0..7b9d07ae 100644 --- a/src/components/ServiceDiscovery.tsx +++ b/src/components/ServiceDiscovery.tsx @@ -3,10 +3,8 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { createPortal } from "react-dom"; import type { Category, Endpoint, Service } from "../data/registry"; -import { - fetchServices, - iconUrl as getIconUrlForService, -} from "../data/registry"; +import { fetchServices } from "../data/registry"; +import { ServiceLogo } from "./ServiceLogo"; import { PINNED_IDS } from "./ServicesPage"; const CATEGORY_LABELS: Record = { @@ -80,10 +78,6 @@ function getExamplePayload(ep: Endpoint): string { return "'{}'"; } -function getIconUrl(service: Service): string { - return getIconUrlForService(service.id); -} - // --------------------------------------------------------------------------- // Filter engine — scores services against a query // --------------------------------------------------------------------------- @@ -193,8 +187,6 @@ export function ServiceDiscovery({ const overlayRef = useRef(null); const gridRef = useRef(null); const inputRef = useRef(null); - const brokenIcons = useRef(new Set()); - const [, forceIconUpdate] = useState(0); const [activeIndex, setActiveIndex] = useState(-1); const [isFocused, setIsFocused] = useState(false); @@ -656,7 +648,6 @@ export function ServiceDiscovery({
{stableScored.slice(0, 48).map(({ service, score }) => { const isMatch = (!debouncedQuery && !externalCategory) || score > 0; - const iconUrl = getIconUrl(service); const t = transforms[service.id]; const isAnimating = hasQuery && isMatch && t; @@ -748,21 +739,11 @@ export function ServiceDiscovery({ zIndex: 1, }} > - {iconUrl && !brokenIcons.current.has(service.id) ? ( - { - brokenIcons.current.add(service.id); - forceIconUpdate((n) => n + 1); - }} - /> - ) : ( -
- {service.name[0]} -
- )} + {service.integration !== "third-party" && ( (null); const [copiedJson, setCopiedJson] = useState(false); const [showAgentTip, setShowAgentTip] = useState(false); - const [imgError, setImgError] = useState(false); const [isClosing, setIsClosing] = useState(false); const handleClose = useCallback(() => { @@ -866,8 +846,6 @@ function ServiceDetailModal({ return () => window.removeEventListener("keydown", handleKey); }, [handleClose]); - const iconUrl = getIconUrl(service); - function formatPrice(ep: Endpoint): string { const p = ep.payment; if (!p?.amount) return p?.amountHint ?? "—"; @@ -982,36 +960,12 @@ function ServiceDetailModal({ {/* Header */}
- {iconUrl && !imgError ? ( - setImgError(true)} - className="discovery-card-icon-img" - style={{ - width: 44, - height: 44, - borderRadius: 10, - }} - /> - ) : ( -
- {service.name[0]} -
- )} +
; + } + + const needsInvert = isDark === manifest.lightBg.has(service.id); + + return ( + setImgError(true)} + /> + ); +} + +export function ServiceLogoFallback({ + name, + size = 28, +}: { + name: string; + size?: number; +}) { + const initials = name + .split(/[\s-]+/) + .slice(0, 2) + .map((w) => w.charAt(0).toUpperCase()) + .join(""); + + return ( +
1 + ? Math.round(size * 0.36) + : Math.round(size * 0.46), + fontWeight: 600, + letterSpacing: "-0.02em", + color: "var(--vocs-text-color-secondary)", + border: + "1px solid light-dark(rgba(0,0,0,0.08), rgba(255,255,255,0.08))", + }} + > + {initials || "?"} +
+ ); +} + +const EMPTY_MANIFEST: IconManifest = { + transparent: new Set(), + lightBg: new Set(), +}; + +function useIconManifest(): IconManifest { + const [manifest, setManifest] = useState(EMPTY_MANIFEST); + useEffect(() => { + fetchIconManifest().then(setManifest); + }, []); + return manifest; +} diff --git a/src/components/ServicesPage.tsx b/src/components/ServicesPage.tsx index c7aaad15..8d3c90ec 100644 --- a/src/components/ServicesPage.tsx +++ b/src/components/ServicesPage.tsx @@ -3,8 +3,9 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { Link } from "vocs"; import type { Category, Endpoint, Service } from "../data/registry"; -import { fetchServices, iconUrl } from "../data/registry"; +import { fetchServices } from "../data/registry"; import { ServiceDiscovery } from "./ServiceDiscovery"; +import { ServiceLogo } from "./ServiceLogo"; export const CATEGORY_LABELS: Record = { ai: "AI", @@ -2943,38 +2944,8 @@ function BorderlessBadge({ children }: { children: React.ReactNode }) { // Service icon with optional first-party overlay // --------------------------------------------------------------------------- -function FallbackIcon({ name }: { name: string }) { - const initials = name - .split(/[\s-]+/) - .slice(0, 2) - .map((w) => w.charAt(0).toUpperCase()) - .join(""); - return ( -
1 ? 10 : 13, - fontWeight: 600, - letterSpacing: "-0.02em", - color: "var(--vocs-text-color-secondary)", - border: - "1px solid light-dark(rgba(0,0,0,0.08), rgba(255,255,255,0.08))", - }} - > - {initials || "?"} -
- ); -} - function ServiceIcon({ service: s }: { service: Service }) { const isFirstParty = s.integration !== "third-party"; - const [imgError, setImgError] = useState(false); return (
- {s.id && !imgError ? ( - setImgError(true)} - /> - ) : ( - - )} + {isFirstParty && ( ${letter}`; @@ -18,7 +15,7 @@ function letterSvg(id: string): string { async function blobGet( id: string, -): Promise<{ body: ReadableStream; contentType: string } | null> { +): Promise<{ data: ArrayBuffer; contentType: string } | null> { if (!BLOB_TOKEN) return null; try { for (const ext of ["png", "svg"]) { @@ -29,11 +26,11 @@ async function blobGet( }); if (blobs.length > 0) { const res = await fetch(blobs[0].url); - if (res.ok && res.body) { + if (res.ok) { const ct = res.headers.get("content-type") ?? (ext === "svg" ? "image/svg+xml" : `image/${ext}`); - return { body: res.body, contentType: ct }; + return { data: await res.arrayBuffer(), contentType: ct }; } } } @@ -43,41 +40,41 @@ async function blobGet( return null; } -async function staticIcon( - request: Request, - id: string, -): Promise { - try { - const origin = new URL(request.url).origin; - const res = await fetch(`${origin}/icons/${id}.svg`); - if (res.ok) { - return new Response(await res.text(), { - headers: { ...FALLBACK_HEADERS, ...CACHE_HEADERS }, - }); - } - } catch { - // static file not available - } - return null; -} - export async function GET(request: Request) { - const id = new URL(request.url).searchParams.get("id"); + const url = new URL(request.url); + const id = url.searchParams.get("id"); if (!id) return new Response("Missing id parameter", { status: 400 }); - // 1. Static override (public/icons/*.svg) — hand-curated icons take priority - const override = await staticIcon(request, id); - if (override) return override; - - // 2. Vercel Blob (logo.dev sync) + // 1. Vercel Blob (synced from logo.dev) const blob = await blobGet(id); if (blob) { - return new Response(blob.body, { + return new Response(blob.data, { headers: { "Content-Type": blob.contentType, ...CACHE_HEADERS }, }); } + // 2. Live logo.dev fallback + if (LOGODEV_PK) { + const domain = url.searchParams.get("domain"); + if (domain) { + try { + const res = await fetch(logoDevUrl(domain, { token: LOGODEV_PK })); + if (res.ok) { + return new Response(await res.arrayBuffer(), { + headers: { "Content-Type": "image/png", ...CACHE_HEADERS }, + }); + } + } catch (e) { + console.error(`[icon] logo.dev fallback error for ${domain}:`, e); + } + } + } + // 3. Letter SVG (guaranteed — never 404) - console.warn(`[icon] no icon found for ${id}, generating letter fallback`); - return new Response(letterSvg(id), { headers: FALLBACK_HEADERS }); + return new Response(letterSvg(id), { + headers: { + "Content-Type": "image/svg+xml", + "Cache-Control": "public, s-maxage=3600, stale-while-revalidate", + }, + }); } diff --git a/src/pages/_api/api/og.tsx b/src/pages/_api/api/og.tsx index d8798f59..e2d67fa6 100644 --- a/src/pages/_api/api/og.tsx +++ b/src/pages/_api/api/og.tsx @@ -1,7 +1,7 @@ // @ts-nocheck – server-only, uses Vite ?raw import and resvg native module import { initWasm, Resvg } from "@resvg/resvg-wasm"; import resvgWasm from "@resvg/resvg-wasm/index_bg.wasm?url"; -import ogDescriptions from "../../../generated/og-descriptions.json"; +import imageDescriptions from "../../../generated/og-descriptions.json"; import templateSvg from "./og-template.svg?raw"; const BLOB = "https://wgfdjv2jfqz2dlpx.public.blob.vercel-storage.com"; @@ -230,7 +230,7 @@ export async function GET(request: Request) { const rawDescription = url.searchParams.get("description") || ""; const path = decodeURIComponent(url.searchParams.get("path") || ""); const description = - (ogDescriptions as Record)[path] || rawDescription; + (imageDescriptions as Record)[path] || rawDescription; const category = getCategoryForPath(path); const subcategory = getSubcategoryForPath(path); diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx index c05a9e22..ee0dd2b3 100644 --- a/src/pages/_layout.tsx +++ b/src/pages/_layout.tsx @@ -447,14 +447,14 @@ export default function Layout(props: React.PropsWithChildren) { )}