diff --git a/app/Router.coffee b/app/Router.coffee
index cce426ea1..c266a23ae 100644
--- a/app/Router.coffee
+++ b/app/Router.coffee
@@ -31,6 +31,7 @@ module.exports = class CocoRouter extends Backbone.Router
     'admin/clas': go('admin/CLAsView')
     'admin/employers': go('admin/EmployersListView')
     'admin/files': go('admin/FilesView')
+    'admin/growth': go('admin/GrowthView')
     'admin/level-sessions': go('admin/LevelSessionsView')
     'admin/users': go('admin/UsersView')
     'admin/base': go('admin/BaseView')
diff --git a/app/templates/admin.jade b/app/templates/admin.jade
index af59ee831..36d754468 100644
--- a/app/templates/admin.jade
+++ b/app/templates/admin.jade
@@ -43,6 +43,9 @@ block content
       a(href="/admin/base", data-i18n="admin.av_other_debug_base_url") Base (for debugging base.jade)
     li
       a(href="/admin/clas", data-i18n="admin.clas") CLAs
+    if me.isAdmin()
+      li
+        a(href="/admin/growth", data-i18n="admin.growth") Growth
 
   hr
 
diff --git a/app/templates/admin/growth.jade b/app/templates/admin/growth.jade
new file mode 100644
index 000000000..0ff7a3c1d
--- /dev/null
+++ b/app/templates/admin/growth.jade
@@ -0,0 +1,32 @@
+extends /templates/base
+
+block content
+  
+  h1(data-i18n="admin.growth_title") Growth
+  if me.isAdmin()
+    if crunchingData
+      h4 Cruncing Data..
+    else
+      h2 Registered Users
+      h3 Per-Day
+      h4 Totals
+      svg.perDayTotal
+      h4 Added
+      svg.perDayAdded
+      table.table.table-striped.table-bordered.table-condensed
+        -for (var i = 0; i < usersPerDay.length; i++)
+          tr
+            td= usersPerDay[i].date
+            td= usersPerDay[i].added
+            td= usersPerDay[i].total
+      h3 Per-Month
+      h4 Totals
+      svg.perMonthTotal
+      h4 Added
+      svg.perMonthAdded
+      table.table.table-striped.table-bordered.table-condensed
+        -for (var i = 0; i < usersPerMonth.length; i++)
+          tr
+            td= usersPerMonth[i].date
+            td= usersPerMonth[i].added
+            td= usersPerMonth[i].total
diff --git a/app/views/admin/GrowthView.coffee b/app/views/admin/GrowthView.coffee
new file mode 100644
index 000000000..b77b88e92
--- /dev/null
+++ b/app/views/admin/GrowthView.coffee
@@ -0,0 +1,192 @@
+RootView = require 'views/kinds/RootView'
+template = require 'templates/admin/growth'
+RealTimeCollection = require 'collections/RealTimeCollection'
+
+# Growth View ###################
+#
+# Display interesting growth data.
+#
+# Currently shows:
+#   Registered user totals and added, per-day and per-month
+#   7-day moving average for registered users added per-day
+#
+# TODO: @padding isn't applied correctly
+# TODO: aggregate recent data if missing?
+#
+
+module.exports = class GrowthView extends RootView
+  id: 'admin-growth-view'
+  template: template
+  height: 300
+  width: 1000
+  xAxisGuideHeight: 80
+  yAxisGuideWidth: 60
+  padding: 10
+
+  constructor: (options) ->
+    super options
+    @usersPerMonth = new RealTimeCollection 'growth/users/registered/per-month'
+    @usersPerMonth.on 'add', @refreshData
+    @usersPerDay = new RealTimeCollection 'growth/users/registered/per-day'
+    @usersPerDay.on 'add', @refreshData
+
+  destroy: ->
+    @usersPerMonth.off 'add', @refreshData
+    @usersPerDay.off 'add', @refreshData
+
+  refreshData: =>
+    @render()
+
+  getRenderData: ->
+    c = super()
+    c.crunchingData = @usersPerMonth.length is 0 and @usersPerDay.length is 0
+    c.usersPerDay = []
+    # @usersPerDay.each (item) ->
+    #   c.usersPerDay.push date: item.get('id'), added: item.get('added'), total: item.get('total')
+    c.usersPerMonth = []
+    # @usersPerMonth.each (item) ->
+    #   c.usersPerMonth.push date: item.get('id'), added: item.get('added'), total: item.get('total')
+    c
+
+  afterRender: ->
+    super()
+    if me.isAdmin()
+      @createPerDayChart()
+      @createPerMonthChart()
+    
+  createPerDayChart: ->
+    addedData = []
+    totalData = []
+    @usersPerDay.each (item) ->
+      addedData.push id: item.get('id'), value: item.get('added')
+      totalData.push id: item.get('id'), value: item.get('total')
+    @createLineChart ".perDayTotal", totalData, 1000
+    @createLineChart ".perDayAdded", addedData, 10, true
+
+  createPerMonthChart: ->
+    addedData = []
+    totalData = []
+    @usersPerMonth.each (item) ->
+      addedData.push id: item.get('id'), value: item.get('added')
+      totalData.push id: item.get('id'), value: item.get('total')
+    @createLineChart ".perMonthTotal", totalData, 1000
+    @createLineChart ".perMonthAdded", addedData, 1000
+
+  createLineChart: (selector, data, guidelineSpacing, sevenDayAverage=false) ->
+    return unless data.length > 1
+    
+    minVal = d3.min(data, (d) -> d.value)
+    maxVal = d3.max(data, (d) -> d.value)
+
+    widthSpacing = (@width - @yAxisGuideWidth - @padding) / (data.length - 1)
+
+    y = d3.scale.linear()
+        .domain([minVal, maxVal])
+        .range([@height - @xAxisGuideHeight - 2 * @padding, 0])
+
+    points = []
+    for i in [0...data.length]
+      points.push id: data[i].id, x: i * widthSpacing + @yAxisGuideWidth, y: y(data[i].value) + @padding
+
+    links = []
+    for i in [0...points.length - 1]
+      if points[i] and points[i + 1]
+        links.push start: points[i], end: points[i + 1]
+
+    guidelines = []
+    diff = maxVal - minVal
+    interval = Math.floor(diff / 5)
+    for i in [0..4]
+      yVal = i * interval + minVal
+      yVal = Math.floor(yVal / guidelineSpacing) * guidelineSpacing
+      guidelines.push start: {id: yVal, x: 0, y: y(yVal)}, end: {id: yVal, x: @width, y: y(yVal)}
+
+    sevenPoints = []
+    sevenLinks = []
+    if sevenDayAverage
+      sevenTotal = 0
+      for i in [0...data.length]
+        sevenTotal += data[i].value
+        if i > 5
+          sevenAvg = sevenTotal / 7
+          sevenPoints.push x: i * widthSpacing + @yAxisGuideWidth, y: y(sevenAvg) + @padding
+        if i > 6
+          sevenTotal -= data[i - 7].value
+      for i in [0...sevenPoints.length - 1]
+        if sevenPoints[i] and sevenPoints[i + 1]
+          sevenLinks.push start: sevenPoints[i], end: sevenPoints[i + 1]
+
+    chart = d3.select(selector)
+      .attr("width", @width)
+      .attr("height", @height)
+
+    chart.selectAll(".circle")
+      .data(points)
+      .enter()
+      .append("circle")
+      .attr("cx", (d) -> d.x )
+      .attr("cy", (d) -> d.y )
+      .attr("r", "2px")
+      .attr("fill", "black") 
+      
+    chart.selectAll(".text")
+      .data(points)
+      .enter()
+      .append("text")
+      .attr("dy", ".35em")
+      .attr("transform", (d, i) => "translate(" + d.x + "," + @height + ") rotate(270)")
+      .text((d) -> 
+        if d.id.length is 8 
+          return "#{parseInt(d.id[4..5])}/#{parseInt(d.id[6..7])}/#{d.id[0..3]}"
+        else
+          return "#{parseInt(d.id[4..5])}/#{d.id[0..3]}"
+        )
+
+    chart.selectAll('.line')
+      .data(links)
+      .enter()
+      .append("line")
+      .attr("x1", (d) -> d.start.x )
+      .attr("y1", (d) -> d.start.y )
+      .attr("x2", (d) -> d.end.x )
+      .attr("y2", (d) -> d.end.y )
+      .style("stroke", "rgb(6,120,155)")
+
+    chart.selectAll(".circle")
+      .data(sevenPoints)
+      .enter()
+      .append("circle")
+      .attr("cx", (d) -> d.x )
+      .attr("cy", (d) -> d.y )
+      .attr("r", "2px")
+      .attr("fill", "purple") 
+
+    chart.selectAll('.line')
+      .data(sevenLinks)
+      .enter()
+      .append("line")
+      .attr("x1", (d) -> d.start.x )
+      .attr("y1", (d) -> d.start.y )
+      .attr("x2", (d) -> d.end.x )
+      .attr("y2", (d) -> d.end.y )
+      .style("stroke", "rgb(200,0,0)")
+
+    chart.selectAll('.line')
+      .data(guidelines)
+      .enter()
+      .append("line")
+      .attr("x1", (d) -> d.start.x )
+      .attr("y1", (d) -> d.start.y )
+      .attr("x2", (d) -> d.end.x )
+      .attr("y2", (d) -> d.end.y )
+      .style("stroke", "rgb(140,140,140)")
+
+    chart.selectAll(".text")
+      .data(guidelines)
+      .enter()
+      .append("text")
+      .attr("x", (d) -> d.start.x)
+      .attr("y", (d) -> d.start.y - 6)
+      .attr("dy", ".35em")
+      .text((d) -> d.start.id)
+