Repository navigation
feat: add a mutuals tab next to followers and following - #1006
Conversation
Lists the people a user follows who follow them back, newest follow first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@kachelle : so the set of friends is the intersection of both followers and following sets? what are the implications of this new abstraction? can we now send messages to each other? my friends will be the only ones I can message on |
|
@younes-io no implications, it's just a list. Messaging works the same as before: if someone follows you, you can start a conversation with them on Remotes, as long as you both have Remotes enabled and neither has blocked the other. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
renamed friendships to mutuals |
There was a problem hiding this comment.
🟢 Approval recommended
The changes are focused, follow existing connection-list patterns, and have no identified blocking issues.
No open issues 🎉
What changed in this PR
Adds a Mutuals tab to profile connection lists, showing people the profile owner follows who follow them back.
Changes:
- Adds a cursor-paginated mutuals endpoint with block-aware access checks.
- Extends connection tabs, empty states, and page metadata for mutuals.
- Adds feature tests and documents the new tab.
| File | Description |
|---|---|
| tests/Feature/Controllers/UserMutualsControllerTest.php | Tests membership, ordering, follow status, blocking, guest access, and metadata. |
| routes/web.php | Registers the mutuals endpoint. |
| resources/js/pages/user/connections.tsx | Adds the Mutuals tab, title, and empty state. |
| KNOWLEDGE_BASE.md | Documents mutual connections. |
| app/Services/PageMetadata.php | Adds mutuals preview metadata and canonical URL. |
| app/Http/Requests/ListUserMutualsRequest.php | Enforces block-aware access to mutuals. |
| app/Http/Controllers/UserMutualsController.php | Queries reciprocal follows and renders the connection list. |
Review effort: Balanced
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
I don't think either “Friendships” or “Mutuals” is a good name. This isn't a new concept or feature where we need to come up with a suitable name. X already has this concept, so I don't see a reason to change the naming.
By the way, I already opened a PR for the same topic a while ago, so it might be worth taking a look at it. |
|
@ashkesarmaa That is not the same concept though... Mutuals is an already existing concept, and it is not the same as Followers you know. Mutuals: the list of people that someone follows that follow them back. |
|
@ashkesarmaa That being said... I think the latter is probably the more valuable list for people visiting a profile. It could also take the form of "followed by ..." on a profile, which could click to show the full list of people you also follow. |
|
its just something different. This 'mutuals' list, is just the intersection. So this is a list of people that mutually know eachother. thats it. Nothing more. 😅 The reason i wanted it was that i was curious who on my list of followers (which is small to be clear 🫣), i also followed. Thats it. |
|
@paulinevos, @kachelle Thanks for the clarification! Sorry, I misunderstood it. 🙂 |
|
@ashkesarmaa np! And I am in favor of your feature. But I would like to have both, in which case I would prefer "followers you know" to have the profile link approach, so that we don't get too many tabs |
|
okey, let me know if and what i should adjust here @paulinevos ! |
|
@kachelle Nothing, just waiting for @ashkesarmaa to confirm the change to link instead of tab on his end. Then we can have both, and I'll merge yours. |
|
lets go! nice chatting folks! 🫶🏼 |
…ips-tab # Conflicts: # KNOWLEDGE_BASE.md # resources/js/pages/user/connections.tsx # routes/web.php
|
Caution Review failedThe pull request is closed. No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Route, access, and mutuals listing app/Http/Requests/ListUserMutualsRequest.php, routes/web.php, app/Http/Controllers/UserMutualsController.php, tests/Feature/Controllers/UserMutualsControllerTest.php |
Adds a public mutuals route and an endpoint that returns cursor-paginated mutual connections. Block relationships between the viewer and profile return a 404. Tests cover filtering, ordering, follow state, guest responses, preview metadata, and partial Inertia loads. |
Connection metadata and page UI app/Services/PageMetadata.php, resources/js/pages/user/connections.tsx, KNOWLEDGE_BASE.md |
Adds mutuals-specific page metadata, a Mutuals tab, and a mutuals empty state. The profile documentation paragraph was replaced with identical text. |
Priority:
Estimated code review effort: 3 (Moderate) | ~20 minutes
Sequence Diagram(s)
sequenceDiagram
participant Visitor
participant WebRoute
participant ListUserMutualsRequest
participant UserMutualsController
participant UserConnectionsQuery
WebRoute->>ListUserMutualsRequest: authorize request
WebRoute->>UserMutualsController: call index
UserMutualsController->>UserConnectionsQuery: query mutual connections
UserConnectionsQuery-->>UserMutualsController: return paginated connections
UserMutualsController-->>Visitor: render connections page
Possibly related PRs
- dev-null-sh/dev-null.sh#733: Adds another connection type and a profile connections tab.
- dev-null-sh/dev-null.sh#1156: Updates user identity, handle-based routes, page metadata, and the connections page used by this change.
- dev-null-sh/dev-null.sh#1157: Changes the profile-backed identity contract used by the mutuals route and response.
Suggested reviewers: nunomaduro, xheaven, simonhamp
Merge Risk: 
Minimal · up to dbe53
-
No actionable merge-blocking risk was identified in the new Mutuals page.
Security architecture risk: 
Minimal · up to dbe53
-
The new page preserves the existing public connections model and checks blocks in both directions. Its results are an intersection of already-public connection lists. No material security risk introduced or worsened by this change was identified.
Retained concerns
No architecture-level concerns identified.Security review details
-
Security Blast Radius
- inferred — Anonymous callers can enumerate mutual relationships for public target profiles. This packages the intersection of information already available through the target's followers and following lists; it grants no relationship-write or privileged service authority.
Trust Boundaries and Controls
- observed — A block in either direction between the authenticated viewer and target profile produces a not-found denial. This matches existing follower/following request authorization. Guests remain allowed under the existing public-list model.
- inferred — Blocks involving individual listed candidates are not filtered, but this behavior predates the PR in both public connection lists. Since a mutual candidate necessarily appears in both existing lists, the new route does not newly bypass a candidate-visibility control.
Resilience and Maintainability Implications
- observed — Feature-test assertions cover both block directions, guest access, exclusion of email, mutual membership, and authenticated follow flags. These assertions were inspected, not executed.
-
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Title check
-
Explanation
The title "feat: add a mutuals tab next to followers and following" matches the main change. The PR adds a Mutuals tab beside Followers and Following on the profile. The raw summary confirms the new controller, route, page type, and PageMetadata support for mutuals. The title is specific and concise, and it follows the conventional commit prefix style. It does not mention the newest-first ordering or the guest/block handling, which is expected for a title.
-
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 6 files. (1 skipped: 1 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
…ips-tab # Conflicts: # KNOWLEDGE_BASE.md # resources/js/pages/user/connections.tsx

When we follow eachother, we are mutuals, introducing a new tab:
mutuals.Desktop:

Iphone SE (!) - so small screen

Summary by CodeRabbit