Skip to main content
Internal Service β€” This is not an HTTP endpoint. It’s called directly by the generate-all orchestrator.

Purpose

Downloads the favicon from a website, converts it to PNG format, and uploads it to Supabase Storage. Returns a public URL for the favicon. Runs in GROUP 1d (parallel with scrape, fire-and-forget). Doesn’t need scraped pages.

Function Signature

async def run_favicon(url: str, org_slug: str) -> StepResult

Parameters

ParameterTypeDescription
urlstrThe website URL
org_slugstrThe Clerk organization slug

Returns

{
  "name": "favicon",
  "status": "success",
  "data": {
    "favicon_url": "https://supabase.co/storage/v1/object/public/favicons/my-business/favicon.png"
  }
}

Favicon Discovery Order

The service tries these locations in order:
  1. /favicon.ico - Standard location
  2. /apple-touch-icon.png - iOS icon (usually higher quality)
  3. /apple-touch-icon-precomposed.png - Alternative iOS icon
  4. HTML <link rel="icon"> tag
  5. HTML <link rel="shortcut icon"> tag
  6. Fallback: Google’s favicon service (https://www.google.com/s2/favicons?domain=...)

Processing Pipeline

Storage Location

Favicons are stored in Supabase Storage:
bucket: favicons
path: {org_slug}/favicon.png
Public URL format:
https://{project}.supabase.co/storage/v1/object/public/favicons/{org_slug}/favicon.png

Code Location

src/app/apis/onboarding/generate_all/
β”œβ”€β”€ favicon.py          # fetch_favicon function
└── tasks/
    └── favicon.py      # run_favicon task wrapper

Error Handling

{
  "name": "favicon",
  "status": "error",
  "error": "Could not find favicon at any standard location"
}
If favicon fetch fails, the onboarding continues without a favicon. The UI shows a default placeholder.