Link preview tooltips now prefetch metadata before you...
Link preview tooltips now prefetch metadata before you hover, eliminating the visible flash between domain fallback and rich preview. Uses ForesightJS proximity detection to...
Link preview tooltips now prefetch metadata before you hover, eliminating the visible flash between domain fallback and rich preview. Uses ForesightJS proximity detection to prefetch on cursor approach.
The problem
The link preview tooltips had a visible shift on hover. The tooltip appeared instantly with a domain-only fallback (just the hostname), then jumped to the rich preview (favicon + title + description) once the API responded. Even on fast connections the flash was noticeable.
The fix
ForesightJS detects when the cursor approaches an external link and prefetches its metadata before the user actually hovers. By the time the hover fires, the data is already cached and the tooltip appears fully populated.
How it works
ForesightManager.register()watches each external link with a 50px hit slop- When the cursor enters the proximity zone,
prefetchMetadata()fires a request to/api/link-metadata - The response goes into the session cache (
window.__linkPreviewState.externalCache) - On actual hover,
showTooltip()checks the cache first. Cache hit means instant rich preview, no network wait
For the rare case where the cursor moves fast enough to hover before the prefetch completes, a 150ms race handles it: if the fetch returns within 150ms (typical for KV-cached responses), the tooltip shows rich data directly. If it takes longer, the domain fallback appears and upgrades when the fetch finishes. In practice, this fallback path almost never triggers.
What changed
All changes are in src/lib/link-preview-component.ts:
- Extracted
fetchAndCacheMetadata()fromgetExternalMetadata(). The new method handles the fetch and cache storage without touching the abort controller, making it safe for both prefetch and hover-triggered calls. - Added
prefetchMetadata()as a fire-and-forget wrapper. Checks cache first, silently catches errors. - Updated
registerLinks()to callForesightManager.initialize()and register each external link for proximity prefetch. - Rewired
showTooltip()to check the cache first, then race the fetch against a 150ms timeout. No more unconditional domain fallback on every hover.