Problem
External links in task descriptions/comments render as bare links. Tools like Slack/GitHub show a small preview card (title, description, image) which makes links far more scannable.
Proposal
- Backend: a new authenticated
GET /api/v2/link-preview?url= endpoint that fetches the URL and returns its OpenGraph/meta summary (title, description, image, site_name, favicon). Outbound requests go through the existing SSRF-safe HTTP client (utils.NewSSRFSafeHTTPClient), so private/loopback/link-local targets are refused at dial time (incl. every redirect hop). HTML is parsed with golang.org/x/net/html — no new dependency.
- Frontend: a ProseMirror widget-decoration extension that renders a Slack-style card below each external link, but only in read-only (preview) mode, so nothing is written into the stored document. Previews are lazily fetched and cached per URL.
Privacy note: previews are fetched server-side only when a logged-in user views a description containing external links; no third-party JS is loaded.
I have a branch ready and will open a PR referencing this issue.
Implementation assisted by Claude Code (AI).
Problem
External links in task descriptions/comments render as bare links. Tools like Slack/GitHub show a small preview card (title, description, image) which makes links far more scannable.
Proposal
GET /api/v2/link-preview?url=endpoint that fetches the URL and returns its OpenGraph/meta summary (title,description,image,site_name,favicon). Outbound requests go through the existing SSRF-safe HTTP client (utils.NewSSRFSafeHTTPClient), so private/loopback/link-local targets are refused at dial time (incl. every redirect hop). HTML is parsed withgolang.org/x/net/html— no new dependency.Privacy note: previews are fetched server-side only when a logged-in user views a description containing external links; no third-party JS is loaded.
I have a branch ready and will open a PR referencing this issue.
Implementation assisted by Claude Code (AI).