Merge /follows/requests into /notifications as a tabbed inbox

Folds the actionable follow-requests surface into the Notifications page
as a Requests tab (alongside the existing Activity tab), so the navbar
exposes a single bell instead of two adjacent inboxes. The Requests tab
shows a count badge for pending rows regardless of read state, while the
bell badge keeps reflecting the unread-notifications count (which already
covers `follow_request_received` rows). The standalone /follows/requests
URL is preserved as a 301 redirect so prior notification deep-links,
emails, and bookmarks still resolve.

Driven by the IA review captured in docs/information-architecture.md.
Specs (notifications, social-follows, journal-landing) are updated in
the same change to reflect the new structure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-04-26 08:24:59 +02:00
parent 3cd01fe9c0
commit 0306d90de8
15 changed files with 715 additions and 200 deletions

View file

@ -38,7 +38,8 @@ export const users = journalSchema.table("users", {
// Profile visibility / lock setting. `public` means anyone can view
// the profile and follows auto-accept. `private` is Mastodon-style
// locked: the profile renders a stub for non-followers, and follows
// require manual approval (Pending → Accepted via /follows/requests).
// require manual approval (Pending → Accepted via the Requests tab on
// /notifications).
// New users default to `private` to match trails.cool's privacy-first
// content defaults; existing users were backfilled to `public` by an
// earlier migration so behavior didn't change for them.

View file

@ -247,6 +247,10 @@ export default {
markAllRead: "Alle als gelesen markieren",
loadOlder: "Ältere laden",
someone: "Jemand",
tabs: {
activity: "Aktivität",
requests: "Anfragen",
},
summary: {
followRequestReceived: "{{name}} möchte dir folgen",
followReceived: "{{name}} folgt dir jetzt",
@ -321,7 +325,7 @@ export default {
public: "Öffentlich",
publicHelp: "Alle sehen dein Profil und deine öffentlichen Inhalte. Folge-Anfragen werden automatisch akzeptiert.",
private: "Privat (gesperrt)",
privateHelp: "Besucher:innen sehen nur eine Hinweisseite mit Anfrage-Button. Nur akzeptierte Follower sehen deine öffentlichen Inhalte. Anfragen verwaltest du unter /follows/requests.",
privateHelp: "Besucher:innen sehen nur eine Hinweisseite mit Anfrage-Button. Nur akzeptierte Follower sehen deine öffentlichen Inhalte. Anfragen verwaltest du im Reiter „Anfragen“ unter /notifications.",
},
},
security: {

View file

@ -247,6 +247,10 @@ export default {
markAllRead: "Mark all read",
loadOlder: "Load older",
someone: "Someone",
tabs: {
activity: "Activity",
requests: "Requests",
},
summary: {
followRequestReceived: "{{name}} requested to follow you",
followReceived: "{{name}} started following you",
@ -321,7 +325,7 @@ export default {
public: "Public",
publicHelp: "Anyone can view your profile and your public content. Follows auto-accept.",
private: "Private (locked)",
privateHelp: "Visitors see a stub with a Request-to-follow button. Only accepted followers see your public content. You manage requests at /follows/requests.",
privateHelp: "Visitors see a stub with a Request-to-follow button. Only accepted followers see your public content. You manage requests in the Requests tab on /notifications.",
},
},
security: {