Adds the front-end side of the link-preview feature so the back-end
team has a fixed contract to implement against.
- docs/link-preview.md: full spec for the `/api/link-preview` proxy
and the preferred inline-on-Post integration. Covers caching, SSRF
guards, metadata-extraction precedence, provider quirks, and the
front-end rendering rules. Scope is the first URL only.
- types/post.ts: new `LinkPreview` type and optional `linkPreview`
field on `Post`.
- LinkPreviewCard: clickable card with a themeColor accent bar,
siteName / title / description (line-clamped), and an optional
1.91:1 thumbnail. Whole card is an `<a target="_blank">` to the
canonical URL.
- MessageBubble: render the card between the bubble body and the
timestamp, with padding that matches visual vs. text-only bubbles.
- mockPosts: example `linkPreview` payloads on p-005 and p-010 so
the visual works when running with VITE_USE_MOCK_POSTS=true,
and so the back-end has concrete reference values.
- Home: lock category carousel height to the tallest page so the
Official Recommendations section below does not jump up when
swiping to a page with fewer categories.
- CollapsibleText: raise default threshold to 25 lines and tighten
the spacing between the expand-all button and the timestamp
(drop the fixed h-8 and use mt-1 instead of mt-1.5).
- formatTime: always render dates as yyyy/m/d HH:mm regardless of
locale, matching the requested timestamp format.
Use thumbnailUrl/posterUrl (and the image url itself for image-type
attachments) inside the 52x52 box of the file/document bubble, falling
back to the file-type icon when no preview is available.
Also tune the deep-link scroll-mt offset (82px / 98px) so a targeted
bubble lands just below the sticky header.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Recommended cards already routed to /browse#post-<id>, but the stream had
no logic to scroll to the target bubble — and the post might not be paged
in yet. MessageStream now resolves the #post-<id> hash, auto-loads more
pages until the bubble renders, scrolls to it, and gives it a brief gold
highlight. Bubbles get scroll-mt so they clear the sticky header.
Also adds a global floating back-to-top button (BackToTop) mounted in
PublicLayout, shown after scrolling past 400px.
Bundles related staging UI work already present in the working tree.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>