diff --git a/app/assets/javascripts/discourse/components/notification_item_component.js b/app/assets/javascripts/discourse/components/notification_item_component.js
new file mode 100644
index 000000000..238f79651
--- /dev/null
+++ b/app/assets/javascripts/discourse/components/notification_item_component.js
@@ -0,0 +1,11 @@
+Discourse.NotificationItemComponent = Ember.Component.extend({
+  tagName: 'span',
+  didInsertElement: function(){
+    var self = this;
+    this.$('a').click(function(){
+      self.set('model.read', true);
+      self.rerender();
+      return true;
+    });
+  }
+});
diff --git a/app/assets/javascripts/discourse/controllers/header.js.es6 b/app/assets/javascripts/discourse/controllers/header.js.es6
index dcfe1ee6d..ca4198d52 100644
--- a/app/assets/javascripts/discourse/controllers/header.js.es6
+++ b/app/assets/javascripts/discourse/controllers/header.js.es6
@@ -16,6 +16,10 @@ export default Discourse.Controller.extend({
     return Discourse.User.current() && !this.get('topic.isPrivateMessage');
   }.property('topic.isPrivateMessage'),
 
+  resetCachedNotifications: function(){
+    this.set("notifications", null);
+  }.observes("currentUser.lastNotificationChange"),
+
   actions: {
     toggleStar: function() {
       var topic = this.get('topic');
@@ -29,10 +33,11 @@ export default Discourse.Controller.extend({
       if (self.get('currentUser.unread_notifications') || self.get('currentUser.unread_private_messages') || !self.get('notifications')) {
         self.set("loading_notifications", true);
         Discourse.ajax("/notifications").then(function(result) {
+          self.set('currentUser.unread_notifications', 0);
+
           self.setProperties({
             notifications: result,
-            loading_notifications: false,
-            'currentUser.unread_notifications': 0
+            loading_notifications: false
           });
         });
       }
diff --git a/app/assets/javascripts/discourse/initializers/subscribe-user-notifications.js.es6 b/app/assets/javascripts/discourse/initializers/subscribe-user-notifications.js.es6
index 8922f42c5..69deb2c28 100644
--- a/app/assets/javascripts/discourse/initializers/subscribe-user-notifications.js.es6
+++ b/app/assets/javascripts/discourse/initializers/subscribe-user-notifications.js.es6
@@ -18,8 +18,15 @@ export default {
         });
       }
       bus.subscribe("/notification/" + user.get('id'), (function(data) {
+        var oldUnread = user.get('unread_notifications');
+        var oldPM = user.get('unread_private_messages');
+
         user.set('unread_notifications', data.unread_notifications);
         user.set('unread_private_messages', data.unread_private_messages);
+
+        if(oldUnread !== data.unread_notifications || oldPM !== data.unread_private_messages) {
+          user.set('lastNotificationChange', new Date());
+        }
       }), user.notification_channel_position);
 
       bus.subscribe("/categories", function(data){
diff --git a/app/assets/javascripts/discourse/templates/components/notification-item.js.handlebars b/app/assets/javascripts/discourse/templates/components/notification-item.js.handlebars
new file mode 100644
index 000000000..50879cae4
--- /dev/null
+++ b/app/assets/javascripts/discourse/templates/components/notification-item.js.handlebars
@@ -0,0 +1 @@
+{{unbound boundI18n scope linkBinding="model.link" usernameBinding="model.username"}}
diff --git a/app/assets/javascripts/discourse/templates/notifications.js.handlebars b/app/assets/javascripts/discourse/templates/notifications.js.handlebars
index f86ddcb4d..dd856989e 100644
--- a/app/assets/javascripts/discourse/templates/notifications.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/notifications.js.handlebars
@@ -3,7 +3,7 @@
     {{#if content}}
       <ul>
         {{#each}}
-          <li {{bind-attr class="read"}}>{{unbound boundI18n scope linkBinding="link" usernameBinding="username"}}</li>
+        <li {{bind-attr class="read"}}>{{notification-item model=this scope=scope}}</li>
         {{/each}}
         <li class="read last">
           <a {{bind-attr href="currentUser.path"}}>{{i18n notifications.more}} &hellip;</a>
diff --git a/app/models/notification.rb b/app/models/notification.rb
index 93ba30ecd..4713d9c86 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -123,12 +123,7 @@ class Notification < ActiveRecord::Base
   protected
 
   def refresh_notification_count
-    user_id = user.id
-    MessageBus.publish("/notification/#{user_id}",
-      {unread_notifications: user.unread_notifications,
-       unread_private_messages: user.unread_private_messages},
-      user_ids: [user_id] # only publish the notification to this user
-    )
+    user.publish_notifications_state
   end
 
 end
diff --git a/app/services/post_alerter.rb b/app/services/post_alerter.rb
index 6c44b706d..d0b53713d 100644
--- a/app/services/post_alerter.rb
+++ b/app/services/post_alerter.rb
@@ -76,6 +76,8 @@ class PostAlerter
 
     user.notifications.where(notification_type: type,
                              topic_id: topic.id).destroy_all
+    # HACK so notification counts sync up correctly
+    user.reload
   end
 
   def create_notification(user, type, post, opts={})