diff --git a/app/styles/play/ladder.sass b/app/styles/play/ladder.sass
index ba99c6948..c1c2fd374 100644
--- a/app/styles/play/ladder.sass
+++ b/app/styles/play/ladder.sass
@@ -29,6 +29,34 @@
   .ellipsis-row
     text-align: center
     
+  // friend column
+
+  .friends-header
+    margin-top: 0
+    margin-bottom: 5px
+
+  .connect-buttons
+    margin-bottom: 10px
+    .btn
+      margin-left: 5px
+  
+  .friend-entry img
+    float: left
+    margin-right: 10px
+    
+  .friend-entry
+    margin-bottom: 15px
+    
+  .connect-facebook
+    background-color: #4c66a4 !important
+    background-image: none
+    color: white
+    
+  .connect-google-plus
+    background-color: #CC3234 !important
+    background-image: none
+    color: white
+    
   td
     padding: 1px 2px
     
diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade
index 092e60372..81bf058c4 100644
--- a/app/templates/play/ladder/ladder_tab.jade
+++ b/app/templates/play/ladder/ladder_tab.jade
@@ -1,6 +1,6 @@
 div#columns.row
   for team in teams
-    div.column.col-md-6
+    div.column.col-md-4
       table.table.table-bordered.table-condensed.table-hover
         tr
           th
@@ -15,8 +15,8 @@ div#columns.row
           th
 
         - var topSessions = team.leaderboard.topPlayers.models;
-        - var inTheTop = team.leaderboard.inTopSessions();
-        - if(!inTheTop) topSessions = topSessions.slice(0, 10);
+        - var showJustTop = team.leaderboard.inTopSessions() || me.get('anonymous');
+        - if(!showJustTop) topSessions = topSessions.slice(0, 10);
         for session, rank in topSessions
           - var myRow = session.get('creator') == me.id
           tr(class=myRow ? "success" : "")
@@ -27,7 +27,7 @@ div#columns.row
               a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}")
                 span(data-i18n="ladder.fight") Fight!
                 
-        if !inTheTop
+        if !showJustTop
           tr(class="active")
             td(colspan=4).ellipsis-row ...
           for session in team.leaderboard.nearbySessions()
@@ -38,4 +38,40 @@ div#columns.row
               td.name-col-cell= session.get('creatorName') || "Anonymous"
               td.fight-cell
                 a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}")
-                  span(data-i18n="ladder.fight") Fight!
\ No newline at end of file
+                  span(data-i18n="ladder.fight") Fight!
+                    
+  div.column.col-md-4
+    h4.friends-header Friends Playing
+    if me.get('anonymous')
+      div.alert.alert-info
+        a(data-toggle="coco-modal", data-target="modal/signup") Sign up to play with your friends!
+    
+    else
+      if !onFacebook
+        div.connect-buttons
+          | Connect:
+          if !onFacebook
+            button.btn.btn-sm.connect-facebook Facebook
+          //button.btn.btn-sm.connect-google-plus Google+
+      
+      if !!friends
+        
+        if friends.length
+          for friend in friends
+            p.friend-entry
+              img(src="http://graph.facebook.com/#{friend.facebookID}/picture").img-thumbnail
+              span= friend.creatorName + ' (' + friend.facebookName + ')'
+              br
+              span= Math.round(friend.totalScore * 100)
+              span : 
+              span= friend.team
+              br
+              a(href="/play/level/#{level.get('slug') || level.id}/?team=#{friend.otherTeam}&opponent=#{friend._id}")
+                span(data-i18n="ladder.fight") Fight!
+  
+  
+        else
+          p Invite your friends to join you in battle!
+            
+      else
+        p Connect to social networks to play with your friends!
\ No newline at end of file
diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
index 226ab5f54..9cce33a14 100644
--- a/app/views/play/ladder/ladder_tab.coffee
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -19,25 +19,68 @@ module.exports = class LadderTabView extends CocoView
   id: 'ladder-tab-view'
   template: require 'templates/play/ladder/ladder_tab'
   startsLoading: true
+  
+  events:
+    'click .connect-facebook': -> FB.login()
+    
+  subscriptions:
+    'facebook-logged-in': -> location.reload()
 
   constructor: (options, @level, @sessions) ->
     super(options)
     @teams = teamDataFromLevel @level
     @leaderboards = {}
     @refreshLadder()
+    @checkFriends()
+
+  checkFriends: ->
+    @loadingFriends = true
+    FB.getLoginStatus (response) =>
+      @facebookStatus = response.status
+      if @facebookStatus is 'connected'
+        @loadFriendSessions()
+      else
+        @loadingFriends = false
+        @renderMaybe()
+
+  loadFriendSessions: ->
+    FB.api '/me/friends', (response) =>
+      @facebookData = response.data
+      console.log 'got facebookData', @facebookData
+      levelFrag = "#{@level.get('original')}.#{@level.get('version').major}"
+      url = "/db/level/#{levelFrag}/leaderboard_friends"
+      $.ajax url, {
+        data: { friendIDs: (f.id for f in @facebookData) }
+        method: 'POST'
+        success: @facebookFriendsLoaded
+      }
+  
+  facebookFriendsLoaded: (result) =>
+    friendsMap = {}
+    friendsMap[friend.id] = friend.name for friend in @facebookData
+    for friend in result
+      friend.facebookName = friendsMap[friend.facebookID]
+      friend.otherTeam = if friend.team is 'humans' then 'ogres' else 'humans'
+    @friends = result
+    @loadingFriends = false
+    @renderMaybe()
 
   refreshLadder: ->
+    promises = []
     for team in @teams
       @leaderboards[team.id]?.off 'sync'
       teamSession = _.find @sessions.models, (session) -> session.get('team') is team.id
       @leaderboards[team.id] = new LeaderboardData(@level, team.id, teamSession)
-      @leaderboards[team.id].once 'sync', @onLeaderboardLoaded, @
-
-  onLeaderboardLoaded: -> @renderMaybe()
+      promises.push @leaderboards[team.id].promise
+    @loadingLeaderboards = true
+    $.when(promises...).then(@leaderboardsLoaded)
 
+  leaderboardsLoaded: =>
+    @loadingLeaderboards = false
+    @renderMaybe()
+    
   renderMaybe: ->
-    leaderboardModels = _.values(@leaderboards)
-    return unless _.every leaderboardModels, (loader) -> loader.loaded
+    return if @loadingFriends or @loadingLeaderboards
     @startsLoading = false
     @render()
 
@@ -48,6 +91,8 @@ module.exports = class LadderTabView extends CocoView
     ctx.teams = @teams
     team.leaderboard = @leaderboards[team.id] for team in @teams
     ctx.levelID = @levelID
+    ctx.friends = @friends
+    ctx.onFacebook = @facebookStatus is 'connected'
     ctx
 
 class LeaderboardData
@@ -70,7 +115,9 @@ class LeaderboardData
       success = (@myRank) =>
       promises.push $.ajax "/db/level/#{level}/leaderboard_rank?scoreOffset=#{@session.get('totalScore')}&team=#{@team}", {success}
     
-    $.when(promises...).then @onLoad
+    @promise = $.when(promises...)
+    @promise.then @onLoad
+    @promise
 
   onLoad: =>
     @loaded = true
@@ -82,7 +129,7 @@ class LeaderboardData
     return me.id in (session.attributes.creator for session in @topPlayers.models)
     
   nearbySessions: ->
-    return unless @session
+    return [] unless @session
     l = []
     above = @playersAbove.models
     above.reverse()