Responses were thin because each card carried almost nothing — a link was a title + OG blurb, an image was just dimensions. Added a server-side enrichment layer that expands cards with the content they point at before calling OpenRouter.
Added
lib/ai-enrich.ts—enrichCards(cards, { notionToken })returns a per-card map of enriched text, cached per source (24h, in-process):- Image cards → captioned once via a cheap vision model
(
OPENROUTER_VISION_MODEL, defaultopenai/gpt-4o-mini), using the card's stored data URL. Previously the model only sawW×H. - Link cards → page is fetched and main article text extracted
(dependency-free: prefers
<article>/<main>, strips tags, caps ~1500 chars). - Notion cards → full page text via the existing
fetchNotionPageItems, instead of the 200-char excerpt (signed-in users with Notion connected).
- Image cards → captioned once via a cheap vision model
(
- Per-request caps (14 images / 24 links / 12 Notion pages) so a large space can't fan out into dozens of scrapes/vision calls at once.
Changed
app/api/ai/route.tsnow enriches the space before building context;describeCardappends the enriched content under each card. The Notion token is only fetched when the space actually contains Notion cards.