Skip to content

Epic: Posts page rebuild — chat-style threaded feed, reactions, bookmarks, search #969

Description

@arturasmckwcz

Overview

Supersedes #892. #892 shipped as a placeholder (disabled Send button, no-op textarea) and its written scope covered only flat posting + @mention + opportunity linking. Since then two rounds of prototype feedback landed on that issue and expanded the scope substantially — this epic replaces #892's plan with the up-to-date one.

Round 1 — proposal

Main composer for creating new posts; inline replies directly inside each post thread; replies to replies grouped within the same reply card; reply counts with collapsed replies to save space; newest reply shown as a full card and older replies as compact previews; author, date, time, and original-message context; three-dot menus for editing and deleting posts and replies; confirmation pop-up before deletion; emoji reactions with quick options and a full searchable picker; icon-only bookmark for "Save for later"; live @mention suggestions, including @ALL; opportunity linking with automatic dropdown dismissal; search across posts, replies, people, and opportunities; people widget for filtering posts by community member; "More posts" for older content.

Round 2 — amendment (supersedes conflicting parts of round 1)

Posts now follow the chat direction, with the oldest at the top and newest at the bottom. The post composer was moved to the bottom. The same composer is used for creating posts and writing replies. Replies remain connected to their original posts and appear in expandable threads. Replies to replies are grouped beneath their parent reply. The reply count includes all responses in the conversation. The composer now includes an emoji picker. Multiple opportunities can be linked to one post.

Note on the amendment: "oldest top / newest bottom" + bottom composer reverses #892's original "newest first" + implicit top-composer assumption — sub-issues below reflect the amended (current) direction.

Round 3 — final approval corrections (2026-09-01)

Reviewed against the final approved prototype. These correct/clarify Round 1 & 2 and supersede any conflicting detail above, in particular Round 1's collapsed-reply display model (point 2 below):

  1. No separate inline reply fields — the same bottom composer used for posts switches into reply mode, showing the target's author, timestamp, and original-message context.
  2. Drops Round 1's "newest reply shown as a full card, older replies as compact previews" — once a thread is expanded, all its replies render as full cards.
  3. Replies-to-replies appear directly beneath their parent reply with a small indent + connector line, grouped in that same reply conversation — not unlimited recursive nesting.
  4. Threads are collapsed by default; after sending a reply the expanded thread stays open so the reply can be reviewed; it collapses on leaving the conversation, pressing Escape, or "Hide replies".
  5. Reply count includes every response in the conversation (direct replies + replies-to-replies) — confirms Round 2, no change.
  6. People-widget filtering matches conversations where the person authored the post or a reply in it — see phased plan below.
  7. Opportunity picker: multiple opportunities selectable, picker stays open during selection, closes via "Done" or on leaving it; selected opportunities show as removable chips.
  8. @all used consistently; mentions insert at the cursor position, including into existing or pasted text.

Phased plan for point 6 (people filter): ship v1 scoped to post-author matching only (unblocked as soon as be#930 lands — no dependency on replies existing yet). Extend to reply-author matching in a v2 follow-up once be#927 (replies) ships, implemented as a query-only addition to be#930's existing search/filter (LEFT JOIN reply ... OR reply.author_id = :id, DISTINCT post.id) — no schema change, no new endpoint. A match always surfaces the whole post/conversation card, reusing the existing post-card component, so no new result-rendering path is needed.

Backend is not fully ready this time

#892 stated "the backend is already fully ready ... this is a frontend-only build" — true for the original flat-post scope (be#680: Post entity + GET/POST/PATCH/DELETE /post), but not true for replies, reactions, bookmarks, or search, none of which exist in the backend today. Per the SDK-contract-first rule, those need backend + SDK work before the corresponding FE sub-issue can start:

Pick order (work one issue at a time, in this sequence)

Grooming is complete (Round 3 above closes out the open display/interaction questions) — all sub-issues below are ready for dev. Order reflects dependency: foundational feed/card/composer first, then backend-blocked features as their contracts land, translations last since copy should be stable before auditing it.

  1. feat: Posts feed — chat-direction ordering (oldest top, newest bottom) + pagination #962 — Feed: chat-direction ordering (oldest top, newest bottom) + pagination — not blocked
  2. feat: Post card — author/tags/opportunity chips, three-dot edit/delete menu with confirm dialog #963 — Post card: author/tags/opportunity chips, three-dot edit/delete menu with confirm dialog — not blocked
  3. feat: Posts composer — free text, @mention (incl. @all), multi-opportunity picker, emoji picker #961 — Posts composer: free text, @mention (incl. @ALL), multi-opportunity picker, emoji picker — not blocked
  4. feat: threaded replies UI — inline replies, grouped replies-to-replies, collapsed older replies #964 — Threaded replies UI — blocked on feat: threaded replies to Posts — Reply entity + endpoints be#927
  5. feat: emoji reactions on posts and replies (quick bar + searchable picker) #965 — Emoji reactions UI — blocked on feat: emoji reactions on Posts and replies be#928
  6. feat: bookmark ("save for later") icon on posts #966 — Bookmark ("save for later") icon — blocked on feat: bookmark ("save for later") on Posts be#929
  7. feat: search bar (posts/replies/people/opportunities) + People widget filter #967 — Search bar + People widget — People-widget v1 (post-author filter) is unblocked once feat: Posts composer — free text, @mention (incl. @all), multi-opportunity picker, emoji picker #961feat: Post card — author/tags/opportunity chips, three-dot edit/delete menu with confirm dialog #963 land; full search + v2 (reply-author filter) blocked on feat: search endpoint for Posts feed (posts, replies, people, opportunities) be#930 / be#927
  8. chore: Posts page translations (en/de) #968 — Translations (en/de) audit pass — do last, once copy from feat: Posts composer — free text, @mention (incl. @all), multi-opportunity picker, emoji picker #961feat: search bar (posts/replies/people/opportunities) + People widget filter #967 is stable

Open questions to resolve during grooming

Acceptance criteria

Supersedes: #892

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions