diff --git a/app/controllers/aspects_controller.rb b/app/controllers/aspects_controller.rb
index 8c94858d3fadadeb70f8af4c45ba963c8828ad58..57f67a52d10019ae3da54eef47ffd5aab5000cb6 100644
--- a/app/controllers/aspects_controller.rb
+++ b/app/controllers/aspects_controller.rb
@@ -28,7 +28,7 @@ class AspectsController < ApplicationController
       redirect_to getting_started_path
       return
     end
-    
+
     # redirect to aspects creation
     if @aspects.blank?
       redirect_to new_aspect_path
@@ -47,7 +47,7 @@ class AspectsController < ApplicationController
                                            :type => ['StatusMessage','ActivityStreams::Photo'],
                                            :order => session[:sort_order] + ' DESC',
                                            :max_time => params[:max_time].to_i
-                          ).includes({:comments => {:author => :profile}}, {:mentions => {:person => :profile}})
+                          ).includes(:mentions => {:person => :profile})
 
     @posts = PostsFake.new(posts)
     if params[:only_posts]
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index d472e457fd462fbfbc2abc6b42b180348b81cfe0..3965c87d62e17ab99db2341e5e4e9aa8b00ed8a5 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -6,7 +6,8 @@ class CommentsController < ApplicationController
   include ApplicationHelper
   before_filter :authenticate_user!
 
-  respond_to :html, :mobile
+  respond_to :html, :mobile, :only => [:create, :destroy]
+  respond_to :js, :only => [:index]
 
   rescue_from ActiveRecord::RecordNotFound do
     render :nothing => true, :status => 404
@@ -53,4 +54,14 @@ class CommentsController < ApplicationController
     end
   end
 
+  def index
+    @post = current_user.find_visible_post_by_id(params[:post_id])
+    if @post
+      @comments = @post.comments.includes(:author => :profile)
+      render :layout => false
+    else
+      raise ActiveRecord::RecordNotFound.new
+    end
+  end
+
 end
diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb
index 574f859966de6b7ec7f5e90c27d3a1a1f9e084a4..ef1a2bcedd6b9da83e450c65e6d070f01f45ac9f 100644
--- a/app/helpers/comments_helper.rb
+++ b/app/helpers/comments_helper.rb
@@ -4,11 +4,11 @@
 
 module CommentsHelper
   GSUB_THIS = "FIUSDHVIUSHDVIUBAIUHAPOIUXJM"
-  def comment_toggle(count, commenting_disabled=false)
-    if count <= 3
-      str = link_to "#{t('stream_helper.hide_comments')}", '#', :class => "show_post_comments"
+  def comment_toggle(post, commenting_disabled=false)
+    if post.comments.size <= 3
+      str = link_to "#{t('stream_helper.hide_comments')}", post_comments_path(post.id), :class => "toggle_post_comments"
     else
-      str = link_to "#{t('stream_helper.show_more_comments', :number => count-3)}", '#', :class => "show_post_comments"
+      str = link_to "#{t('stream_helper.show_more_comments', :number => post.comments.size - 3)}", post_comments_path(post.id), :class => "toggle_post_comments"
     end
     str
   end
diff --git a/app/models/post.rb b/app/models/post.rb
index db3434726b0987f69db8e3e5bc77a0fcb514fe81..97de06edccdd879d63c0c33613076ea341acf42e 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -13,7 +13,7 @@ class Post < ActiveRecord::Base
   xml_attr :public
   xml_attr :created_at
 
-  has_many :comments, :order => 'created_at ASC', :dependent => :destroy
+  has_many :comments, :dependent => :destroy
   has_many :likes, :conditions => {:positive => true}, :dependent => :delete_all
   has_many :dislikes, :conditions => {:positive => false}, :class_name => 'Like', :dependent => :delete_all
 
@@ -111,5 +111,10 @@ class Post < ActiveRecord::Base
   def activity_streams?
     false
   end
+
+  # @return [Array<Comment>]
+  def last_three_comments
+    self.comments.order('created_at DESC').limit(3).includes(:author => :profile).reverse
+  end
 end
 
diff --git a/app/views/comments/_comments.haml b/app/views/comments/_comments.haml
index a4e155b999473e593a3abce4d7c8ba6dcc3aab95..304550afccb81dcd0a69e2d7e9be74e0bad94557 100644
--- a/app/views/comments/_comments.haml
+++ b/app/views/comments/_comments.haml
@@ -3,18 +3,16 @@
 -#   the COPYRIGHT file.
 
 - unless comments_expanded
-  %ul.show_comments{:class => ("hidden" if comments.size <= 3)}
+  %ul.show_comments{:class => ("hidden" if post.comments.size <= 3)}
     %li
-      %b= comment_toggle(comments.size)
+      %b= comment_toggle( post)
 
-%ul.comments{:id => post.id, :class => ("hidden" if comments.size == 0 && !comments_expanded)}
-  -if comments.size > 3
-    .older_comments{:class => ("hidden inactive" unless comments_expanded)}
-      = render :partial => 'comments/comment', :collection => comments[0..-4], :locals => {:post => post}
-    = render :partial => 'comments/comment', :collection => comments[-3, 3], :locals => {:post => post}
+%ul.comments{:id => post.id, :class => ('loaded' if post.comments.size <= 3)}
+  -if post.comments.size > 3 && !comments_expanded
+    = render :partial => 'comments/comment', :collection => post.last_three_comments, :locals => {:post => post}
   -else
-    = render :partial => 'comments/comment', :collection => comments, :locals => {:post => post}
+    = render :partial => 'comments/comment', :collection => post.comments, :locals => {:post => post}
 
-  - unless @commenting_disabled
-    %li.comment.show
-      = new_comment_form(post.id, current_user)
+- unless @commenting_disabled
+  .new_comment_form_wrapper{:class => ( 'hidden' if post.comments.size == 0)}
+    = new_comment_form(post.id, current_user)
diff --git a/app/views/comments/index.html.haml b/app/views/comments/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..83963707982936feb7a8dd54cfd39e5fc2365b58
--- /dev/null
+++ b/app/views/comments/index.html.haml
@@ -0,0 +1 @@
+= render :partial => 'comments/comment', :collection => @comments, :locals => {:post => @post}
diff --git a/app/views/shared/_stream_element.html.haml b/app/views/shared/_stream_element.html.haml
index 9cd085270c6be97c7db1ca8868cfc6568dbc72bb..113f47c28e8f49e4f20e96cff78a9a239d7eb701 100644
--- a/app/views/shared/_stream_element.html.haml
+++ b/app/views/shared/_stream_element.html.haml
@@ -59,4 +59,4 @@
         - if post.likes_count > 0
           = render "likes/likes_container", :post_id => post.id, :likes_count => post.likes_count, :current_user => current_user
 
-      = render "comments/comments", :post => post, :comments => post.comments, :current_user => current_user, :commenting_disabled => (defined?(@commenting_disabled) && @commenting_disabled)
+      = render "comments/comments", :post => post, :current_user => current_user, :commenting_disabled => (defined?(@commenting_disabled) && @commenting_disabled)
diff --git a/config/routes.rb b/config/routes.rb
index b65608746fc2953c19367bfeec7a72e411d97998..1a79267626e6adab3a57a7e22d9cfcd82d1418a1 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -16,7 +16,7 @@ Diaspora::Application.routes.draw do
 
   resources :posts, :only => [:show, :destroy] do
     resources :likes, :only => [:create, :destroy, :index]
-    resources :comments, :only => [:create, :destroy]
+    resources :comments, :only => [:create, :destroy, :index]
   end
 
   get 'bookmarklet' => 'status_messages#bookmarklet'
diff --git a/features/step_definitions/comment_steps.rb b/features/step_definitions/comment_steps.rb
index b4c5fad5bf5fb1e1d96d1ed1cd722a65a9304151..514be350450bbee8f56042be5e5c6b2c73915bde 100644
--- a/features/step_definitions/comment_steps.rb
+++ b/features/step_definitions/comment_steps.rb
@@ -7,11 +7,9 @@ When /^I open the comment box$/ do
 end
 
 Then /^the first comment field should be open/ do
-  css_query = "$('#main_stream .stream_element:first ul.comments:visible')"
-  page.evaluate_script("#{css_query}.length").should == 1
+  find("#main_stream .stream_element .new_comment").should be_visible
 end
 
 Then /^the first comment field should be closed$/ do
-  css_query = "$('#main_stream .stream_element:first ul.comments:hidden')"
-  page.evaluate_script("#{css_query}.length").should == 1
+  find("#main_stream .stream_element .new_comment").should_not be_visible
 end
diff --git a/lib/fake.rb b/lib/fake.rb
index 4aaccd51953c71adfdda65a6cf6a6b947f523295..3466e018d9b563ae39221e24799d4834ac0deaa5 100644
--- a/lib/fake.rb
+++ b/lib/fake.rb
@@ -6,9 +6,6 @@ class PostsFake
     author_ids = []
     posts.each do |p|
       author_ids << p.author_id
-      p.comments.each do |c|
-        author_ids << c.author_id
-      end
     end
 
     people = Person.where(:id => author_ids).includes(:profile)
@@ -17,9 +14,6 @@ class PostsFake
 
     @post_fakes = posts.map do |post|
       f = Fake.new(post, self)
-      f.comments = post.comments.map do |comment|
-        Fake.new(comment, self)
-      end
       f
     end
   end
@@ -29,7 +23,6 @@ class PostsFake
   end
 
   class Fake
-    attr_accessor :comments
     attr_reader :model
     def initialize(model, fakes_collection)
       @fakes_collection = fakes_collection
diff --git a/public/javascripts/stream.js b/public/javascripts/stream.js
index 55d03ce999e9e4bcc053be65bab12ac95e229518..690f476129a2c7f8799c70ab377da5c04a84d86a 100644
--- a/public/javascripts/stream.js
+++ b/public/javascripts/stream.js
@@ -52,7 +52,7 @@ var Stream = {
   },
 
   setUpComments: function(){
-    $("a.show_post_comments:not(.show)", this.selector).live('click', Stream.toggleComments);
+    $("a.toggle_post_comments:not(.show)", this.selector).live('click', Stream.toggleComments);
     // comment link form focus
     $(".focus_comment_textarea", this.selector).live('click', function(evt) {
       Stream.focusNewComment($(this), evt);
@@ -66,7 +66,7 @@ var Stream = {
       var element = $(this),
         target = element.parents(".comment"),
         post = element.closest(".stream_element"),
-        toggler = post.find(".show_post_comments");
+        toggler = post.find(".toggle_post_comments");
 
       target.hide("blind", { direction: "vertical" }, 300, function() {
         $(this).remove();
@@ -126,42 +126,58 @@ var Stream = {
 
   toggleComments: function(evt) {
     evt.preventDefault();
-    var $this = $(this),
-      showUl = $(this).closest("li"),
-      commentBlock = $this.closest(".stream_element").find("ul.comments", ".content"),
-      commentBlockMore = $this.closest(".stream_element").find(".older_comments", ".content")
-
-    if( commentBlockMore.hasClass("inactive") ) {
-      commentBlockMore.fadeIn(150, function() {
-        commentBlockMore.removeClass("inactive");
-        commentBlockMore.removeClass("hidden");
+
+    var $toggler = $(this),
+        comments = $toggler.closest('.stream_element').find('ul.comments');
+
+    if (comments.hasClass('loaded') && !comments.hasClass('hidden')){
+      Stream.hideComments.apply($toggler);
+    }else {
+      Stream.showComments.apply($toggler);
+    }
+  },
+  showComments: function(){
+    var commentList = this.closest('.stream_element').find('ul.comments'),
+        toggle = this;
+
+    if( commentList.hasClass('loaded') ){
+        toggle.html(Diaspora.widgets.i18n.t("comments.hide"));
+        commentList.removeClass('hidden');
+    }
+    else {
+      toggle.append("<img alt='loading' src='/images/ajax-loader.gif' />");
+      $.ajax({
+        url: this.attr('href'),
+        success: function(data){
+          toggle.html(Diaspora.widgets.i18n.t("comments.hide"));
+          commentList.html(data)
+                     .addClass('loaded');
+          Diaspora.widgets.publish("stream/scrolled")
+        }
       });
-      $this.html(Diaspora.widgets.i18n.t("comments.hide"));
-    } else {
-      if(commentBlock.hasClass("hidden")) {
-        commentBlock.removeClass("hidden");
-        showUl.css("margin-bottom","-1em");
-        $this.html(Diaspora.widgets.i18n.t("comments.hide"));
-      }else{
-        commentBlock.addClass("hidden");
-        showUl.css("margin-bottom","1em");
-        $this.html(Diaspora.widgets.i18n.t("comments.show"));
-      }
     }
   },
 
+  hideComments: function(){
+    var commentList = this.closest('.stream_element').find('ul.comments');
+    commentList.addClass('hidden');
+    this.html(Diaspora.widgets.i18n.t("comments.show"));
+  },
+
   focusNewComment: function(toggle, evt) {
     evt.preventDefault();
-    var commentBlock = toggle.closest(".stream_element").find("ul.comments", ".content");
+    var post = toggle.closest(".stream_element");
+    var commentBlock = post.find(".new_comment_form_wrapper");
+    var textarea = post.find(".new_comment textarea");
 
     if(commentBlock.hasClass("hidden")) {
       commentBlock.removeClass("hidden");
-      commentBlock.find("textarea").focus();
+      textarea.focus();
     } else {
       if(commentBlock.children().length <= 1) {
         commentBlock.addClass("hidden");
       } else {
-        commentBlock.find("textarea").focus();
+        textarea.focus();
       }
     }
   }
diff --git a/public/javascripts/web-socket-receiver.js b/public/javascripts/web-socket-receiver.js
index 76761a29aa8d260fd542eb18b90ee9fb49ea5f68..ddd36e35486e3874e9b9fa8f599036b9610bfe3e 100644
--- a/public/javascripts/web-socket-receiver.js
+++ b/public/javascripts/web-socket-receiver.js
@@ -97,16 +97,16 @@ var WebSocketReceiver = {
           $(html).fadeIn("fast", function(){})
         );
       } else {
-        $('.comments li:last', post).before(
+        $('.comments', post).append(
           $(html).fadeIn("fast", function(){})
         );
       }
 
-      var toggler = $('.show_post_comments', post).parent();
+      var toggler = $('.toggle_post_comments', post).parent();
 
       if(toggler.length > 0){
         toggler.html(
-          toggler.html().replace(/\d+/,$('.comments', post).find('li').length -1)
+          toggler.html().replace(/\d+/,$('.comments', post).find('li').length)
         );
 
         if( !$(".comments", post).is(':visible') ) {
diff --git a/public/stylesheets/sass/application.sass b/public/stylesheets/sass/application.sass
index c13d41ee456747493cd9cd9ac00ca95f35f27e0d..f4b960511a89513bbc7ca6a5abf756555422fa23 100644
--- a/public/stylesheets/sass/application.sass
+++ b/public/stylesheets/sass/application.sass
@@ -481,11 +481,6 @@ ul.as-selections
       :font
         :size 1em
 
-  .comments
-    :padding
-      :bottom 6px
-    > li:last-child
-      :border-bottom none
   .comment_box
     :width 475px
     :margin
@@ -552,23 +547,6 @@ ul.as-selections
       :background none
       :border none
 
-
-.stream ul.comments
-  :padding
-    :bottom 6px
-
-  > li:last-child
-    :border-bottom none
-
-  .avatar
-    :width 30px
-    :height 30px
-
-  .comment_box
-    :margin
-      :bottom 5px
-
-
 .submit_button
   :text
     :align right
@@ -576,8 +554,12 @@ ul.as-selections
 ul.comments,
 ul.show_comments,
 .likes_container
+
+  .avatar
+    :width 30px
+    :height 30px
+
   :margin 0
-    :top 0.5em
   :padding 0
 
   :font
@@ -587,14 +569,6 @@ ul.show_comments,
 
   :position relative
 
-  form
-    textarea
-      :width 365px
-      :height 21px
-
-  input
-    :display none
-
   li
     :list
       :style none
@@ -603,12 +577,6 @@ ul.show_comments,
     :border
       :bottom 1px dotted #aaa
 
-    .new_comment
-      :min-height 35px
-      p
-        :margin
-          :bottom 0
-
     .from
       :font
         :size 1em
@@ -627,7 +595,7 @@ ul.show_comments,
       :padding
         :left 36px
         :right 10px
-        
+
       p
         :margin
           :bottom 0
@@ -636,41 +604,68 @@ ul.show_comments,
     .right
       :right 4px
 
-    form
+    .avatar
+      :position absolute
+      :display inline
+
+ul.show_comments
+  :padding
+    :bottom 6px
+  :margin
+    :top 6px
+
+form.new_comment
+  :padding 8px 5px
+  .avatar
+    :position absolute
+    :display inline
+    :width 30px
+    :height 30px
+
+  :min-height 35px
+
+  input
+    :display none
+
+  :margin
+    :bottom -4px
+
+  :font
+    :size 1em
+
+  .submit_button
+    input
       :margin
-        :top -5px
-        :bottom -4px
-      :font
-        :size 1em
+        :right 0
 
-      .submit_button
-        input
-          :margin
-            :right 0
+  textarea
+    :width 365px
+    :height 21px
 
-      textarea
-        :font
-          :size 1em
-        :margin
-          :bottom -3px
+    :font
+      :size 1em
+    :margin
+      :top 0
+      :bottom -3px
 
-      p
-        :position relative
-        :left 35px
+  p
+    :margin
+      :bottom 0
+      :top -10px
+    :position relative
+    :left 35px
 
-    .avatar
-      :position absolute
-      :display inline
+  &.open
+    .submit_button
+      :display block
+      :margin
+        :top 5px
+        :bottom 2px
+        :right 2px
+
+    input
+      :display inline-block
 
-    form.open
-      .submit_button
-        :display block
-        :margin
-          :top 5px
-          :bottom 2px
-          :right 2px
-      input
-        :display inline-block
 
 .comments
   .timeago
@@ -2209,8 +2204,6 @@ h3,h4
 
 
 ul.show_comments
-  :margin
-    :bottom -0.5em
   :border
     :top 1px dotted #aaa
 
diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb
index 31a0e3ad8c782111d2663b74ced3cbc31adcd15c..e7a38b33096c6f086fe88d6a9b35dcea11e29b32 100644
--- a/spec/controllers/comments_controller_spec.rb
+++ b/spec/controllers/comments_controller_spec.rb
@@ -117,4 +117,25 @@ describe CommentsController do
       response.body.strip.should be_empty
     end
   end
+
+  describe '#index' do
+    before do
+      @message = bob.post(:status_message, :text => "hey", :to => bob.aspects.first.id)
+      @comments = [alice, bob, eve].map{ |u| u.comment("hey", :post => @message) }
+    end
+    it 'returns all the comments for a post' do
+      get :index, :post_id => @message.id, :format => 'js'
+      assigns[:comments].should == @comments
+    end
+    it 'returns a 404 on a nonexistent post' do
+      get :index, :post_id => 235236, :format => 'js'
+      response.status.should == 404
+    end
+    it 'returns a 404 on a post that is not visible to the signed in user' do
+      message = eve.post(:status_message, :text => "hey", :to => eve.aspects.first.id)
+      bob.comment("hey", :post => @message)
+      get :index, :post_id => message.id, :format => 'js'
+      response.status.should == 404
+    end
+  end
 end
diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb
index a591c399caea2638f25bde79fd8a3900a079db99..274f1ce0833f560aeb373b9dfb27974bdb59f3c8 100644
--- a/spec/models/post_spec.rb
+++ b/spec/models/post_spec.rb
@@ -51,6 +51,15 @@ describe Post do
     end
   end
 
-  describe '#receive' do
+  describe '#last_three_comments' do
+    it 'returns the last three comments of a post' do
+      post = bob.post :status_message, :text => "hello", :to => 'all'
+      created_at = Time.now - 100
+      comments = [alice, eve, bob, alice].map do |u|
+        created_at = created_at + 10
+        u.comment("hey", :post => post, :created_at => created_at)
+      end
+      post.last_three_comments.map{|c| c.id}.should == comments[1,3].map{|c| c.id}
+    end
   end
 end