diff --git a/app/assets/images/pages/front/play_web.jpg b/app/assets/images/pages/front/play_web.jpg
deleted file mode 100644
index 6ef8412da..000000000
Binary files a/app/assets/images/pages/front/play_web.jpg and /dev/null differ
diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index c02762a02..0a89b3c1e 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -340,6 +340,14 @@
     multiplayer_caption: "Play with friends!"
     auth_caption: "Save your progress."
 
+  leaderboard:
+    leaderboard: "Leaderboard"
+    view_other_solutions: "View Other Solutions"
+    top_solutions: "Top Solutions"
+    day_tab: "Today"
+    week_tab: "This Week"
+    all_tab: "All-Time"
+
   inventory:
     choose_inventory: "Equip Items"
     equipped_item: "Equipped"
diff --git a/app/models/User.coffee b/app/models/User.coffee
index ee537e1ae..2dcc1dcc6 100644
--- a/app/models/User.coffee
+++ b/app/models/User.coffee
@@ -133,6 +133,21 @@ module.exports = class User extends CocoModel
     application.tracker.identify foreshadowsLevels: @foreshadowsLevels unless me.isAdmin()
     @foreshadowsLevels
 
+  getLeaderboardsGroup: ->
+    return @leaderboardsGroup if @leaderboardsGroup?
+    group = me.get('testGroupNumber') % 64
+    if group < 16
+      @leaderboardsGroup = 'always'
+    else if group < 32
+      @leaderboardsGroup = 'early'
+    else if group < 48
+      @leaderboardsGroup = 'late'
+    else
+      @leaderboardsGroup = 'never'
+    @leaderboardsGroup = 'always' if me.isAdmin()
+    application.tracker.identify leaderboardsGroup: @leaderboardsGroup unless me.isAdmin()
+    @leaderboardsGroup
+
   getVideoTutorialStylesIndex: (numVideos=0)->
     # A/B Testing video tutorial styles
     # Not a constant number of videos available (e.g. could be 0, 1, 3, or 4 currently)
diff --git a/app/styles/play/level/modal/hero-victory-modal.sass b/app/styles/play/level/modal/hero-victory-modal.sass
index c881afa9f..5fa59faa9 100644
--- a/app/styles/play/level/modal/hero-victory-modal.sass
+++ b/app/styles/play/level/modal/hero-victory-modal.sass
@@ -320,6 +320,11 @@
       margin: 0
       float: left
     
+  .leaderboard-button
+    height: 60px
+    line-height: 30px
+    margin: 0 10px
+    float: left
 
   .next-level-buttons
     float: right
diff --git a/app/styles/game-menu/game-menu-modal.sass b/app/styles/play/menu/game-menu-modal.sass
similarity index 100%
rename from app/styles/game-menu/game-menu-modal.sass
rename to app/styles/play/menu/game-menu-modal.sass
diff --git a/app/styles/game-menu/guide-view.sass b/app/styles/play/menu/guide-view.sass
similarity index 100%
rename from app/styles/game-menu/guide-view.sass
rename to app/styles/play/menu/guide-view.sass
diff --git a/app/styles/game-menu/inventory-modal.sass b/app/styles/play/menu/inventory-modal.sass
similarity index 100%
rename from app/styles/game-menu/inventory-modal.sass
rename to app/styles/play/menu/inventory-modal.sass
diff --git a/app/styles/game-menu/item-view.sass b/app/styles/play/menu/item-view.sass
similarity index 100%
rename from app/styles/game-menu/item-view.sass
rename to app/styles/play/menu/item-view.sass
diff --git a/app/styles/game-menu/multiplayer-view.sass b/app/styles/play/menu/multiplayer-view.sass
similarity index 100%
rename from app/styles/game-menu/multiplayer-view.sass
rename to app/styles/play/menu/multiplayer-view.sass
diff --git a/app/styles/game-menu/options-view.sass b/app/styles/play/menu/options-view.sass
similarity index 100%
rename from app/styles/game-menu/options-view.sass
rename to app/styles/play/menu/options-view.sass
diff --git a/app/styles/game-menu/save-load-view.sass b/app/styles/play/menu/save-load-view.sass
similarity index 100%
rename from app/styles/game-menu/save-load-view.sass
rename to app/styles/play/menu/save-load-view.sass
diff --git a/app/styles/play/modal/leaderboard-modal.sass b/app/styles/play/modal/leaderboard-modal.sass
new file mode 100644
index 000000000..b2320cba9
--- /dev/null
+++ b/app/styles/play/modal/leaderboard-modal.sass
@@ -0,0 +1,93 @@
+@import "app/styles/bootstrap/variables"
+@import "app/styles/mixins"
+
+#leaderboard-modal
+
+  //- Clear modal defaults
+  
+  .modal-dialog
+    width: 820px
+    height: 570px
+    padding: 0
+    background: none
+    position: relative
+    top: 40px
+
+    
+  //- Background
+  
+  #leaderboard-background
+    position: absolute
+    top: -146px
+    left: -3px
+
+    
+  //- Close modal button
+
+  #close-modal
+    position: absolute
+    left: 769px
+    top: -5px
+    width: 60px
+    height: 60px
+    color: white
+    text-align: center
+    font-size: 30px
+    padding-top: 17px
+    cursor: pointer
+    z-index: 2
+    @include rotate(-3deg)
+
+    &:hover
+      color: yellow
+
+    
+  //- Nav bar
+
+  #leaderboard-nav
+    position: absolute
+    top: 53px
+    left: 42px
+    width: 178px
+
+    li
+      background: url(/images/pages/play/modal/menu-tab.png)
+      padding: 5px
+      margin: -5px 0
+      height: 80px
+      padding: 0
+      
+      &.active
+        background: url(/images/pages/play/modal/menu-tab-selected.png)
+        width: 197px
+
+      a
+        font-size: 18px
+        line-height: 50px
+        background: none
+        color: rgb(195,153,124)
+        font-weight: bold
+        padding: 14px 20px
+        font-family: $headings-font-family
+        text-transform: uppercase
+    
+        .glyphicon
+          margin-right: 6px
+
+
+  //- Tab panels
+  
+  .leaderboard-tab-content
+    position: absolute
+    left: 219px
+    top: 21px
+    width: 571px
+    height: 514px
+    padding: 50px
+    overflow-y: scroll
+
+  ::-webkit-scrollbar
+    // So that the scrollbar doesn't go on top of the close button.
+    // Wish we could easily do this for Firefox.
+    display: none
+
diff --git a/app/styles/play/modal/leaderboard-tab-view.sass b/app/styles/play/modal/leaderboard-tab-view.sass
new file mode 100644
index 000000000..d2691932d
--- /dev/null
+++ b/app/styles/play/modal/leaderboard-tab-view.sass
@@ -0,0 +1,2 @@
+.leaderboard-tab-view
+  color: black
diff --git a/app/templates/play/level/modal/hero-victory-modal.jade b/app/templates/play/level/modal/hero-victory-modal.jade
index 22fe126a1..2c13d42ba 100644
--- a/app/templates/play/level/modal/hero-victory-modal.jade
+++ b/app/templates/play/level/modal/hero-victory-modal.jade
@@ -68,6 +68,9 @@ block modal-footer-content
       .sign-up-blurb(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account!
       button.btn.btn-illustrated.btn-warning.sign-up-button.btn-lg(data-dismiss="modal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress
 
+  else if !showHourOfCodeDoneButton && showLeaderboard
+    button.btn.btn-illustrated.btn-warning.leaderboard-button.btn-lg(data-dismiss="modal", data-i18n="leaderboard.view_other_solutions") View Other Solutions
+
   button.btn.btn-illustrated.btn-lg.btn-warning.hide#saving-progress-label(disabled, data-i18n="play_level.victory_saving_progress") Saving Progress
 
   .next-level-buttons
diff --git a/app/templates/play/modal/leaderboard-modal.jade b/app/templates/play/modal/leaderboard-modal.jade
new file mode 100644
index 000000000..68fe487f8
--- /dev/null
+++ b/app/templates/play/modal/leaderboard-modal.jade
@@ -0,0 +1,17 @@
+.modal-dialog
+  .modal-content
+    img(src="/images/pages/play/modal/game-menu-background.png", draggable="false")#leaderboard-background
+
+    div#close-modal
+      span.glyphicon.glyphicon-remove
+
+    ul#leaderboard-nav.nav.nav-pills.nav-stacked
+      for submenu, index in submenus
+        li(class=submenu === showTab ? "active" : "")
+          a(href='#' + submenu + '-view', data-toggle='tab')
+            span(data-i18n='leaderboard.' + submenu + '_tab')
+
+    .tab-content.leaderboard-tab-content
+      for submenu, index in submenus
+        .tab-pane(id=submenu + '-view')
+          .leaderboard-tab-view
\ No newline at end of file
diff --git a/app/templates/play/modal/leaderboard-tab-view.jade b/app/templates/play/modal/leaderboard-tab-view.jade
new file mode 100644
index 000000000..22234e73d
--- /dev/null
+++ b/app/templates/play/modal/leaderboard-tab-view.jade
@@ -0,0 +1,2 @@
+div dis be da tab view for #{timespan}
+span= Math.random()
diff --git a/app/views/common/SearchView.coffee b/app/views/common/SearchView.coffee
index e0b24a533..93ffa26ba 100644
--- a/app/views/common/SearchView.coffee
+++ b/app/views/common/SearchView.coffee
@@ -10,7 +10,7 @@ class SearchCollection extends Backbone.Collection
       @url += 'created,permissions'
       @url += ',' + projected for projected in projection
     else @url += 'true'
-    @url += "&term=#{term}" if @term
+    @url += "&term=#{@term}" if @term
 
   comparator: (a, b) ->
     score = 0
diff --git a/app/views/editor/modal/VersionsModal.coffee b/app/views/editor/modal/VersionsModal.coffee
index d3e174947..8be2ca97c 100755
--- a/app/views/editor/modal/VersionsModal.coffee
+++ b/app/views/editor/modal/VersionsModal.coffee
@@ -12,7 +12,7 @@ class VersionsViewCollection extends CocoCollection
 
   initialize: (@url, @levelID, @model) ->
     super()
-    @url = url + @levelID + '/versions'
+    @url = @url + @levelID + '/versions'
 
 module.exports = class VersionsModal extends ModalView
   template: template
diff --git a/app/views/play/CampaignView.coffee b/app/views/play/CampaignView.coffee
index 5866e59b7..06697df26 100644
--- a/app/views/play/CampaignView.coffee
+++ b/app/views/play/CampaignView.coffee
@@ -11,6 +11,7 @@ MusicPlayer = require 'lib/surface/MusicPlayer'
 storage = require 'core/storage'
 AuthModal = require 'views/core/AuthModal'
 SubscribeModal = require 'views/core/SubscribeModal'
+LeaderboardModal = require 'views/play/modal/LeaderboardModal'
 Level = require 'models/Level'
 utils = require 'core/utils'
 require 'vendor/three'
@@ -205,6 +206,7 @@ module.exports = class CampaignView extends RootView
           for nextLevelOriginal in level.nextLevels ? []
             if nextLevel = _.find(@campaign.renderedLevels, original: nextLevelOriginal)
               @createLine level.position, nextLevel.position
+      @showLeaderboard @options.justBeatLevel?.get('original') if (@options.showLeaderboard or true)
     @applyCampaignStyles()
     @testParticles()
 
@@ -217,6 +219,12 @@ module.exports = class CampaignView extends RootView
     authModal.mode = 'signup'
     @openModalView authModal
 
+  showLeaderboard: (levelOriginal) ->
+    #levelOriginal ?= '5411cb3769152f1707be029c'  # Testing: show Dungeons of Kithgard
+    levelOriginal ?= '541c9a30c6362edfb0f34479'  # Testing: show Kithgard Gates
+    leaderboardModal = new LeaderboardModal supermodel: @supermodel, levelOriginal: levelOriginal
+    @openModalView leaderboardModal
+
   determineNextLevel: (levels) ->
     foundNext = false
     for level in levels
diff --git a/app/views/play/level/modal/HeroVictoryModal.coffee b/app/views/play/level/modal/HeroVictoryModal.coffee
index d88760dae..ec4eec156 100644
--- a/app/views/play/level/modal/HeroVictoryModal.coffee
+++ b/app/views/play/level/modal/HeroVictoryModal.coffee
@@ -23,6 +23,7 @@ module.exports = class HeroVictoryModal extends ModalView
 
   events:
     'click #continue-button': 'onClickContinue'
+    'click .leaderboard-button': 'onClickLeaderboard'
     'click .return-to-ladder-button': 'onClickReturnToLadder'
     'click .sign-up-button': 'onClickSignupButton'
 
@@ -145,6 +146,11 @@ module.exports = class HeroVictoryModal extends ModalView
       # Show the "I'm done" button between 30 - 120 minutes if they definitely came from Hour of Code
       c.showHourOfCodeDoneButton = me.get('hourOfCode') and showDone
 
+    lg = me.getLeaderboardsGroup()
+    c.showLeaderboard = lg is 'always'
+    c.showLeaderboard = true if me.level() >= 3 and lg.group is 'early'
+    c.showLeaderboard = true if me.level() >= 5 and lg.group is 'late'
+
     return c
 
   afterRender: ->
@@ -322,11 +328,18 @@ module.exports = class HeroVictoryModal extends ModalView
     link += '/' + nextCampaign unless nextCampaign is 'dungeon'
     link
 
-  onClickContinue: (e) ->
+  onClickContinue: (e, extraOptions=null) ->
     @playSound 'menu-button-click'
     nextLevelLink = @getNextLevelLink()
     # Preserve the supermodel as we navigate back to the world map.
-    Backbone.Mediator.publish 'router:navigate', route: nextLevelLink, viewClass: require('views/play/CampaignView'), viewArgs: [{supermodel: if @options.hasReceivedMemoryWarning then null else @supermodel}, @getNextLevelCampaign()]
+    options =
+      justBeatLevel: @level
+      supermodel: if @options.hasReceivedMemoryWarning then null else @supermodel
+    _.merge options, extraOptions if extraOptions
+    Backbone.Mediator.publish 'router:navigate', route: nextLevelLink, viewClass: require('views/play/CampaignView'), viewArgs: [options, @getNextLevelCampaign()]
+
+  onClickLeaderboard: (e) ->
+    @onClickContinue e, showLeaderboard: true
 
   onClickReturnToLadder: (e) ->
     @playSound 'menu-button-click'
diff --git a/app/views/play/modal/LeaderboardModal.coffee b/app/views/play/modal/LeaderboardModal.coffee
new file mode 100644
index 000000000..b5e25f848
--- /dev/null
+++ b/app/views/play/modal/LeaderboardModal.coffee
@@ -0,0 +1,49 @@
+ModalView = require 'views/core/ModalView'
+template = require 'templates/play/modal/leaderboard-modal'
+LeaderboardTabView = require 'views/play/modal/LeaderboardTabView'
+
+module.exports = class LeaderboardModal extends ModalView
+  id: 'leaderboard-modal'
+  template: template
+  instant: true
+  timespans: ['day', 'week', 'all']
+
+  subscriptions: {}
+
+  events:
+    'shown.bs.tab #leaderboard-nav a': 'onTabShown'
+    'click #close-modal': 'hide'
+
+  constructor: (options) ->
+    super options
+    @levelOriginal = @options.levelOriginal
+
+
+  getRenderData: (c) ->
+    c = super c
+    c.submenus = @timespans
+    c.showTab = c.submenus[0]
+    c
+
+  afterRender: ->
+    super()
+    for timespan, index in @timespans
+      submenuView = new LeaderboardTabView timespan: timespan, levelOriginal: @levelOriginal
+      @insertSubView submenuView, @$el.find "##{timespan}-view .leaderboard-tab-view"
+      if index is 0
+        submenuView.$el.parent().addClass 'active'
+        submenuView.onShown?()
+    @playSound 'game-menu-open'
+    @$el.find('.nano:visible').nanoScroller()
+
+  onTabShown: (e) ->
+    @playSound 'game-menu-tab-switch'
+    timespan = e.target.hash.substring(1).replace(/-view/g, '')
+    subview = _.find @subviews, timespan: timespan
+    subview.onShown?()
+    otherSubview.onHidden?() for subviewKey, otherSubview of @subviews when otherSubview isnt subview
+
+  onHidden: ->
+    super()
+    subview.onHidden?() for subviewKey, subview of @subviews
+    @playSound 'game-menu-close'
diff --git a/app/views/play/modal/LeaderboardTabView.coffee b/app/views/play/modal/LeaderboardTabView.coffee
new file mode 100644
index 000000000..161a1280b
--- /dev/null
+++ b/app/views/play/modal/LeaderboardTabView.coffee
@@ -0,0 +1,27 @@
+CocoView = require 'views/core/CocoView'
+template = require 'templates/play/modal/leaderboard-tab-view'
+
+module.exports = class LeaderboardTabView extends CocoView
+  template: template
+  className: 'leaderboard-tab-view'
+  helpVideoHeight: '295'
+  helpVideoWidth: '471'
+
+  events:
+    'click .start-subscription-button': "clickSubscribe"
+
+  constructor: (options) ->
+    super options
+    @timespan = @options.timespan
+    @levelOriginal = @options.levelOriginal
+
+  destroy: ->
+    super()
+
+  getRenderData: ->
+    c = super()
+    c.timespan = @timespan
+    c
+
+  afterRender: ->
+    super()