Skip to main content

Saved Posts

Members can bookmark posts and reopen them later from a private Saved collection. Saves are per user — other members cannot see what you saved.

Overview

Saved posts let users:

  • Bookmark a post from the feed, profile, hashtag pages, or post detail
  • Browse saved posts newest-first on Saved (/profile/saved)
  • Remove a bookmark from the post card or from the Saved page
  • See whether a post is already saved (isSaved) on feed and post responses

Saves do not change post privacy, notify the author, or appear in public profiles.

In the app (UI)

Save or unsave a post

  1. Open any post (feed, profile, hashtag, or post detail).
  2. Use the bookmark control on the post card (Save / Remove from saved).
  3. A toast confirms success or shows an error if the request fails.

Open your Saved collection

  • Profile menu → Saved posts, or
  • Navigate to /profile/saved

The page lists posts you can still see, newest saves first, with pagination. Unsaving a post removes it from the list immediately.

You must be signed in. Guests see a sign-in prompt on the Saved page.

API

All endpoints use api/Post and require authentication (User, Moderator, or Admin).

Save a post

POST /api/Post/{postId}/save
Authorization: Bearer {token}

Response (success):

{
"success": true,
"message": "Post saved",
"data": {
"isSaved": true
}
}

Saving an already-saved post is idempotent (isSaved: true).

Unsave a post

DELETE /api/Post/{postId}/save
Authorization: Bearer {token}

Response (success):

{
"success": true,
"message": "Post unsaved",
"data": {
"isSaved": false
}
}

List saved posts

GET /api/Post/saved?page=1&pageSize=10
Authorization: Bearer {token}
ParameterTypeDefaultDescription
pageint1Page number (1-based)
pageSizeint10Posts per page

Response (success):

{
"success": true,
"data": {
"posts": [],
"totalCount": 0,
"page": 1,
"pageSize": 10,
"totalPages": 0,
"hasMore": false
}
}

Each post in posts includes the usual post DTO fields and isSaved: true.

isSaved on other reads

When the caller is authenticated, feed, user posts, hashtag posts, and single-post responses include isSaved so the UI can show the bookmark state without a separate round trip.

Visibility rules

The Saved list only returns posts the current user is allowed to see:

  • Your own posts (any visibility), or
  • Posts that are Public and not hidden

If a saved post becomes private, hidden, or deleted, it no longer appears in /api/Post/saved (and deleted posts cascade-remove the save row).

Data model

PostgreSQL table SavedPosts:

ColumnNotes
IdUUID primary key
UserIdOwner of the save (FK → Users, cascade delete)
PostIdSaved post (FK → Posts, cascade delete)
CreatedAtWhen the post was saved (list sorts newest first)

Unique index on (UserId, PostId) — one save per user per post.

On self-host upgrades, schema may come from db-migration / custom migrations, or the hotfix SQL under tools/hotfix/2026-09-07-saved-posts.sql if the publisher instructs a manual apply. See Release notes.