diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 8b7a05e89..d629c1270 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -3,7 +3,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     loading: "Загрузка..."
     saving: "Сохранение..."
     sending: "Отправка..."
-#    send: "Send"
+    send: "Отправить"
     cancel: "Отмена"
     save: "Сохранить"
     create: "Создать"
@@ -115,8 +115,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     forum_page: "наш форум"
     forum_suffix: "."
     send: "Отправить отзыв"
-#    contact_candidate: "Contact Candidate"
-#    recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 18% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns."
+    contact_candidate: "Связаться с кандидатом"
+    recruitment_reminder: "Используйте эту форму, чтобы обратиться к кандидатам, если вы заинтересованы в интервью. Помните, что CodeCombat взимает 18% от первого года зарплаты. Плата производится по найму сотрудника и подлежит возмещению в течение 90 дней, если работник не остаётся на рабочем месте. Работники с частичной занятостью, удалённые и работающие по контракту свободны, как стажёры."
 
   diplomat_suggestion:
     title: "Помогите перевести CodeCombat!"
@@ -151,7 +151,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     wizard_tab: "Волшебник"
     password_tab: "Пароль"
     emails_tab: "Email-адреса"
-#    job_profile_tab: "Job Profile"
+    job_profile_tab: "Профиль соискателя"
     admin: "Админ"
     wizard_color: "Цвет одежды волшебника"
     new_password: "Новый пароль"
@@ -169,37 +169,37 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     error_saving: "Ошибка сохранения"
     saved: "Изменения сохранены"
     password_mismatch: "Пароли не совпадают."
-#    job_profile: "Job Profile"
-#    job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
-#    job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
+    job_profile: "Профиль соискателя"
+    job_profile_approved: "Ваш профиль соискателя был одобрен CodeCombat. Работодатели смогут видеть его, пока вы не отметите его неактивным или он не будет изменен в течение четырёх недель."
+    job_profile_explanation: "Привет! Заполните это, и мы свяжемся с вами при нахождении работы разработчика программного обеспечения для вас."
 
   account_profile:
     edit_settings: "Изменить настройки"
     profile_for_prefix: "Профиль для "
     profile_for_suffix: ""
-#    approved: "Approved"
-#    not_approved: "Not Approved"
-#    looking_for: "Looking for:"
-#    last_updated: "Last updated:"
-#    contact: "Contact"
-#    work_experience: "Work Experience"
-#    education: "Education"
-#    our_notes: "Our Notes"
-#    projects: "Projects"
+    approved: "Одобрено"
+    not_approved: "Не одобрено"
+    looking_for: "Ищет:"
+    last_updated: "Последнее обновление:"
+    contact: "Контакты"
+    work_experience: "Опыт работы"
+    education: "Образование"
+    our_notes: "Наши заметки"
+    projects: "Проекты"
 
-#  employers:
-#    want_to_hire_our_players: "Want to hire expert CodeCombat players?"
-#    contact_george: "Contact George to see our candidates"
-#    candidates_count_prefix: "We currently have "
-#    candidates_count_many: "many"
-#    candidates_count_suffix: "highly skilled and vetted developers looking for work."
-#    candidate_name: "Name"
-#    candidate_location: "Location"
-#    candidate_looking_for: "Looking For"
-#    candidate_role: "Role"
-#    candidate_top_skills: "Top Skills"
-#    candidate_years_experience: "Yrs Exp"
-#    candidate_last_updated: "Last Updated"
+  employers:
+    want_to_hire_our_players: "Хотите нанимать игроков-экспертов CodeCombat?"
+    contact_george: "Свяжитесь с Джорджем, чтобы посмотреть наших кандидатов"
+    candidates_count_prefix: "Сейчас у нас есть "
+    candidates_count_many: "много"
+    candidates_count_suffix: "высококвалифицированных и проверенных разработчиков, ищущих работу."
+    candidate_name: "Имя"
+    candidate_location: "Местонахождение"
+    candidate_looking_for: "Ищет"
+    candidate_role: "Роль"
+    candidate_top_skills: "Лучшие навыки"
+    candidate_years_experience: "Лет опыта"
+    candidate_last_updated: "Последнее обновление"
 
   play_level:
     level_load_error: "Уровень не может быть загружен: "
@@ -379,7 +379,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     results: "Результаты"
     description: "Описание"
     or: "или"
-#    subject: "Subject"
+    subject: "Тема"
     email: "Email"
     password: "Пароль"
     message: "Сообщение"
@@ -661,5 +661,5 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     gplus_friends: "Друзья G+"
     gplus_friend_sessions: "Сессии друзей G+"
     leaderboard: "таблица лидеров"
-#    user_schema: "User Schema"
-#    user_profile: "User Profile"
+    user_schema: "Пользовательская Schema"
+    user_profile: "Пользовательский профиль"
diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index 023933929..190dde2c1 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -318,15 +318,15 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     contact_us: "联系我们!"
     hipchat_prefix: "你也可以在这里找到我们"
     hipchat_url: "HipChat 房间。"
-#    back: "Back"
+    back: "后退"
     revert: "还原"
     revert_models: "还原模式"
-#    fork_title: "Fork New Version"
-#    fork_creating: "Creating Fork..."
-#    more: "More"
-#    wiki: "Wiki"
-#    live_chat: "Live Chat"
-#    level_publish: "Publish This Level (irreversible)?"
+    fork_title: "派生新版本"
+    fork_creating: "正在执行派生..."
+    more: "更多"
+    wiki: "维基"
+    live_chat: "在线聊天"
+    level_publish: "发布这个关卡吗 (发布后不能撤销)?"
     level_some_options: "有哪些选项?"
     level_tab_thangs: "物体"
     level_tab_scripts: "脚本"
@@ -334,11 +334,11 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     level_tab_components: "组件"
     level_tab_systems: "系统"
     level_tab_thangs_title: "目前所有物体"
-#    level_tab_thangs_all: "All"
+    level_tab_thangs_all: "所有"
     level_tab_thangs_conditions: "启动条件"
     level_tab_thangs_add: "增加物体"
-#    delete: "Delete"
-#    duplicate: "Duplicate"
+    delete: "删除"
+    duplicate: "复制"
     level_settings_title: "设置"
     level_component_tab_title: "目前所有组件"
     level_component_btn_new: "创建新的组件"
diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee
index bb2fc0547..e63e1cd0a 100644
--- a/app/models/CocoModel.coffee
+++ b/app/models/CocoModel.coffee
@@ -11,14 +11,11 @@ class CocoModel extends Backbone.Model
 
   initialize: ->
     super()
-    @constructor.schema ?= @urlRoot[4..].replace '.', '_'
+    @constructor.schema ?= require "schemas/models/#{@urlRoot[4..].replace '.', '_'}"
     if not @constructor.className
       console.error("#{@} needs a className set.")
     @markToRevert()
-    if @constructor.schema?.loaded
-      @addSchemaDefaults()
-    else
-      @loadSchema()
+    @addSchemaDefaults()
     @once 'sync', @onLoaded, @
     @saveBackup = _.debounce(@saveBackup, 500)
 
@@ -34,9 +31,8 @@ class CocoModel extends Backbone.Model
   onLoaded: ->
     @loaded = true
     @loading = false
-    if @constructor.schema?.loaded
-      @markToRevert()
-      @loadFromBackup()
+    @markToRevert()
+    @loadFromBackup()
 
   set: ->
     res = super(arguments...)
@@ -55,18 +51,6 @@ class CocoModel extends Backbone.Model
     CocoModel.backedUp[@id] = @
 
   @backedUp = {}
-
-  loadSchema: ->
-    return if @constructor.schema.loading
-    @constructor.schema = require 'schemas/' + @constructor.schema + '_schema' unless @constructor.schema.loaded
-    @onConstructorSync()
-
-  onConstructorSync: ->
-    @constructor.schema.loaded = true
-    @addSchemaDefaults()
-    @trigger 'schema-loaded'
-
-  @hasSchema: -> return @schema?.loaded
   schema: -> return @constructor.schema
 
   validate: ->
@@ -129,7 +113,7 @@ class CocoModel extends Backbone.Model
     @set "permissions", (@get("permissions") or []).concat({access: 'read', target: 'public'})
 
   addSchemaDefaults: ->
-    return if @addedSchemaDefaults or not @constructor.hasSchema()
+    return if @addedSchemaDefaults
     @addedSchemaDefaults = true
     for prop, defaultValue of @constructor.schema.default or {}
       continue if @get(prop)?
diff --git a/app/models/SuperModel.coffee b/app/models/SuperModel.coffee
index adcac62eb..6963392a2 100644
--- a/app/models/SuperModel.coffee
+++ b/app/models/SuperModel.coffee
@@ -2,7 +2,6 @@ class SuperModel
   constructor: ->
     @models = {}
     @collections = {}
-    @schemas = {}
     _.extend(@, Backbone.Events)
 
   populateModel: (model) ->
@@ -26,11 +25,7 @@ class SuperModel
     @removeEventsFromModel(model)
 
   modelLoaded: (model) ->
-    model.loadSchema()
     schema = model.schema()
-    unless schema.loaded
-      @schemas[model.urlRoot] = schema
-      return schema.once('sync', => @modelLoaded(model))
     refs = model.getReferencedModels(model.attributes, schema, '/', @shouldLoadProjection)
     refs = [] unless @mustPopulate is model or @shouldPopulate(model)
 #    console.log 'Loaded', model.get('name')
@@ -103,9 +98,6 @@ class SuperModel
     for model in _.values @models
       total += 1
       loaded += 1 if model.loaded
-    for schema in _.values @schemas
-      total += 1
-      loaded += 1 if schema.loaded
 
     return 1.0 unless total
     return loaded / total
diff --git a/app/schemas/article_schema.coffee b/app/schemas/models/article.coffee
similarity index 94%
rename from app/schemas/article_schema.coffee
rename to app/schemas/models/article.coffee
index 0274f92a6..60f65640f 100644
--- a/app/schemas/article_schema.coffee
+++ b/app/schemas/models/article.coffee
@@ -1,4 +1,4 @@
-c = require './schemas'
+c = require './../schemas'
 
 ArticleSchema = c.object()
 c.extendNamedProperties ArticleSchema  # name first
diff --git a/app/schemas/level_schema.coffee b/app/schemas/models/level.coffee
similarity index 99%
rename from app/schemas/level_schema.coffee
rename to app/schemas/models/level.coffee
index 919b44c44..7180c6a67 100644
--- a/app/schemas/level_schema.coffee
+++ b/app/schemas/models/level.coffee
@@ -1,5 +1,5 @@
-c = require './schemas'
-ThangComponentSchema = require './thang_component_schema'
+c = require './../schemas'
+ThangComponentSchema = require './../models/thang_component'
 
 SpecificArticleSchema = c.object()
 c.extendNamedProperties SpecificArticleSchema  # name first
diff --git a/app/schemas/level_component_schema.coffee b/app/schemas/models/level_component.coffee
similarity index 98%
rename from app/schemas/level_component_schema.coffee
rename to app/schemas/models/level_component.coffee
index 3178eb916..8552979ee 100644
--- a/app/schemas/level_component_schema.coffee
+++ b/app/schemas/models/level_component.coffee
@@ -1,5 +1,5 @@
-c = require './schemas'
-metaschema = require './metaschema'
+c = require './../schemas'
+metaschema = require './../metaschema'
 
 attackSelfCode = """
 class AttacksSelf extends Component
diff --git a/app/schemas/level_feedback_schema.coffee b/app/schemas/models/level_feedback.coffee
similarity index 96%
rename from app/schemas/level_feedback_schema.coffee
rename to app/schemas/models/level_feedback.coffee
index 201beb468..f8bb6a73c 100644
--- a/app/schemas/level_feedback_schema.coffee
+++ b/app/schemas/models/level_feedback.coffee
@@ -1,4 +1,4 @@
-c = require './schemas'
+c = require './../schemas'
 
 LevelFeedbackLevelSchema = c.object {required: ['original', 'majorVersion']}, {
   original: c.objectId({})
diff --git a/app/schemas/level_session_schema.coffee b/app/schemas/models/level_session.coffee
similarity index 99%
rename from app/schemas/level_session_schema.coffee
rename to app/schemas/models/level_session.coffee
index 4244c4771..670dc9ad4 100644
--- a/app/schemas/level_session_schema.coffee
+++ b/app/schemas/models/level_session.coffee
@@ -1,4 +1,4 @@
-c = require './schemas'
+c = require './../schemas'
 
 LevelSessionPlayerSchema = c.object
   id: c.objectId
diff --git a/app/schemas/level_system_schema.coffee b/app/schemas/models/level_system.coffee
similarity index 98%
rename from app/schemas/level_system_schema.coffee
rename to app/schemas/models/level_system.coffee
index 9b186aaac..1804de363 100644
--- a/app/schemas/level_system_schema.coffee
+++ b/app/schemas/models/level_system.coffee
@@ -1,5 +1,5 @@
-c = require './schemas'
-metaschema = require './metaschema'
+c = require './../schemas'
+metaschema = require './../metaschema'
 
 jitterSystemCode = """
 class Jitter extends System
diff --git a/app/schemas/patch_schema.coffee b/app/schemas/models/patch.coffee
similarity index 97%
rename from app/schemas/patch_schema.coffee
rename to app/schemas/models/patch.coffee
index 5c2ce122e..e14423371 100644
--- a/app/schemas/patch_schema.coffee
+++ b/app/schemas/models/patch.coffee
@@ -1,4 +1,4 @@
-c = require './schemas'
+c = require './../schemas'
 
 patchables = ['level', 'thang_type', 'level_system', 'level_component', 'article']
   
diff --git a/app/schemas/thang_component_schema.coffee b/app/schemas/models/thang_component.coffee
similarity index 96%
rename from app/schemas/thang_component_schema.coffee
rename to app/schemas/models/thang_component.coffee
index b6d574fdc..eebcf155b 100644
--- a/app/schemas/thang_component_schema.coffee
+++ b/app/schemas/models/thang_component.coffee
@@ -1,4 +1,4 @@
-c = require './schemas'
+c = require './../schemas'
 
 module.exports = ThangComponentSchema = c.object {
   title: "Component"
diff --git a/app/schemas/thang_type_schema.coffee b/app/schemas/models/thang_type.coffee
similarity index 98%
rename from app/schemas/thang_type_schema.coffee
rename to app/schemas/models/thang_type.coffee
index 1e6bc2ee5..eb78c1c11 100644
--- a/app/schemas/thang_type_schema.coffee
+++ b/app/schemas/models/thang_type.coffee
@@ -1,5 +1,5 @@
-c = require './schemas'
-ThangComponentSchema = require './thang_component_schema'
+c = require './../schemas'
+ThangComponentSchema = require './thang_component'
 
 ThangTypeSchema = c.object()
 c.extendNamedProperties ThangTypeSchema  # name first
diff --git a/app/schemas/user_schema.coffee b/app/schemas/models/user.coffee
similarity index 99%
rename from app/schemas/user_schema.coffee
rename to app/schemas/models/user.coffee
index a386051f3..6bb3939e6 100644
--- a/app/schemas/user_schema.coffee
+++ b/app/schemas/models/user.coffee
@@ -1,4 +1,4 @@
-c = require './schemas'
+c = require './../schemas'
 emailSubscriptions = ['announcement', 'tester', 'level_creator', 'developer', 'article_editor', 'translator', 'support', 'notification']
 
 UserSchema = c.object {},
diff --git a/app/styles/contribute_classes.sass b/app/styles/contribute_classes.sass
index 9244aca55..e4b8ff7fb 100644
--- a/app/styles/contribute_classes.sass
+++ b/app/styles/contribute_classes.sass
@@ -49,9 +49,15 @@
     &:hover
       background-color: rgba(200, 244, 255, 0.2)
 
-    h4
-      text-align: center
+    a:not(.has-github)
+      cursor: default
+      text-decoration: none
+
     img
       max-width: 100px
       max-height: 100px
+    .caption
+      background-color: transparent
+      h4
+        text-align: center
     
diff --git a/app/templates/contribute/adventurer.jade b/app/templates/contribute/adventurer.jade
index 0cbe1e866..3b9367620 100644
--- a/app/templates/contribute/adventurer.jade
+++ b/app/templates/contribute/adventurer.jade
@@ -53,30 +53,12 @@ block content
         span(data-i18n="contribute.adventurer_join_suf")
           | so if you prefer to be notified those ways, sign up there!
 
-      if me.attributes.anonymous
-        div#sign-up.alert.alert-info
-          strong(data-i18n="contribute.alert_account_message_intro")
-            | Hey there!
-          span  
-          span(data-i18n="contribute.alert_account_message_pref") 
-            | To subscribe for class emails, you'll need to 
-          a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
-            | create an account
-          span  
-          span(data-i18n="contribute.alert_account_message_suf")
-            | first.
+      .contributor-signup-anonymous
+      .contributor-signup(data-contributor-class-id="tester", data-contributor-class-name="adventurer")
 
-      label.checkbox(for="tester").well
-        input(type='checkbox', name="tester", id="tester")
-        span(data-i18n="contribute.adventurer_subscribe_desc")  
-          | Get emails when there are new levels to test.
-        .saved-notification  ✓ Saved
-
-      //#Contributors
-      //  h3(data-i18n="contribute.brave_adventurers")
-      //    | Our Brave Adventurers:
-      //  ul.adventurers
-      //    li Kieizroe
-      //    li ... many, many more
+      //h3(data-i18n="contribute.brave_adventurers")
+      //  | Our Brave Adventurers:
+      //
+      //#contributor-list
 
     div.clearfix
diff --git a/app/templates/contribute/ambassador.jade b/app/templates/contribute/ambassador.jade
index dc1048ac6..2d1f65564 100644
--- a/app/templates/contribute/ambassador.jade
+++ b/app/templates/contribute/ambassador.jade
@@ -47,29 +47,12 @@ block content
           | solving levels can summon higher level wizards to help them.
           | This will be a great way for ambassadors to do their thing. We'll keep you posted!
 
-      if me.attributes.anonymous
-        div#sign-up.alert.alert-info
-          strong(data-i18n="contribute.alert_account_message_intro")
-            | Hey there!
-          span  
-          span(data-i18n="contribute.alert_account_message_pref") 
-            | To subscribe for class emails, you'll need to 
-          a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
-            | create an account
-          span  
-          span(data-i18n="contribute.alert_account_message_suf")
-            | first.
+      .contributor-signup-anonymous
+      .contributor-signup(data-contributor-class-id="support", data-contributor-class-name="ambassador")
 
-      label.checkbox(for="support").well
-        input(type='checkbox', name="support", id="support")
-        span(data-i18n="contribute.ambassador_subscribe_desc")
-          | Get emails on support updates and multiplayer developments.
-        .saved-notification  ✓ Saved
-
-      //#Contributors
-      //  h3(data-i18n="contribute.helpful_ambassadors")
-      //    | Our Helpful Ambassadorsd:
-      //  ul.ambassadors
-      //    li 
+      //h3(data-i18n="contribute.helpful_ambassadors")
+      //  | Our Helpful Ambassadorsd:
+      //
+      //#contributor-list
 
     div.clearfix
diff --git a/app/templates/contribute/archmage.jade b/app/templates/contribute/archmage.jade
index db7dad7db..ae982472e 100644
--- a/app/templates/contribute/archmage.jade
+++ b/app/templates/contribute/archmage.jade
@@ -57,37 +57,12 @@ block content
         span(data-i18n="contribute.join_desc_4")
           | and we'll go from there!
 
-      if me.attributes.anonymous
-        div#sign-up.alert.alert-info
-          strong(data-i18n="contribute.alert_account_message_intro")
-            | Hey there!
-          span  
-          span(data-i18n="contribute.alert_account_message_pref") 
-            | To subscribe for class emails, you'll need to 
-          a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
-            | create an account
-          span  
-          span(data-i18n="contribute.alert_account_message_suf")
-            | first.
+      .contributor-signup-anonymous
+      .contributor-signup(data-contributor-class-id="developer", data-contributor-class-name="archmage")
 
-      label.checkbox(for="developer").well
-        input(type='checkbox', name="developer", id="developer")
-        span(data-i18n="contribute.archmage_subscribe_desc")
-          | Get emails on new coding opportunities and announcements.
-        .saved-notification  ✓ Saved
+      h3(data-i18n="contribute.powerful_archmages")
+        | Our Powerful Archmages:
 
-      #Contributors
-        h3(data-i18n="contribute.powerful_archmages")
-          | Our Powerful Archmages:
-        .row
-          for contributor in contributors
-            .col-xs-6.col-md-3
-              .thumbnail
-                if contributor.avatar
-                  img.img-responsive(src="/images/pages/contribute/archmage/" + contributor.avatar + "_small.png", alt="")
-                else
-                  img.img-responsive(src="/images/pages/contribute/archmage.png", alt="")
-                .caption
-                  h4= contributor.name
+      #contributor-list
 
     div.clearfix
diff --git a/app/templates/contribute/artisan.jade b/app/templates/contribute/artisan.jade
index 9e6d1320d..54a27327b 100644
--- a/app/templates/contribute/artisan.jade
+++ b/app/templates/contribute/artisan.jade
@@ -54,38 +54,13 @@ block content
         li
           a(href="http://discourse.codecombat.com", data-i18n="contribute.artisan_join_step4") Post your levels on the forum for feedback.
 
-      if me.attributes.anonymous
-        div#sign-up.alert.alert-info
-          strong(data-i18n="contribute.alert_account_message_intro")
-            | Hey there!
-          span  
-          span(data-i18n="contribute.alert_account_message_pref") 
-            | To subscribe for class emails, you'll need to 
-          a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
-            | create an account
-          span  
-          span(data-i18n="contribute.alert_account_message_suf")
-            | first.
+      .contributor-signup-anonymous
+      .contributor-signup(data-contributor-class-id="level_creator", data-contributor-class-name="artisan")
 
-      label.checkbox(for="level_creator").well
-        input(type='checkbox', name="level_creator", id="level_creator")
-        span(data-i18n="contribute.artisan_subscribe_desc")
-          | Get emails on level editor updates and announcements.
-        .saved-notification  ✓ Saved
+      h3(data-i18n="contribute.creative_artisans")
+        | Our Creative Artisans:
 
-      #Contributors
-        h3(data-i18n="contribute.creative_artisans")
-          | Our Creative Artisans:
-        .row
-          for contributor in contributors
-            .col-xs-6.col-md-3
-              .thumbnail
-                if contributor.avatar
-                  img.img-responsive(src="/images/pages/contribute/artisan/" + contributor.avatar + "_small.png", alt="")
-                else
-                  img.img-responsive(src="/images/pages/contribute/artisan.png", alt="")
-                .caption
-                  h4= contributor.name
+      #contributor-list
 
     div.clearfix
 
diff --git a/app/templates/contribute/contribute.jade b/app/templates/contribute/contribute.jade
index ffb7045a6..800b383e7 100644
--- a/app/templates/contribute/contribute.jade
+++ b/app/templates/contribute/contribute.jade
@@ -37,18 +37,7 @@ block content
           | - Nick, George, Scott, Michael, Jeremy and Glen
         hr
 
-      if me.attributes.anonymous
-        div#sign-up.alert.alert-info
-          strong(data-i18n="contribute.alert_account_message_intro")
-            | Hey there!
-          span  
-          span(data-i18n="contribute.alert_account_message_pref") 
-            | To subscribe for class emails, you'll need to 
-          a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
-            | create an account
-          span  
-          span(data-i18n="contribute.alert_account_message_suf")
-            | first.
+      .contributor-signup-anonymous
 
       #archmage.header-scrolling-fix
         .class_image
@@ -69,13 +58,7 @@ block content
           p.lead(data-i18n="contribute.more_about_archmage")
             | Learn More About Becoming an Archmage
 
-        label.checkbox(for="developer").well
-          input(type='checkbox', name="developer", id="developer")
-          span(data-i18n="contribute.archmage_subscribe_desc")
-            | Get emails on new coding opportunities and announcements.
-          .saved-notification
-            |  ✓
-            span(data-i18n="contribute.saved") Saved
+        .contributor-signup(data-contributor-class-id="developer", data-contributor-class-name="archmage")
 
       #artisan.header-scrolling-fix
 
@@ -102,13 +85,7 @@ block content
           p.lead(data-i18n="contribute.more_about_artisan")
             | Learn More About Becoming An Artisan
 
-        label.checkbox(for="level_creator").well
-          input(type='checkbox', name="level_creator", id="level_creator")
-          span(data-i18n="contribute.artisan_subscribe_desc")
-            | Get emails on level editor updates and announcements.
-          .saved-notification
-            |  ✓
-            span(data-i18n="contribute.saved") Saved
+        .contributor-signup(data-contributor-class-id="level_creator", data-contributor-class-name="artisan")
 
       #adventurer.header-scrolling-fix
 
@@ -130,13 +107,7 @@ block content
           p.lead(data-i18n="contribute.more_about_adventurer")
             | Learn More About Becoming an Adventurer
 
-        label.checkbox(for="tester").well
-          input(type='checkbox', name="tester", id="tester")
-          span(data-i18n="contribute.adventurer_subscribe_desc")  
-            | Get emails when there are new levels to test.
-          .saved-notification
-            |  ✓
-            span(data-i18n="contribute.saved") Saved
+        .contributor-signup(data-contributor-class-id="tester", data-contributor-class-name="adventurer")
     
       #scribe.header-scrolling-fix
 
@@ -162,13 +133,7 @@ block content
           p.lead(data-i18n="contribute.more_about_scribe")
             | Learn More About Becoming a Scribe
 
-        label.checkbox(for="article_editor").well
-          input(type='checkbox', name="article_editor", id="article_editor")
-          span(data-i18n="contribute.scribe_subscribe_desc")
-            | Get emails about article writing announcements.
-          .saved-notification
-            |  ✓
-            span(data-i18n="contribute.saved") Saved
+        .contributor-signup(data-contributor-class-id="article_editor", data-contributor-class-name="scribe")
 
       #diplomat.header-scrolling-fix
 
@@ -191,14 +156,8 @@ block content
           p.lead(data-i18n="contribute.more_about_diplomat")
             | Learn More About Becoming a Diplomat
 
-        label.checkbox(for="translator").well
-          input(type='checkbox', name="translator", id="translator")
-          span(data-i18n="contribute.diplomat_subscribe_desc")
-            | Get emails about i18n developments and levels to translate.
-          .saved-notification
-            |  ✓
-            span(data-i18n="contribute.saved") Saved
-      
+        .contributor-signup(data-contributor-class-id="translator", data-contributor-class-name="diplomat")
+
       #ambassador.header-scrolling-fix
 
         .class_image
@@ -218,13 +177,7 @@ block content
           p.lead(data-i18n="contribute.more_about_ambassador")
             | Learn More About Becoming an Ambassador
 
-        label.checkbox(for="support").well
-          input(type='checkbox', name="support", id="support")
-          span(data-i18n="contribute.ambassador_subscribe_desc")
-            | Get emails on support updates and multiplayer developments.
-          .saved-notification
-            |  ✓
-            span(data-i18n="contribute.saved") Saved
+        .contributor-signup(data-contributor-class-id="support", data-contributor-class-name="ambassador")
 
       #counselor.header-scrolling-fix
 
diff --git a/app/templates/contribute/contributor_list.jade b/app/templates/contribute/contributor_list.jade
new file mode 100644
index 000000000..32e5ac9e3
--- /dev/null
+++ b/app/templates/contribute/contributor_list.jade
@@ -0,0 +1,13 @@
+.row
+  for contributor in contributors
+    .col-xs-6.col-md-3
+      .thumbnail
+        - var src = "/images/pages/contribute/" + contributorClassName + ".png";
+        - if(contributor.avatar)
+        -   src = src.replace(contributorClassName, contributorClassName + "/" + contributor.avatar + "_small");
+        - if(contributor.id)
+        -   src = "/db/user/" + contributor.id + "/avatar?s=100&fallback=" + src;
+        a(href=contributor.github ? "https://github.com/codecombat/codecombat/commits?author=" + contributor.github : null, class=contributor.github ? 'has-github' : '')
+          img.img-responsive(src=src, alt=contributor.name)
+          .caption
+            h4= contributor.name
diff --git a/app/templates/contribute/contributor_signup.jade b/app/templates/contribute/contributor_signup.jade
new file mode 100644
index 000000000..2b9a8f188
--- /dev/null
+++ b/app/templates/contribute/contributor_signup.jade
@@ -0,0 +1,5 @@
+label.checkbox(for=contributorClassID).well
+  input(type='checkbox', name=contributorClassID, id=contributorClassID)
+  span(data-i18n="contribute.#{contributorClassName}_subscribe_desc")
+  .saved-notification  ✓ Saved
+
diff --git a/app/templates/contribute/contributor_signup_anonymous.jade b/app/templates/contribute/contributor_signup_anonymous.jade
new file mode 100644
index 000000000..5ee89a23a
--- /dev/null
+++ b/app/templates/contribute/contributor_signup_anonymous.jade
@@ -0,0 +1,12 @@
+if me.attributes.anonymous
+  div#sign-up.alert.alert-info
+    strong(data-i18n="contribute.alert_account_message_intro")
+      | Hey there!
+    span  
+    span(data-i18n="contribute.alert_account_message_pref") 
+      | To subscribe for class emails, you'll need to 
+    a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
+      | create an account
+    span  
+    span(data-i18n="contribute.alert_account_message_suf")
+      | first.
diff --git a/app/templates/contribute/diplomat.jade b/app/templates/contribute/diplomat.jade
index 3c161e778..1150bdda7 100644
--- a/app/templates/contribute/diplomat.jade
+++ b/app/templates/contribute/diplomat.jade
@@ -44,51 +44,37 @@ block content
           | , edit it online, and submit a pull request. Also, check this box below to 
           | keep up-to-date on new internationalization developments!
 
-      if me.attributes.anonymous
-        div#sign-up.alert.alert-info
-          strong(data-i18n="contribute.alert_account_message_intro")
-            | Hey there!
-          span  
-          span(data-i18n="contribute.alert_account_message_pref") 
-            | To subscribe for class emails, you'll need to 
-          a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
-            | create an account
-          span  
-          span(data-i18n="contribute.alert_account_message_suf")
-            | first.
+      .contributor-signup-anonymous
+      .contributor-signup(data-contributor-class-id="translator", data-contributor-class-name="diplomat")
 
-      label.checkbox(for="translator").well
-        input(type='checkbox', name="translator", id="translator")
-        span(data-i18n="contribute.diplomat_subscribe_desc")
-          | Get emails about i18n developments and levels to translate.
-        .saved-notification  ✓ Saved
+      h3(data-i18n="contribute.translating_diplomats")
+        | Our Translating Diplomats:
 
-      #Contributors
-        h3(data-i18n="contribute.translating_diplomats")
-          | Our Translating Diplomats:
-        ul.diplomats
-          li Turkish - Nazım Gediz Aydındoğmuş, cobaimelan, wakeup
-          li Brazilian Portuguese - Gutenberg Barros, Kieizroe, Matthew Burt, brunoporto, cassiocardoso
-          li Portugal Portuguese - Matthew Burt, ReiDuKuduro
-          li German - Dirk, faabsen, HiroP0, Anon, bkimminich
-          li Thai - Kamolchanok Jittrepit
-          li Vietnamese - An Nguyen Hoang Thien
-          li Dutch - Glen De Cauwsemaecker, Guido Zuidhof, Ruben Vereecken, Jasper D'haene
-          li Greek - Stergios
-          li Latin American Spanish - Jesús Ruppel, Matthew Burt, Mariano Luzza
-          li Spain Spanish - Matthew Burt, DanielRodriguezRivero, Anon, Pouyio
-          li French - Xeonarno, Elfisen, Armaldio, MartinDelille, pstweb, veritable, jaybi, xavismeh, Anon, Feugy
-          li Hungarian - ferpeter, csuvsaregal, atlantisguru, Anon
-          li Japanese - g1itch, kengos
-          li Chinese - Adam23, spacepope, yangxuan8282, Cheng Zheng
-          li Polish - Anon, Kacper Ciepielewski
-          li Danish - Einar Rasmussen, sorsjen, Randi Hillerøe, Anon
-          li Slovak - Anon
-          li Persian - Reza Habibi (Rehb)
-          li Czech - vanous
-          li Russian - fess89, ser-storchak, Mr A
-          li Ukrainian - fess89
-          li Italian - flauta
-          li Norwegian - bardeh
+      //#contributor-list
+      // TODO: collect CodeCombat userids for these guys so we can include a tiled list
+      ul.diplomats
+        li Turkish - Nazım Gediz Aydındoğmuş, cobaimelan, wakeup
+        li Brazilian Portuguese - Gutenberg Barros, Kieizroe, Matthew Burt, brunoporto, cassiocardoso
+        li Portugal Portuguese - Matthew Burt, ReiDuKuduro
+        li German - Dirk, faabsen, HiroP0, Anon, bkimminich
+        li Thai - Kamolchanok Jittrepit
+        li Vietnamese - An Nguyen Hoang Thien
+        li Dutch - Glen De Cauwsemaecker, Guido Zuidhof, Ruben Vereecken, Jasper D'haene
+        li Greek - Stergios
+        li Latin American Spanish - Jesús Ruppel, Matthew Burt, Mariano Luzza
+        li Spain Spanish - Matthew Burt, DanielRodriguezRivero, Anon, Pouyio
+        li French - Xeonarno, Elfisen, Armaldio, MartinDelille, pstweb, veritable, jaybi, xavismeh, Anon, Feugy
+        li Hungarian - ferpeter, csuvsaregal, atlantisguru, Anon
+        li Japanese - g1itch, kengos
+        li Chinese - Adam23, spacepope, yangxuan8282, Cheng Zheng
+        li Polish - Anon, Kacper Ciepielewski
+        li Danish - Einar Rasmussen, sorsjen, Randi Hillerøe, Anon
+        li Slovak - Anon
+        li Persian - Reza Habibi (Rehb)
+        li Czech - vanous
+        li Russian - fess89, ser-storchak, Mr A
+        li Ukrainian - fess89
+        li Italian - flauta
+        li Norwegian - bardeh
 
     div.clearfix
diff --git a/app/templates/contribute/scribe.jade b/app/templates/contribute/scribe.jade
index eafab49b6..92155143c 100644
--- a/app/templates/contribute/scribe.jade
+++ b/app/templates/contribute/scribe.jade
@@ -44,37 +44,12 @@ block content
           | tell us a little about yourself, your experience with programming and
           | what sort of things you'd like to write about. We'll go from there!
 
-      if me.attributes.anonymous
-        div#sign-up.alert.alert-info
-          strong(data-i18n="contribute.alert_account_message_intro")
-            | Hey there!
-          span  
-          span(data-i18n="contribute.alert_account_message_pref") 
-            | To subscribe for class emails, you'll need to 
-          a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
-            | create an account
-          span  
-          span(data-i18n="contribute.alert_account_message_suf")
-            | first.
+      .contributor-signup-anonymous
+      .contributor-signup(data-contributor-class-id="article_editor", data-contributor-class-name="scribe")
 
-      label.checkbox(for="article_editor").well
-        input(type='checkbox', name="article_editor", id="article_editor")
-        span(data-i18n="contribute.scribe_subscribe_desc")
-          | Get emails about article writing announcements.
-        .saved-notification  ✓ Saved
-
-      #Contributors
-        h3(data-i18n="contribute.diligent_scribes")
-          | Our Diligent Scribes:
-        ul.scribes
-          li Ryan Faidley
-          li Glen De Cauwsemaecker
-          li Mischa Lewis-Norelle
-          li Tavio
-          li Ronnie Cheng
-          li engstrom
-          li Dman19993
-          li mattinsler
-          
+      h3(data-i18n="contribute.diligent_scribes")
+        | Our Diligent Scribes:
+      
+      #contributor-list(data-contributor-class-name="scribe")
 
     div.clearfix
diff --git a/app/views/account/job_profile_view.coffee b/app/views/account/job_profile_view.coffee
index d14fc2f79..940d52ffe 100644
--- a/app/views/account/job_profile_view.coffee
+++ b/app/views/account/job_profile_view.coffee
@@ -14,12 +14,6 @@ module.exports = class JobProfileView extends CocoView
     'updated'
   ]
 
-  constructor: (options) ->
-    super options
-    unless me.schema().loaded
-      @addSomethingToLoad("user_schema")
-      @listenToOnce me, 'schema-loaded', => @somethingLoaded 'user_schema'
-
   afterRender: ->
     super()
     return if @loading()
@@ -29,6 +23,7 @@ module.exports = class JobProfileView extends CocoView
     visibleSettings = @editableSettings.concat @readOnlySettings
     data = _.pick (me.get('jobProfile') ? {}), (value, key) => key in visibleSettings
     data.name ?= (me.get('firstName') + ' ' + me.get('lastName')).trim() if me.get('firstName')
+    console.log 'schema?', me.schema()
     schema = _.cloneDeep me.schema().properties.jobProfile
     schema.properties = _.pick schema.properties, (value, key) => key in visibleSettings
     schema.required = _.intersection schema.required, visibleSettings
diff --git a/app/views/account/settings_view.coffee b/app/views/account/settings_view.coffee
index e74db5f65..5e1d606da 100644
--- a/app/views/account/settings_view.coffee
+++ b/app/views/account/settings_view.coffee
@@ -43,11 +43,7 @@ module.exports = class SettingsView extends View
     @jobProfileView = new JobProfileView()
     @listenTo @jobProfileView, 'change', @save
     @insertSubView @jobProfileView
-
-    if me.schema().loaded
-      @buildPictureTreema()
-    else
-      @listenToOnce me, 'schema-loaded', @buildPictureTreema
+    @buildPictureTreema()
 
   chooseTab: (category) ->
     id = "##{category}-pane"
@@ -85,6 +81,7 @@ module.exports = class SettingsView extends View
     schema = _.cloneDeep me.schema()
     schema.properties = _.pick me.schema().properties, 'photoURL'
     schema.required = ['photoURL']
+    console.log 'have data', data, 'schema', schema
     treemaOptions =
       filePath: "db/user/#{me.id}"
       schema: schema
@@ -92,8 +89,8 @@ module.exports = class SettingsView extends View
       callbacks: {change: @onPictureChanged}
 
     @pictureTreema = @$el.find('#picture-treema').treema treemaOptions
-    @pictureTreema.build()
-    @pictureTreema.open()
+    @pictureTreema?.build()
+    @pictureTreema?.open()
     @$el.find('.gravatar-fallback').toggle not me.get 'photoURL'
 
   onPictureChanged: (e) =>
diff --git a/app/views/contribute/adventurer_view.coffee b/app/views/contribute/adventurer_view.coffee
index cdb711e98..9428a8624 100644
--- a/app/views/contribute/adventurer_view.coffee
+++ b/app/views/contribute/adventurer_view.coffee
@@ -4,4 +4,5 @@ template = require 'templates/contribute/adventurer'
 
 module.exports = class AdventurerView extends ContributeClassView
   id: "adventurer-view"
-  template: template
\ No newline at end of file
+  template: template
+  contributorClassName: 'adventurer'
diff --git a/app/views/contribute/ambassador_view.coffee b/app/views/contribute/ambassador_view.coffee
index 669951176..6ea7a68cd 100644
--- a/app/views/contribute/ambassador_view.coffee
+++ b/app/views/contribute/ambassador_view.coffee
@@ -5,3 +5,4 @@ template = require 'templates/contribute/ambassador'
 module.exports = class AmbassadorView extends ContributeClassView
   id: "ambassador-view"
   template: template
+  contributorClassName: 'ambassador'
diff --git a/app/views/contribute/archmage_view.coffee b/app/views/contribute/archmage_view.coffee
index ec18303f8..7ac7508ca 100644
--- a/app/views/contribute/archmage_view.coffee
+++ b/app/views/contribute/archmage_view.coffee
@@ -4,28 +4,30 @@ template = require 'templates/contribute/archmage'
 module.exports = class ArchmageView extends ContributeClassView
   id: "archmage-view"
   template: template
+  contributorClassName: 'archmage'
 
   contributors: [
-    {name: "Tom Steinbrecher", avatar: "tom"}
-    {name: "Sébastien Moratinos", avatar: "sebastien"}
-    {name: "deepak1556", avatar: "deepak"}
-    {name: "Ronnie Cheng", avatar: "ronald"}
-    {name: "Chloe Fan", avatar: "chloe"}
-    {name: "Rachel Xiang", avatar: "rachel"}
-    {name: "Dan Ristic", avatar: "dan"}
-    {name: "Brad Dickason", avatar: "brad"}
+    {id: "52bfc3ecb7ec628868001297", name: "Tom Steinbrecher", github: "TomSteinbrecher"}
+    {id: "5272806093680c5817033f73", name: "Sébastien Moratinos", github: "smoratinos"}
+    {name: "deepak1556", avatar: "deepak", github: "deepak1556"}
+    {name: "Ronnie Cheng", avatar: "ronald", github: "rhc2104"}
+    {name: "Chloe Fan", avatar: "chloe", github: "chloester"}
+    {name: "Rachel Xiang", avatar: "rachel", github: "rdxiang"}
+    {name: "Dan Ristic", avatar: "dan", github: "dristic"}
+    {name: "Brad Dickason", avatar: "brad", github: "bdickason"}
     {name: "Rebecca Saines", avatar: "becca"}
-    {name: "Laura Watiker", avatar: "laura"}
-    {name: "Shiying Zheng", avatar: "shiying"}
-    {name: "Mischa Lewis-Norelle", avatar: "mischa"}
+    {name: "Laura Watiker", avatar: "laura", github: "lwatiker"}
+    {name: "Shiying Zheng", avatar: "shiying", github: "shiyingzheng"}
+    {name: "Mischa Lewis-Norelle", avatar: "mischa", github: "mlewisno"}
     {name: "Paul Buser", avatar: "paul"}
     {name: "Benjamin Stern", avatar: "ben"}
     {name: "Alex Cotsarelis", avatar: "alex"}
     {name: "Ken Stanley", avatar: "ken"}
-    {name: "devast8a", avatar: ""}
-    {name: "phansch", avatar: ""}
-    {name: "Zach Martin", avatar: ""}
+    {name: "devast8a", avatar: "", github: "devast8a"}
+    {name: "phansch", avatar: "", github: "phansch"}
+    {name: "Zach Martin", avatar: "", github: "zachster01"}
     {name: "David Golds", avatar: ""}
-    {name: "gabceb", avatar: ""}
-    {name: "MDP66", avatar: ""}
+    {name: "gabceb", avatar: "", github: "gabceb"}
+    {name: "MDP66", avatar: "", github: "MDP66"}
+    {name: "Alexandru Caciulescu", avatar: "", github: "Darredevil"}
   ]
diff --git a/app/views/contribute/artisan_view.coffee b/app/views/contribute/artisan_view.coffee
index b7d184d57..dbad64902 100644
--- a/app/views/contribute/artisan_view.coffee
+++ b/app/views/contribute/artisan_view.coffee
@@ -5,10 +5,11 @@ template = require 'templates/contribute/artisan'
 module.exports = class ArtisanView extends ContributeClassView
   id: "artisan-view"
   template: template
+  contributorClassName: 'artisan'
 
   contributors: [
     {name: "Sootn", avatar: ""}
-    {name: "Zach Martin", avatar: ""}
+    {name: "Zach Martin", avatar: "", github: "zachster01"}
     {name: "Aftermath", avatar: ""}
     {name: "mcdavid1991", avatar: ""}
     {name: "dwhittaker", avatar: ""}
@@ -19,6 +20,6 @@ module.exports = class ArtisanView extends ContributeClassView
     {name: "Axandre Oge", avatar: "axandre"}
     {name: "Katharine Chan", avatar: "katharine"}
     {name: "Derek Wong", avatar: "derek"}
-    {name: "Alexandru Caciulescu", avatar: ""}
-    {name: "Prabh Simran Singh Baweja", avatar: ""}
+    {name: "Alexandru Caciulescu", avatar: "", github: "Darredevil"}
+    {name: "Prabh Simran Singh Baweja", avatar: "", github: "prabh27"}
   ]
diff --git a/app/views/contribute/contribute_class_view.coffee b/app/views/contribute/contribute_class_view.coffee
index 5442ff719..246499694 100644
--- a/app/views/contribute/contribute_class_view.coffee
+++ b/app/views/contribute/contribute_class_view.coffee
@@ -1,6 +1,9 @@
 SignupModalView = require 'views/modal/signup_modal'
 View = require 'views/kinds/RootView'
 {me} = require('lib/auth')
+contributorSignupAnonymousTemplate = require 'templates/contribute/contributor_signup_anonymous'
+contributorSignupTemplate = require 'templates/contribute/contributor_signup'
+contributorListTemplate = require 'templates/contribute/contributor_list'
 
 module.exports = class ContributeClassView extends View
   navPrefix: '/contribute'
@@ -16,6 +19,12 @@ module.exports = class ContributeClassView extends View
 
   afterRender: ->
     super()
+    @$el.find('.contributor-signup-anonymous').replaceWith(contributorSignupAnonymousTemplate(me: me))
+    @$el.find('.contributor-signup').each ->
+      context = me: me, contributorClassID: $(@).data('contributor-class-id'), contributorClassName: $(@).data('contributor-class-name')
+      $(@).replaceWith(contributorSignupTemplate(context))
+    @$el.find('#contributor-list').replaceWith(contributorListTemplate(contributors: @contributors, contributorClassName: @contributorClassName))
+
     checkboxes = @$el.find('input[type="checkbox"]').toArray()
     _.forEach checkboxes, (el) ->
       el = $(el)
diff --git a/app/views/contribute/counselor_view.coffee b/app/views/contribute/counselor_view.coffee
index b589c4ed9..6e5a6be2c 100644
--- a/app/views/contribute/counselor_view.coffee
+++ b/app/views/contribute/counselor_view.coffee
@@ -5,3 +5,4 @@ template = require 'templates/contribute/counselor'
 module.exports = class CounselorView extends ContributeClassView
   id: "counselor-view"
   template: template
+  contributorClassName: 'counselor'
diff --git a/app/views/contribute/diplomat_view.coffee b/app/views/contribute/diplomat_view.coffee
index 6b159bfed..0769af517 100644
--- a/app/views/contribute/diplomat_view.coffee
+++ b/app/views/contribute/diplomat_view.coffee
@@ -5,3 +5,4 @@ template = require 'templates/contribute/diplomat'
 module.exports = class DiplomatView extends ContributeClassView
   id: "diplomat-view"
   template: template
+  contributorClassName: 'diplomat'
diff --git a/app/views/contribute/scribe_view.coffee b/app/views/contribute/scribe_view.coffee
index 2aedbbb98..7f87a3275 100644
--- a/app/views/contribute/scribe_view.coffee
+++ b/app/views/contribute/scribe_view.coffee
@@ -5,3 +5,14 @@ template = require 'templates/contribute/scribe'
 module.exports = class ScribeView extends ContributeClassView
   id: "scribe-view"
   template: template
+  contributorClassName: 'scribe'
+
+  contributors: [
+    {name: "Ryan Faidley"}
+    {name: "Mischa Lewis-Norelle", github: "mlewisno"}
+    {name: "Tavio"}
+    {name: "Ronnie Cheng", github: "rhc2104"}
+    {name: "engstrom"}
+    {name: "Dman19993"}
+    {name: "mattinsler"}
+  ]
diff --git a/app/views/editor/article/edit.coffee b/app/views/editor/article/edit.coffee
index 31acafbca..0123546e0 100644
--- a/app/views/editor/article/edit.coffee
+++ b/app/views/editor/article/edit.coffee
@@ -35,17 +35,11 @@ module.exports = class ArticleEditView extends View
     )
 
     @article.fetch()
-    @article.loadSchema()
-    @listenToOnce(@article, 'sync', @onArticleSync)
-    @listenToOnce(@article, 'schema-loaded', @buildTreema)
+    @listenToOnce(@article, 'sync', @buildTreema)
     @pushChangesToPreview = _.throttle(@pushChangesToPreview, 500)
 
-  onArticleSync: ->
-    @article.loaded = true
-    @buildTreema()
-
   buildTreema: ->
-    return if @treema? or (not @article.loaded) or (not Article.hasSchema())
+    return if @treema? or (not @article.loaded)
     unless @article.attributes.body
       @article.set('body', '')
     @startsLoading = false
diff --git a/app/views/editor/components/main.coffee b/app/views/editor/components/main.coffee
index 2c39b6086..0104aa5d9 100644
--- a/app/views/editor/components/main.coffee
+++ b/app/views/editor/components/main.coffee
@@ -20,9 +20,6 @@ module.exports = class ThangComponentEditView extends CocoView
 
   render: =>
     return if @destroyed
-    for model in [Level, LevelComponent]
-      temp = new model()
-      @listenToOnce temp, 'schema-loaded', @render unless model.schema?.loaded
     if not @componentCollection
       @componentCollection = @supermodel.getCollection new ComponentsCollection()
     unless @componentCollection.loaded
@@ -32,7 +29,7 @@ module.exports = class ThangComponentEditView extends CocoView
 
   afterRender: ->
     super()
-    return @showLoading() unless @componentCollection?.loaded and Level.schema.loaded and LevelComponent.schema.loaded
+    return @showLoading() unless @componentCollection?.loaded
     @hideLoading()
     @buildExtantComponentTreema()
     @buildAddComponentTreema()
diff --git a/app/views/editor/thang/edit.coffee b/app/views/editor/thang/edit.coffee
index 7c3500fad..c5b08d7c0 100644
--- a/app/views/editor/thang/edit.coffee
+++ b/app/views/editor/thang/edit.coffee
@@ -61,12 +61,11 @@ module.exports = class ThangTypeEditView extends View
     )
 
     @thangType.fetch()
-    @thangType.loadSchema()
     @listenToOnce(@thangType, 'sync', @onThangTypeSync)
     @refreshAnimation = _.debounce @refreshAnimation, 500
 
   onThangTypeSync: ->
-    return unless @thangType.loaded and ThangType.hasSchema()
+    return unless @thangType.loaded
     @startsLoading = false
     @files = new DocumentFiles(@thangType)
     @files.fetch()
diff --git a/app/views/kinds/RootView.coffee b/app/views/kinds/RootView.coffee
index fd824cd47..7ef3e7221 100644
--- a/app/views/kinds/RootView.coffee
+++ b/app/views/kinds/RootView.coffee
@@ -41,13 +41,13 @@ module.exports = class RootView extends CocoView
     hash = location.hash
     location.hash = ''
     location.hash = hash
-    @buildLanguages()
     @renderScrollbar()
     #@$('.antiscroll-wrap').antiscroll()  # not yet, buggy
 
   afterRender: ->
     super(arguments...)
     @chooseTab(location.hash.replace('#','')) if location.hash
+    @buildLanguages()
     $('body').removeClass('is-playing')
 
   chooseTab: (category) ->
@@ -58,7 +58,7 @@ module.exports = class RootView extends CocoView
   buildLanguages: ->
     $select = @$el.find(".language-dropdown").empty()
     if $select.hasClass("fancified")
-      $select.parent().find('.options,.trigger').remove()
+      $select.parent().find('.options, .trigger').remove()
       $select.unwrap().removeClass("fancified")
     preferred = me.lang()
     codes = _.keys(locale)
@@ -76,10 +76,8 @@ module.exports = class RootView extends CocoView
     $.i18n.setLng(newLang, {})
     @saveLanguage(newLang)
     @render()
-    @buildLanguages()
     unless newLang.split('-')[0] is "en"
       @openModalView(application.router.getView("modal/diplomat_suggestion", "_modal"))
-    $('body').attr('lang', newLang)
 
   saveLanguage: (newLang) ->
     me.set('preferredLanguage', newLang)
diff --git a/app/views/play_view.coffee b/app/views/play_view.coffee
index d505cb5e6..349f900c7 100644
--- a/app/views/play_view.coffee
+++ b/app/views/play_view.coffee
@@ -227,4 +227,3 @@ module.exports = class PlayView extends View
     super()
     @$el.find('.modal').on 'shown.bs.modal', ->
       $('input:visible:first', @).focus()
-    
diff --git a/scripts/windows/coco-dev-setup/batch/config/localized/license-ru.coco b/scripts/windows/coco-dev-setup/batch/config/localized/license-ru.coco
new file mode 100644
index 000000000..48ad97ea1
--- /dev/null
+++ b/scripts/windows/coco-dev-setup/batch/config/localized/license-ru.coco
@@ -0,0 +1,10 @@
+ 
+��業��� MIT (���)
+ 
+Copyright (c) 2014 CodeCombat Inc. � ��㣨� ���⭨��
+ 
+������ ��業��� ࠧ�蠥� ��栬, ����稢訬 ����� ������� �ணࠬ����� ���ᯥ祭�� � ᮯ������饩 ���㬥��樨 (� ���쭥�襬 ����㥬묨 <�ணࠬ���� ���ᯥ祭��>), ������������ �ᯮ�짮���� �ணࠬ���� ���ᯥ祭�� ��� ��࠭�祭��, ������ ����࠭�祭��� �ࠢ� �� �ᯮ�짮�����, ����஢����, ���������, ����������, �㡫�����, �����࠭����, �㡫�業��஢���� �/��� �த��� ����� �ணࠬ����� ���ᯥ祭��, ⠪�� ��� � ��栬, ����� �।��⠢����� ������ �ணࠬ���� ���ᯥ祭��, �� ᮡ���� ᫥����� �᫮���:
+ 
+��������� ��� 㢥�������� �� ����᪮� �ࠢ� � ����� �᫮��� ������ ���� ����祭� �� �� ����� ��� ���稬� ��� ������� �ணࠬ����� ���ᯥ祭��.
+ 
+������ ����������� ����������� ��������������� <��� ����>, ��� �����-���� ��������, ���� ���������� ��� ���������������, �������, �� �� ������������� ���������� �������� �����������, ������������ �� ��� ����������� ���������� � ���������� ��������� ����. �� � ����� ������ ������ ��� ��������������� �� ����� ��������������� �� ����� � ���������� ������, ������� ��� ������ ���������� �� ����������� ����������, �������� ��� �����, ��������� ��, ������� �������� ��� ��������� � ����������� ������������ ��� �������������� ������������ ����������� ��� ����� ���������� � ����������� ������������.
\ No newline at end of file
diff --git a/scripts/windows/coco-dev-setup/batch/config/localized/readme-ru.coco b/scripts/windows/coco-dev-setup/batch/config/localized/readme-ru.coco
new file mode 100644
index 000000000..c62f89900
--- /dev/null
+++ b/scripts/windows/coco-dev-setup/batch/config/localized/readme-ru.coco
@@ -0,0 +1,29 @@
+       _____           _        _____                 _           _   
+      /  __ \         | |      /  __ \               | |         | |  
+      | /  \/ ___   __| | ___  | /  \/ ___  _ __ ___ | |__   __ _| |_ 
+      | |    / _ \ / _` |/ _ \ | |    / _ \| '_ ` _ \| '_ \ / _` | __|
+      | \__/\ (_) | (_| |  __/ | \__/\ (_) | | | | | | |_) | (_| | |_ 
+       \____/\___/ \__,_|\___|  \____/\___/|_| |_| |_|_.__/ \__,_|\__|
+ 
+=============================================================================
+ 
+����ࠢ�塞, ⥯��� �� ���� ᮮ���⢠ CodeCombat.
+������, ����� ��� �।� ࠧࠡ��稪� ��⠭������, �� ��⮢� �����
+������ ����� � ������ ��� ᤥ���� ��� ��� ����.
+ 
+� ��� ���� ������ ��� �� �⥫� �� � ���� ���������?
+�������� � ���� � hipchat @ https://www.hipchat.com/g3plnOKqa
+ 
+�� ���� ᯮᮡ ���⨦���� �⮣� - ���饭�� ��襣� ��㬠.
+�� ����� ���� ��� @ http://discourse.codecombat.com/
+ 
+�� ����� ������ � ��᫥���� ���⨦����� � ��襬 �����.
+��� ����� ���� @ http://blog.codecombat.com/
+ 
+� ��᫥����, �� �� �� ���祭��, - �� ����� ���� ������� ���� ���㬥��樨
+� ���ଠ樨 � ��襩 ���� @ https://github.com/codecombat/codecombat/wiki
+ 
+�� ��������, �� �� �㤥� ��᫠������� � ��襬 ᮮ���⢥ ⠪ ��, ��� � ��.
+ 
+ 
+                            - ���, ���द, �����, ������, ���६� � ����
diff --git a/scripts/windows/coco-dev-setup/batch/config/localized/tips-ru.coco b/scripts/windows/coco-dev-setup/batch/config/localized/tips-ru.coco
new file mode 100644
index 000000000..90d791d16
--- /dev/null
+++ b/scripts/windows/coco-dev-setup/batch/config/localized/tips-ru.coco
@@ -0,0 +1,7 @@
+  1) ����� �������� �����, ��������, �⢥砩� �����⥫쭮 � �ࠢ��쭮
+  2) ����� ��⠭��騪 ��室���� � �⠤�� ���� � ����� ᮤ�ঠ�� ����
+  3) �� ����� ᮮ���� � ����� @ 'https://github.com/codecombat/codecombat/issues'
+  4) ���� ������/�।�������? �������� � ���� � HipChat �१ CodeCombat.com
+ 
+  �� ����� ���� ��蠣���� �㪮����⢮ ��� ������� ��⠭��騪� � ��襩 ����.
+  github.com/codecombat/codecombat/wiki/Setup-on-Windows:-a-step-by-step-guide
\ No newline at end of file
diff --git a/scripts/windows/coco-dev-setup/batch/localization/ru.coco b/scripts/windows/coco-dev-setup/batch/localization/ru.coco
index 150391711..9914b5d44 100644
--- a/scripts/windows/coco-dev-setup/batch/localization/ru.coco
+++ b/scripts/windows/coco-dev-setup/batch/localization/ru.coco
@@ -3,19 +3,19 @@
 	<global>
 		<native>�������</native>
 		<description>Russian</description>
-		<tips>Before we start the installation, here are some tips:</tips>
-		<exit>Press any key to exit...</exit>
+		<tips>����� ���, ��� �� ������ ���������, ��� ��������� �������:</tips>
+		<exit>������� Enter ��� ������...</exit>
 	</global>
 	<language>
-		<choosen>You have choosen ������� as your language.</choosen>
+		<choosen>�� ������� ������� � �������� ������ �����.</choosen>
 		<feedback>C ������� ������� �� ����� �������� �� �������.</feedback>
 	</language>
 	<license>
-		<s1>In order to continue the installation of the developers environment</s1>
-		<s2>you will have to read and agree with the following license:</s2>
-		<q1>Have you read the license and do you agree with it?</q1>
-		<a1>This setup can't happen without an agreement.</a1>
-		<a2>Installation and Setup of the CodeCombat environment is cancelled.</a2>
+		<s1>��� ����, ����� ���������� ��������� ����� ������������</s1>
+		<s2>�� ������ ��������� � ����������� �� ��������� ���������:</s2>
+		<q1>�� ��������� �������� � �������� � ���?</q1>
+		<a1>������ ��������� �� �������� ��� ��������.</a1>
+		<a2>��������� � ��������� ����� CodeCombat ��������.</a2>
 	</license>
 	<install>
 		<system>
@@ -38,7 +38,7 @@
 			<downloading>�����������...</downloading>
 			<installing>���������������...</installing>
 			<unzipping>���������������...</unzipping>
-			<cleaning>���������...</cleaning>
+			<cleaning>�����������...</cleaning>
 			<mongodbpath>����������, ���������� ������ ����, ���� ������ ���� ���������� MongoDB</mongodbpath>
 		</process>
 	</install>
@@ -53,7 +53,7 @@
 			<question>�� ������ �������� ��������� Local Git ������� ��������������?</question>
 			<consequence>���������, ��� �� ��������� ��������� ����������� ����� �����������.</consequence>
 			<donotclose>�� ���������� ��� ����, ����������.</donotclose>
-			<wait>����� �� ������ ������, ������� ����� ������� ��� �����������...</wait>
+			<wait>����� �� ������ ������, ������� Enter ��� �����������...</wait>
 		</skip>
 		<process>
 			<path>����������, ������� ������ ���� �� ������ CodeCombat ����������� git: </path>
diff --git a/server/articles/article_handler.coffee b/server/articles/article_handler.coffee
index 1d9e90436..8aa2d26dc 100644
--- a/server/articles/article_handler.coffee
+++ b/server/articles/article_handler.coffee
@@ -4,7 +4,7 @@ Handler = require('../commons/Handler')
 ArticleHandler = class ArticleHandler extends Handler
   modelClass: Article
   editableProperties: ['body', 'name', 'i18n']
-  jsonSchema: require './article_schema'
+  jsonSchema: require '../../app/schemas/models/article'
 
   hasAccess: (req) ->
     req.method is 'GET' or req.user?.isAdmin()
diff --git a/server/commons/mapping.coffee b/server/commons/mapping.coffee
index d7400c951..3cfcc2164 100644
--- a/server/commons/mapping.coffee
+++ b/server/commons/mapping.coffee
@@ -10,21 +10,6 @@ module.exports.handlers =
   'thang_type': 'levels/thangs/thang_type_handler'
   'user': 'users/user_handler'
 
-module.exports.schemas =
-  'article': 'articles/article_schema'
-  'common': 'commons/schemas'
-  'i18n': 'commons/i18n_schema'
-  'level': 'levels/level_schema'
-  'level_component': 'levels/components/level_component_schema'
-  'level_feedback': 'levels/feedbacks/level_feedback_schema'
-  'level_session': 'levels/sessions/level_session_schema'
-  'level_system': 'levels/systems/level_system_schema'
-  'metaschema': 'commons/metaschema'
-  'patch': 'patches/patch_schema'
-  'thang_component': 'levels/thangs/thang_component_schema'
-  'thang_type': 'levels/thangs/thang_type_schema'
-  'user': 'users/user_schema'
-
 module.exports.routes =
   [
     'routes/auth'
diff --git a/server/levels/Level.coffee b/server/levels/Level.coffee
index 83e8d678b..9cadeac7b 100644
--- a/server/levels/Level.coffee
+++ b/server/levels/Level.coffee
@@ -1,6 +1,6 @@
 mongoose = require('mongoose')
 plugins = require('../plugins/plugins')
-jsonschema = require('../../app/schemas/level_schema')
+jsonschema = require('../../app/schemas/models/level')
 
 LevelSchema = new mongoose.Schema({
   description: String
diff --git a/server/levels/components/LevelComponent.coffee b/server/levels/components/LevelComponent.coffee
index 5f00f261c..6c1a58370 100644
--- a/server/levels/components/LevelComponent.coffee
+++ b/server/levels/components/LevelComponent.coffee
@@ -1,6 +1,6 @@
 mongoose = require('mongoose')
 plugins = require('../../plugins/plugins')
-jsonschema = require('../../../app/schemas/level_component_schema')
+jsonschema = require('../../../app/schemas/models/level_component')
 
 LevelComponentSchema = new mongoose.Schema {
   description: String
diff --git a/server/levels/components/level_component_handler.coffee b/server/levels/components/level_component_handler.coffee
index e2b7a2ba8..3bcc572d0 100644
--- a/server/levels/components/level_component_handler.coffee
+++ b/server/levels/components/level_component_handler.coffee
@@ -3,7 +3,7 @@ Handler = require('../../commons/Handler')
 
 LevelComponentHandler = class LevelComponentHandler extends Handler
   modelClass: LevelComponent
-  jsonSchema: require '../../../app/schemas/level_component_schema'
+  jsonSchema: require '../../../app/schemas/models/level_component'
   editableProperties: [
     'system'
     'description'
diff --git a/server/levels/feedbacks/LevelFeedback.coffee b/server/levels/feedbacks/LevelFeedback.coffee
index 234caf367..5fef6a567 100644
--- a/server/levels/feedbacks/LevelFeedback.coffee
+++ b/server/levels/feedbacks/LevelFeedback.coffee
@@ -2,7 +2,7 @@
 
 mongoose = require('mongoose')
 plugins = require('../../plugins/plugins')
-jsonschema = require('../../../app/schemas/level_feedback_schema')
+jsonschema = require('../../../app/schemas/models/level_feedback')
 
 LevelFeedbackSchema = new mongoose.Schema({
   created:
diff --git a/server/levels/feedbacks/level_feedback_handler.coffee b/server/levels/feedbacks/level_feedback_handler.coffee
index cd4ffda26..58d268db1 100644
--- a/server/levels/feedbacks/level_feedback_handler.coffee
+++ b/server/levels/feedbacks/level_feedback_handler.coffee
@@ -4,7 +4,7 @@ Handler = require('../../commons/Handler')
 class LevelFeedbackHandler extends Handler
   modelClass: LevelFeedback
   editableProperties: ['rating', 'review', 'level', 'levelID', 'levelName']
-  jsonSchema: require '../../../app/schemas/level_feedback_schema'
+  jsonSchema: require '../../../app/schemas/models/level_feedback'
 
   makeNewInstance: (req) ->
     feedback = super(req)
diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee
index 9a9a8aafd..f0c6d225b 100644
--- a/server/levels/level_handler.coffee
+++ b/server/levels/level_handler.coffee
@@ -8,7 +8,7 @@ mongoose = require('mongoose')
 
 LevelHandler = class LevelHandler extends Handler
   modelClass: Level
-  jsonSchema: require '../../app/schemas/level_schema'
+  jsonSchema: require '../../app/schemas/models/level'
   editableProperties: [
     'description'
     'documentation'
diff --git a/server/levels/sessions/LevelSession.coffee b/server/levels/sessions/LevelSession.coffee
index d91b7241c..c30519ba0 100644
--- a/server/levels/sessions/LevelSession.coffee
+++ b/server/levels/sessions/LevelSession.coffee
@@ -2,7 +2,7 @@
 
 mongoose = require('mongoose')
 plugins = require('../../plugins/plugins')
-jsonschema = require('../../../app/schemas/level_session_schema')
+jsonschema = require('../../../app/schemas/models/level_session')
 
 LevelSessionSchema = new mongoose.Schema({
   created:
diff --git a/server/levels/sessions/level_session_handler.coffee b/server/levels/sessions/level_session_handler.coffee
index 25131833d..5771711f2 100644
--- a/server/levels/sessions/level_session_handler.coffee
+++ b/server/levels/sessions/level_session_handler.coffee
@@ -9,7 +9,7 @@ class LevelSessionHandler extends Handler
   editableProperties: ['multiplayer', 'players', 'code', 'completed', 'state',
                        'levelName', 'creatorName', 'levelID', 'screenshot',
                        'chat', 'teamSpells', 'submitted', 'unsubscribed']
-  jsonSchema: require '../../../app/schemas/level_session_schema'
+  jsonSchema: require '../../../app/schemas/models/level_session'
 
   getByRelationship: (req, res, args...) ->
     return @getActiveSessions req, res if args.length is 2 and args[1] is 'active'
diff --git a/server/levels/systems/LevelSystem.coffee b/server/levels/systems/LevelSystem.coffee
index 730b338ad..f945aaa95 100644
--- a/server/levels/systems/LevelSystem.coffee
+++ b/server/levels/systems/LevelSystem.coffee
@@ -1,6 +1,6 @@
 mongoose = require('mongoose')
 plugins = require('../../plugins/plugins')
-jsonschema = require('../../../app/schemas/level_system_schema')
+jsonschema = require('../../../app/schemas/models/level_system')
 
 LevelSystemSchema = new mongoose.Schema {
   description: String
diff --git a/server/levels/systems/level_system_handler.coffee b/server/levels/systems/level_system_handler.coffee
index c3fd0a366..bf1bb39d5 100644
--- a/server/levels/systems/level_system_handler.coffee
+++ b/server/levels/systems/level_system_handler.coffee
@@ -13,7 +13,7 @@ LevelSystemHandler = class LevelSystemHandler extends Handler
     'configSchema'
   ]
   postEditableProperties: ['name']
-  jsonSchema: require '../../../app/schemas/level_system_schema'
+  jsonSchema: require '../../../app/schemas/models/level_system'
 
   getEditableProperties: (req, document) ->
     props = super(req, document)
diff --git a/server/levels/thangs/thang_type_handler.coffee b/server/levels/thangs/thang_type_handler.coffee
index 851d2ccf6..abdecd529 100644
--- a/server/levels/thangs/thang_type_handler.coffee
+++ b/server/levels/thangs/thang_type_handler.coffee
@@ -3,7 +3,7 @@ Handler = require('../../commons/Handler')
 
 ThangTypeHandler = class ThangTypeHandler extends Handler
   modelClass: ThangType
-  jsonSchema: require '../../../app/schemas/thang_type_schema'
+  jsonSchema: require '../../../app/schemas/models/thang_type'
   editableProperties: [
     'name',
     'raw',
diff --git a/server/patches/patch_handler.coffee b/server/patches/patch_handler.coffee
index 33b729e22..12a68ed9a 100644
--- a/server/patches/patch_handler.coffee
+++ b/server/patches/patch_handler.coffee
@@ -1,6 +1,6 @@
 Patch = require('./Patch')
 Handler = require('../commons/Handler')
-schema = require '../../app/schemas/patch_schema'
+schema = require '../../app/schemas/models/patch'
 {handlers} = require '../commons/mapping'
 mongoose = require('mongoose')
 
@@ -8,7 +8,7 @@ PatchHandler = class PatchHandler extends Handler
   modelClass: Patch
   editableProperties: []
   postEditableProperties: ['delta', 'target', 'commitMessage']
-  jsonSchema: require '../../app/schemas/patch_schema'
+  jsonSchema: require '../../app/schemas/models/patch'
 
   makeNewInstance: (req) ->
     patch = super(req)
diff --git a/server/routes/db.coffee b/server/routes/db.coffee
index 072b0ea8d..beb120573 100644
--- a/server/routes/db.coffee
+++ b/server/routes/db.coffee
@@ -1,7 +1,6 @@
 log = require 'winston'
 errors = require '../commons/errors'
 handlers = require('../commons/mapping').handlers
-schemas = require('../commons/mapping').schemas
 mongoose = require 'mongoose'
 
 module.exports.setup = (app) ->
@@ -48,7 +47,7 @@ module.exports.setup = (app) ->
 getSchema = (req, res, moduleName) ->
   try
     name = moduleName.replace '.', '_'
-    schema = require('../../app/schemas/' + name + '_schema')
+    schema = require('../../app/schemas/models/' + name)
 
     res.send(JSON.stringify(schema, null, '\t'))
     res.end()
diff --git a/server/routes/file.coffee b/server/routes/file.coffee
index 7a16c3709..f01f635e3 100644
--- a/server/routes/file.coffee
+++ b/server/routes/file.coffee
@@ -19,7 +19,7 @@ fileGet = (req, res) ->
     objectId = mongoose.Types.ObjectId(path)
     query = objectId
   catch e
-    path = path.split('/')    
+    path = path.split('/')
     filename = path[path.length-1]
     path = path[...path.length-1].join('/')
     query =
@@ -34,7 +34,7 @@ fileGet = (req, res) ->
         res.setHeader('Content-Type', 'text/json')
         res.send(results)
         res.end()
-        
+
   else
     Grid.gfs.collection('media').findOne query, (err, filedata) =>
       return errors.notFound(res) if not filedata
@@ -42,7 +42,7 @@ fileGet = (req, res) ->
       if req.headers['if-modified-since'] is filedata.uploadDate
         res.status(304)
         return res.end()
-  
+
       res.setHeader('Content-Type', filedata.contentType)
       res.setHeader('Last-Modified', filedata.uploadDate)
       res.setHeader('Cache-Control', 'public')
@@ -70,7 +70,7 @@ postFileSchema =
   required: ['filename', 'mimetype', 'path']
 
 filePost = (req, res) ->
-  return errors.forbidden(res) unless req.user?.isAdmin()
+  return errors.forbidden(res) unless req.user
   options = req.body
   tv4 = require('tv4').tv4
   valid = tv4.validate(options, postFileSchema)
@@ -83,7 +83,8 @@ filePost = (req, res) ->
 
 saveURL = (req, res) ->
   options = createPostOptions(req)
-  checkExistence options, res, req.body.force, (err) ->
+  force = req.user.isAdmin() and req.body.force
+  checkExistence options, res, force, (err) ->
     return errors.serverError(res) if err
     writestream = Grid.gfs.createWriteStream(options)
     request(req.body.url).pipe(writestream)
@@ -91,7 +92,8 @@ saveURL = (req, res) ->
 
 saveFile = (req, res) ->
   options = createPostOptions(req)
-  checkExistence options, res, req.body.force, (err) ->
+  force = req.user.isAdmin() and req.body.force
+  checkExistence options, res, force, (err) ->
     return if err
     writestream = Grid.gfs.createWriteStream(options)
     f = req.files[req.body.postName]
@@ -101,7 +103,8 @@ saveFile = (req, res) ->
 
 savePNG = (req, res) ->
   options = createPostOptions(req)
-  checkExistence options, res, req.body.force, (err) ->
+  force = req.user.isAdmin() and req.body.force
+  checkExistence options, res, force, (err) ->
     return errors.serverError(res) if err
     writestream = Grid.gfs.createWriteStream(options)
     img = new Buffer(req.body.b64png, 'base64')
@@ -143,11 +146,11 @@ createPostOptions = (req) ->
   unless req.body.name
     name = req.body.filename.split('.')[0]
     req.body.name = _.str.humanize(name)
-  
+
   path = req.body.path or ''
   path = path[1...] if path and path[0] is '/'
   path = path[...path.length-2] if path and path[path.length-1] is '/'
-  
+
   options =
     mode: 'w'
     filename: req.body.filename
@@ -158,6 +161,6 @@ createPostOptions = (req) ->
       name: req.body.name
       path: path
       creator: ''+req.user._id
-  options.metadata.description = req.body.description if req.body.description? 
+  options.metadata.description = req.body.description if req.body.description?
 
   options
diff --git a/server/users/User.coffee b/server/users/User.coffee
index fd9b81969..0d3c42a92 100644
--- a/server/users/User.coffee
+++ b/server/users/User.coffee
@@ -1,5 +1,5 @@
 mongoose = require('mongoose')
-jsonschema = require('../../app/schemas/user_schema')
+jsonschema = require('../../app/schemas/models/user')
 crypto = require('crypto')
 {salt, isProduction} = require('../../server_config')
 mail = require '../commons/mail'
diff --git a/server/users/user_handler.coffee b/server/users/user_handler.coffee
index eb26ff7e5..cbdb44af8 100644
--- a/server/users/user_handler.coffee
+++ b/server/users/user_handler.coffee
@@ -1,4 +1,4 @@
-schema = require '../../app/schemas/user_schema'
+schema = require '../../app/schemas/models/user'
 crypto = require 'crypto'
 request = require 'request'
 User = require './User'
@@ -198,7 +198,10 @@ UserHandler = class UserHandler extends Handler
     @modelClass.findById(id).exec (err, document) =>
       return @sendDatabaseError(res, err) if err
       photoURL = document?.get('photoURL')
-      photoURL ||= @buildGravatarURL document
+      if photoURL
+        photoURL = "/file/#{photoURL}"
+      else
+        photoURL = @buildGravatarURL document, req.query.s, req.query.fallback
       res.redirect photoURL
       res.end()
 
@@ -239,10 +242,11 @@ UserHandler = class UserHandler extends Handler
     obj.jobProfile = _.pick obj.jobProfile, subfields
     obj
 
-  buildGravatarURL: (user) ->
+  buildGravatarURL: (user, size, fallback) ->
     emailHash = @buildEmailHash user
-    defaultAvatar = "http://codecombat.com/file/db/thang.type/52a00d55cf1818f2be00000b/portrait.png"
-    "https://www.gravatar.com/avatar/#{emailHash}?default=#{defaultAvatar}"
+    fallback ?= "http://codecombat.com/file/db/thang.type/52a00d55cf1818f2be00000b/portrait.png"
+    fallback = "http://codecombat.com#{fallback}" unless /^http/.test fallback
+    "https://www.gravatar.com/avatar/#{emailHash}?s=#{size}&default=#{fallback}"
 
   buildEmailHash: (user) ->
     # emailHash is used by gravatar