diff --git a/app/assets/javascripts/discourse/controllers/group_controller.js b/app/assets/javascripts/discourse/controllers/group_controller.js
index c6efff8fe..3fa523e0d 100644
--- a/app/assets/javascripts/discourse/controllers/group_controller.js
+++ b/app/assets/javascripts/discourse/controllers/group_controller.js
@@ -1,3 +1,11 @@
+/**
+  The basic controller for a group
+
+  @class GroupController
+  @extends Discourse.ObjectController
+  @namespace Discourse
+  @module Discourse
+**/
 Discourse.GroupController = Discourse.ObjectController.extend({
 
   // It would be nice if bootstrap marked action lists as selected when their links
diff --git a/app/assets/javascripts/discourse/controllers/group_index_controller.js b/app/assets/javascripts/discourse/controllers/group_index_controller.js
new file mode 100644
index 000000000..ec2d196cb
--- /dev/null
+++ b/app/assets/javascripts/discourse/controllers/group_index_controller.js
@@ -0,0 +1,32 @@
+/**
+  Handles displaying posts within a group
+
+  @class GroupIndexController
+  @extends Ember.ArrayController
+  @namespace Discourse
+  @module Discourse
+**/
+Discourse.GroupIndexController = Ember.ArrayController.extend({
+  needs: ['group'],
+  loading: false,
+
+  actions: {
+    loadMore: function() {
+
+      if (this.get('loading')) { return; }
+      this.set('loading', true);
+      var posts = this.get('model'),
+          self = this;
+      if (posts && posts.length) {
+        var lastPostId = posts[posts.length-1].get('id'),
+            group = this.get('controllers.group.model');
+
+        group.findPosts({beforePostId: lastPostId}).then(function(newPosts) {
+          posts.addObjects(newPosts);
+          self.set('loading', false);
+        });
+      }
+    }
+  }
+});
+
diff --git a/app/assets/javascripts/discourse/models/group.js b/app/assets/javascripts/discourse/models/group.js
index a76dae825..5d307de07 100644
--- a/app/assets/javascripts/discourse/models/group.js
+++ b/app/assets/javascripts/discourse/models/group.js
@@ -126,8 +126,21 @@ Discourse.Group = Discourse.Model.extend({
       var message = $.parseJSON(e.responseText).errors;
       bootbox.alert(message);
     });
-  }
+  },
 
+  findPosts: function(opts) {
+    opts = opts || {};
+
+    var data = {};
+    if (opts.beforePostId) { data.before_post_id = opts.beforePostId; }
+
+    return Discourse.ajax("/groups/" + this.get('name') + "/posts.json", { data: data }).then(function (posts) {
+      return posts.map(function (p) {
+        p.user = Discourse.User.create(p.user);
+        return Em.Object.create(p);
+      });
+    });
+  }
 });
 
 Discourse.Group.reopenClass({
diff --git a/app/assets/javascripts/discourse/routes/group_index_route.js b/app/assets/javascripts/discourse/routes/group_index_route.js
index 675b35b43..3976e0e9d 100644
--- a/app/assets/javascripts/discourse/routes/group_index_route.js
+++ b/app/assets/javascripts/discourse/routes/group_index_route.js
@@ -1,6 +1,14 @@
+/**
+  The route for the index of a Group
+
+  @class GroupIndexRoute
+  @extends Discourse.Route
+  @namespace Discourse
+  @module Discourse
+**/
 Discourse.GroupIndexRoute = Discourse.Route.extend({
   model: function() {
-    return this.modelFor('group');
+    return this.modelFor('group').findPosts();
   },
 
   setupController: function(controller, model) {
diff --git a/app/assets/javascripts/discourse/routes/group_members_route.js b/app/assets/javascripts/discourse/routes/group_members_route.js
index 3ac3a06a3..4cea70c09 100644
--- a/app/assets/javascripts/discourse/routes/group_members_route.js
+++ b/app/assets/javascripts/discourse/routes/group_members_route.js
@@ -1,3 +1,11 @@
+/**
+  Set things up to display the members of a group
+
+  @class GroupMembersRoute
+  @extends Discourse.Route
+  @namespace Discourse
+  @module Discourse
+**/
 Discourse.GroupMembersRoute = Discourse.Route.extend({
   model: function() {
     return this.modelFor('group');
diff --git a/app/assets/javascripts/discourse/routes/group_route.js b/app/assets/javascripts/discourse/routes/group_route.js
index 668528f7b..acbbbe823 100644
--- a/app/assets/javascripts/discourse/routes/group_route.js
+++ b/app/assets/javascripts/discourse/routes/group_route.js
@@ -1,3 +1,11 @@
+/**
+  The base route for a group
+
+  @class GroupRoute
+  @extends Discourse.Route
+  @namespace Discourse
+  @module Discourse
+**/
 Discourse.GroupRoute = Discourse.Route.extend({
 
   model: function(params) {
diff --git a/app/assets/javascripts/discourse/templates/group/index.js.handlebars b/app/assets/javascripts/discourse/templates/group/index.js.handlebars
index 932962af7..8e73e8e3e 100644
--- a/app/assets/javascripts/discourse/templates/group/index.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/group/index.js.handlebars
@@ -1,3 +1,16 @@
-GROUP INDEX
-{{name}}
-
+<div class='user-stream'>
+  {{#groupedEach model}}
+    <div class='item'>
+      <div class='clearfix info'>
+        {{#link-to 'user' user class="avatar-link"}}<div class='avatar-wrapper'>{{avatar user imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div>{{/link-to}}
+        <span class='time'>{{unboundDate path="created_at" leaveAgo="true"}}</span>
+        <span class="title">
+          <a href="{{unbound url}}">{{unbound title}}</a>
+        </span>
+      </div>
+      <p class='excerpt'>
+      {{{unbound cooked}}}
+      </p>
+    </div>
+  {{/groupedEach}}
+</div>
diff --git a/app/assets/javascripts/discourse/templates/user/user.js.handlebars b/app/assets/javascripts/discourse/templates/user/user.js.handlebars
index 05feafb50..73e4c3567 100644
--- a/app/assets/javascripts/discourse/templates/user/user.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/user/user.js.handlebars
@@ -44,11 +44,12 @@
           <div class='bio'>{{{bio_cooked}}}</div>
 
           {{#if custom_groups}}
-          <div class='groups'>
-            {{#each custom_groups}}
-              {{#link-to 'group' this}}{{name}}{{/link-to}}
-            {{/each}}
-          </div>
+            <div class='groups'>
+              {{i18n groups.title count=custom_groups.length}}:
+              {{#each custom_groups}}
+                {{#link-to 'group' this}}{{name}}{{/link-to}}
+              {{/each}}
+            </div>
           {{/if}}
 
           {{#if isSuspended}}
diff --git a/app/assets/javascripts/discourse/views/group_index_view.js b/app/assets/javascripts/discourse/views/group_index_view.js
new file mode 100644
index 000000000..c73a56d43
--- /dev/null
+++ b/app/assets/javascripts/discourse/views/group_index_view.js
@@ -0,0 +1,4 @@
+Discourse.GroupIndexView = Discourse.View.extend(Discourse.LoadMore, {
+  eyelineSelector: '.user-stream .item'
+});
+
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 75fff2aa3..c9fc37c50 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -6,6 +6,13 @@ class GroupsController < ApplicationController
     render_serialized(group, BasicGroupSerializer)
   end
 
+  def posts
+    group = Group.where(name: params.require(:group_id)).first
+    guardian.ensure_can_see!(group)
+    posts = group.posts_for(guardian, params[:before_post_id])
+    render_serialized posts.to_a, GroupPostSerializer
+  end
+
   def members
     group = Group.where(name: params.require(:group_id)).first
     guardian.ensure_can_see!(group)
diff --git a/app/models/group.rb b/app/models/group.rb
index b83144b6f..ef2c3060c 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -31,6 +31,24 @@ class Group < ActiveRecord::Base
 
   validate :alias_level, inclusion: { in: ALIAS_LEVELS.values}
 
+  def posts_for(guardian, before_post_id)
+    user_ids = group_users.map {|gu| gu.user_id}
+    result = Post.where(user_id: user_ids).includes(:user, :topic).references(:posts, :topics)
+    result = result.where('topics.archetype <> ?', Archetype.private_message)
+
+    unless guardian.is_staff?
+      allowed_ids = guardian.allowed_category_ids
+      if allowed_ids.length > 0
+        result = result.where('topics.category_id IS NULL or topics.category_id IN (?)', allowed_ids)
+      else
+        result = result.where('topics.category_id IS NULL')
+      end
+    end
+
+    result = result.where('posts.id < ?', before_post_id) if before_post_id
+    result.order('posts.created_at desc').limit(20)
+  end
+
   def self.trust_group_ids
     (10..19).to_a
   end
@@ -156,7 +174,6 @@ class Group < ActiveRecord::Base
     end
   end
 
-
   def self.builtin
     Enum.new(:moderators, :admins, :trust_level_1, :trust_level_2)
   end
diff --git a/app/serializers/group_post_serializer.rb b/app/serializers/group_post_serializer.rb
new file mode 100644
index 000000000..db451432a
--- /dev/null
+++ b/app/serializers/group_post_serializer.rb
@@ -0,0 +1,15 @@
+class GroupPostSerializer < ApplicationSerializer
+  attributes :id,
+             :cooked,
+             :created_at,
+             :title,
+             :url
+
+  has_one :user, serializer: BasicUserSerializer, embed: :objects
+
+  def title
+    object.topic.title
+  end
+
+end
+
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 820ca9d74..80e724f8c 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -174,6 +174,9 @@ en:
       sent_by_you: "Sent by <a href='{{userUrl}}'>you</a>"
 
     groups:
+      title:
+        one: "group"
+        other: "groups"
       members: "Members"
       posts: "Posts"
       alias_levels:
diff --git a/config/routes.rb b/config/routes.rb
index 3092ffecf..e19f563f4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -165,6 +165,7 @@ Discourse::Application.routes.draw do
 
   resources :groups do
     get 'members'
+    get 'posts'
   end
 
   resources :posts do