diff --git a/app/assets/javascripts/discourse/app/components/bookmark-list.js b/app/assets/javascripts/discourse/app/components/bookmark-list.js
index 7272ab73816..09062748c0b 100644
--- a/app/assets/javascripts/discourse/app/components/bookmark-list.js
+++ b/app/assets/javascripts/discourse/app/components/bookmark-list.js
@@ -19,6 +19,11 @@ export default Component.extend({
         bookmark
           .destroy()
           .then(() => {
+            this.appEvents.trigger(
+              "bookmarks:changed",
+              null,
+              bookmark.attachedTo()
+            );
             this._removeBookmarkFromList(bookmark);
             resolve(true);
           })
@@ -52,7 +57,12 @@ export default Component.extend({
   @action
   editBookmark(bookmark) {
     openBookmarkModal(bookmark, {
-      onAfterSave: () => {
+      onAfterSave: (savedData) => {
+        this.appEvents.trigger(
+          "bookmarks:changed",
+          savedData,
+          bookmark.attachedTo()
+        );
         this.reload();
       },
       onAfterDelete: () => {
diff --git a/app/assets/javascripts/discourse/app/components/bookmark.js b/app/assets/javascripts/discourse/app/components/bookmark.js
index 35b8a31a4ee..7f7f53ef718 100644
--- a/app/assets/javascripts/discourse/app/components/bookmark.js
+++ b/app/assets/javascripts/discourse/app/components/bookmark.js
@@ -201,6 +201,7 @@ export default Component.extend({
       post_id: this.model.postId,
       id: this.model.id || response.id,
       name: this.model.name,
+      topic_id: this.model.topicId,
     });
   },
 
diff --git a/app/assets/javascripts/discourse/app/controllers/bookmark.js b/app/assets/javascripts/discourse/app/controllers/bookmark.js
index b47b83b9513..4b0136a31b7 100644
--- a/app/assets/javascripts/discourse/app/controllers/bookmark.js
+++ b/app/assets/javascripts/discourse/app/controllers/bookmark.js
@@ -24,6 +24,7 @@ export function openBookmarkModal(
     let modalController = showModal("bookmark", {
       model: {
         postId: bookmark.post_id,
+        topicId: bookmark.topic_id,
         id: bookmark.id,
         reminderAt: bookmark.reminder_at,
         autoDeletePreference: bookmark.auto_delete_preference,
diff --git a/app/assets/javascripts/discourse/app/controllers/topic.js b/app/assets/javascripts/discourse/app/controllers/topic.js
index 5ebaa903e2d..331db6d8ba2 100644
--- a/app/assets/javascripts/discourse/app/controllers/topic.js
+++ b/app/assets/javascripts/discourse/app/controllers/topic.js
@@ -755,7 +755,11 @@ export default Controller.extend(bufferedProperty("model"), {
           (bookmark) => bookmark.post_id === post.id && !bookmark.for_topic
         );
         return this._modifyPostBookmark(
-          bookmarkForPost || { post_id: post.id, for_topic: false },
+          bookmarkForPost || {
+            post_id: post.id,
+            topic_id: post.topic_id,
+            for_topic: false,
+          },
           post
         );
       } else {
@@ -1231,6 +1235,13 @@ export default Controller.extend(bufferedProperty("model"), {
         this.model.set("bookmarking", false);
         this.model.set("bookmarked", true);
         this.model.incrementProperty("bookmarksWereChanged");
+        this.appEvents.trigger(
+          "bookmarks:changed",
+          savedData,
+          bookmark.attachedTo()
+        );
+
+        // TODO (martin) (2022-02-01) Remove these old bookmark events, replaced by bookmarks:changed.
         this.appEvents.trigger("topic:bookmark-toggled");
       },
       onAfterDelete: (topicBookmarked, bookmarkId) => {
@@ -1300,6 +1311,7 @@ export default Controller.extend(bufferedProperty("model"), {
       const firstPost = await this.model.firstPost();
       return this._modifyTopicBookmark({
         post_id: firstPost.id,
+        topic_id: this.model.id,
         for_topic: true,
       });
     }
diff --git a/app/assets/javascripts/discourse/app/models/bookmark.js b/app/assets/javascripts/discourse/app/models/bookmark.js
index 735e7d00e03..e33f3e1dced 100644
--- a/app/assets/javascripts/discourse/app/models/bookmark.js
+++ b/app/assets/javascripts/discourse/app/models/bookmark.js
@@ -36,6 +36,13 @@ const Bookmark = RestModel.extend({
     });
   },
 
+  attachedTo() {
+    if (this.for_topic) {
+      return { target: "topic", targetId: this.topic_id };
+    }
+    return { target: "post", targetId: this.post_id };
+  },
+
   togglePin() {
     if (this.newBookmark) {
       return Promise.resolve();
diff --git a/app/assets/javascripts/discourse/app/models/post.js b/app/assets/javascripts/discourse/app/models/post.js
index 74d94bb9707..6d2a43d829e 100644
--- a/app/assets/javascripts/discourse/app/models/post.js
+++ b/app/assets/javascripts/discourse/app/models/post.js
@@ -314,6 +314,11 @@ const Post = RestModel.extend({
       bookmark_id: data.id,
     });
     this.topic.incrementProperty("bookmarksWereChanged");
+    this.appEvents.trigger("bookmarks:changed", data, {
+      target: "post",
+      targetId: this.id,
+    });
+    // TODO (martin) (2022-02-01) Remove these old bookmark events, replaced by bookmarks:changed.
     this.appEvents.trigger("page:bookmark-post-toggled", this);
     this.appEvents.trigger("post-stream:refresh", { id: this.id });
   },
@@ -321,8 +326,6 @@ const Post = RestModel.extend({
   deleteBookmark(bookmarked) {
     this.set("topic.bookmarked", bookmarked);
     this.clearBookmark();
-    this.topic.incrementProperty("bookmarksWereChanged");
-    this.appEvents.trigger("page:bookmark-post-toggled", this);
   },
 
   clearBookmark() {
@@ -334,6 +337,12 @@ const Post = RestModel.extend({
       bookmark_auto_delete_preference: null,
     });
     this.topic.incrementProperty("bookmarksWereChanged");
+    this.appEvents.trigger("bookmarks:changed", null, {
+      target: "post",
+      targetId: this.id,
+    });
+    // TODO (martin) (2022-02-01) Remove these old bookmark events, replaced by bookmarks:changed.
+    this.appEvents.trigger("page:bookmark-post-toggled", this);
   },
 
   updateActionsSummary(json) {
diff --git a/app/assets/javascripts/discourse/app/models/topic.js b/app/assets/javascripts/discourse/app/models/topic.js
index eed03afc394..e7c102cfab6 100644
--- a/app/assets/javascripts/discourse/app/models/topic.js
+++ b/app/assets/javascripts/discourse/app/models/topic.js
@@ -386,7 +386,13 @@ const Topic = RestModel.extend({
       "bookmarks",
       this.bookmarks.filter((bookmark) => {
         if (bookmark.id === id && bookmark.for_topic) {
+          // TODO (martin) (2022-02-01) Remove these old bookmark events, replaced by bookmarks:changed.
           this.appEvents.trigger("topic:bookmark-toggled");
+          this.appEvents.trigger(
+            "bookmarks:changed",
+            null,
+            bookmark.attachedTo()
+          );
         }
 
         return bookmark.id !== id;
diff --git a/lib/topic_view.rb b/lib/topic_view.rb
index ec215308268..1f2cb0103b3 100644
--- a/lib/topic_view.rb
+++ b/lib/topic_view.rb
@@ -388,7 +388,7 @@ class TopicView
 
   def bookmarks
     @bookmarks ||= @topic.bookmarks.where(user: @user).joins(:topic).select(
-      :id, :post_id, :for_topic, :reminder_at, :name, :auto_delete_preference
+      :id, :post_id, "topics.id AS topic_id", :for_topic, :reminder_at, :name, :auto_delete_preference
     )
   end