diff --git a/.codeclimate.yml b/.codeclimate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a0dac5a315e0b15f3ef989c0f1ab7b29cc828516
--- /dev/null
+++ b/.codeclimate.yml
@@ -0,0 +1,24 @@
+version: "2"
+plugins:
+  duplication:
+    enabled: true
+    config:
+      languages:
+        javascript:
+          mass_threshold: 50
+  sass-lint:
+    enabled: true
+    config:
+      config: .sass-lint.yml
+  eslint:
+    enabled: true
+    channel: "eslint-5"
+    config:
+      config: .eslintrc.yml
+exclude_patterns:
+  - "node_modules/**"
+  - "vendor/**"
+  - "db/**"
+  - "config/**"
+  - "docs/**"
+  - "test/**"
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/appstack.js b/app/assets/javascripts/admin/appstack.js
index 23ae425c9b5a48cae95aec35f4bbf21415cd455e..aa96e4785e2122a1d5a8f8f4f5c96192ec2041f6 100644
--- a/app/assets/javascripts/admin/appstack.js
+++ b/app/assets/javascripts/admin/appstack.js
@@ -16,6 +16,7 @@
 //= require_tree ./commons
 //= require_tree ../application/plugins
 //= require_tree ./plugins
+//= require_tree ./utils
 //= require ./communication/init
 
 window.osuny = {};
diff --git a/app/assets/javascripts/admin/communication/init.js b/app/assets/javascripts/admin/communication/init.js
index ab94a3b301ba8ab4a94bf8818c36b6e1025c164a..7d114c0b6b8bc7f6d8ddb0fceef848600696dc56 100644
--- a/app/assets/javascripts/admin/communication/init.js
+++ b/app/assets/javascripts/admin/communication/init.js
@@ -1,5 +1,6 @@
 //= require_self
 //= require ./menu_items
 //= require ./preview
+//= require ./websites
 
 window.osuny.communication = {};
diff --git a/app/assets/javascripts/admin/communication/menu_items.js b/app/assets/javascripts/admin/communication/menu_items.js
index ad81bcaf90aa97b2ef928d3d5af10a0d528e9a78..a4bfdc477aca48a94c296f5aaae215baad7ceff1 100644
--- a/app/assets/javascripts/admin/communication/menu_items.js
+++ b/app/assets/javascripts/admin/communication/menu_items.js
@@ -73,10 +73,7 @@ window.osuny.communication.menuItems = {
 
 window.addEventListener('DOMContentLoaded', function () {
     'use strict';
-    if (document.body.classList.contains('items-new') ||
-            document.body.classList.contains('items-edit') ||
-            document.body.classList.contains('items-create') ||
-            document.body.classList.contains('items-update')) {
+    if (window.osuny.isInControllerForm('items')) {
         window.osuny.communication.menuItems.init();
     }
 });
diff --git a/app/assets/javascripts/admin/communication/websites.js b/app/assets/javascripts/admin/communication/websites.js
new file mode 100644
index 0000000000000000000000000000000000000000..677df2eb65e8c59b5747c7fd81efe6995caf4869
--- /dev/null
+++ b/app/assets/javascripts/admin/communication/websites.js
@@ -0,0 +1,52 @@
+/* global $ */
+window.osuny.communication.websites = {
+    init: function () {
+        'use strict';
+        this.languagesCheckboxes = document.querySelectorAll('.js-languages input[type="checkbox"]');
+        this.defaultLanguageSelect = document.querySelector('.js-default-language');
+        this.defaultLanguageOptions = this.defaultLanguageSelect.querySelectorAll('option');
+        this.initEvents();
+        this.onChangeCheckbox();
+    },
+
+    initEvents: function () {
+        'use strict';
+        var i;
+        for (i = 0 ; i < this.languagesCheckboxes.length ; i += 1) {
+            this.languagesCheckboxes[i].addEventListener('change', this.onChangeCheckbox.bind(this));
+        }
+    },
+
+    onChangeCheckbox: function () {
+        'use strict';
+        var languageCheckbox,
+            languageOption,
+            i;
+
+        // Clean options
+        this.defaultLanguageSelect.innerHTML = "";
+
+        // Re-hydrate options
+        for (i = 0; i < this.defaultLanguageOptions.length; i += 1) {
+            languageOption = this.defaultLanguageOptions[i];
+            languageCheckbox = document.querySelector('.js-languages input[type="checkbox"][value="' + languageOption.value + '"]')
+            if (languageOption.value === "" || languageCheckbox.checked) {
+                this.defaultLanguageSelect.appendChild(languageOption);
+            }
+        }
+    },
+
+    invoke: function () {
+        'use strict';
+        return {
+            init: this.init.bind(this)
+        };
+    }
+}.invoke();
+
+window.addEventListener('DOMContentLoaded', function () {
+    'use strict';
+    if (window.osuny.isInControllerForm('websites')) {
+        window.osuny.communication.websites.init();
+    }
+});
diff --git a/app/assets/javascripts/admin/pure.js b/app/assets/javascripts/admin/pure.js
index 23ae425c9b5a48cae95aec35f4bbf21415cd455e..aa96e4785e2122a1d5a8f8f4f5c96192ec2041f6 100644
--- a/app/assets/javascripts/admin/pure.js
+++ b/app/assets/javascripts/admin/pure.js
@@ -16,6 +16,7 @@
 //= require_tree ./commons
 //= require_tree ../application/plugins
 //= require_tree ./plugins
+//= require_tree ./utils
 //= require ./communication/init
 
 window.osuny = {};
diff --git a/app/assets/javascripts/admin/utils/controller_form.js b/app/assets/javascripts/admin/utils/controller_form.js
new file mode 100644
index 0000000000000000000000000000000000000000..5c74e37111746e2b4e9172b912eb18134e138b4d
--- /dev/null
+++ b/app/assets/javascripts/admin/utils/controller_form.js
@@ -0,0 +1,6 @@
+window.osuny.isInControllerForm = function (controllerName) {
+    return document.body.classList.contains(controllerName + '-new') ||
+        document.body.classList.contains(controllerName + '-edit') ||
+        document.body.classList.contains(controllerName + '-create') ||
+        document.body.classList.contains(controllerName + '-update');
+}
\ No newline at end of file
diff --git a/app/models/communication/website.rb b/app/models/communication/website.rb
index 04cd37eb01ba7fd11c58ab9dcbab5f08279f3e4b..0d0c46680a18bd407b6a449bbd12112bfa741da6 100644
--- a/app/models/communication/website.rb
+++ b/app/models/communication/website.rb
@@ -18,7 +18,7 @@
 #  created_at          :datetime         not null
 #  updated_at          :datetime         not null
 #  about_id            :uuid             indexed => [about_type]
-#  default_language_id :uuid             indexed
+#  default_language_id :uuid             not null, indexed
 #  university_id       :uuid             not null, indexed
 #
 # Indexes
@@ -52,7 +52,7 @@ class Communication::Website < ApplicationRecord
     gitlab: 1
   }
 
-  belongs_to :default_language, class_name: "Language", optional: true
+  belongs_to :default_language, class_name: "Language"
   has_and_belongs_to_many :languages,
                           class_name: 'Language',
                           join_table: 'communication_websites_languages',
diff --git a/app/models/communication/website/configs/default_languages.rb b/app/models/communication/website/configs/default_languages.rb
index d3d27677962f78ee9f65e0a6cbd9ffbaed940df2..dfaf6276250e6a2f8f410f69740b463a589956f2 100644
--- a/app/models/communication/website/configs/default_languages.rb
+++ b/app/models/communication/website/configs/default_languages.rb
@@ -18,7 +18,7 @@
 #  created_at          :datetime         not null
 #  updated_at          :datetime         not null
 #  about_id            :uuid             indexed => [about_type]
-#  default_language_id :uuid             indexed
+#  default_language_id :uuid             not null, indexed
 #  university_id       :uuid             not null, indexed
 #
 # Indexes
diff --git a/app/models/communication/website/configs/default_permalinks.rb b/app/models/communication/website/configs/default_permalinks.rb
index 842de1d49d4f1b7144d7287de4f9e17efc4ed62c..cb70b44bdf719f769d4b7058da32509b5e563790 100644
--- a/app/models/communication/website/configs/default_permalinks.rb
+++ b/app/models/communication/website/configs/default_permalinks.rb
@@ -18,7 +18,7 @@
 #  created_at          :datetime         not null
 #  updated_at          :datetime         not null
 #  about_id            :uuid             indexed => [about_type]
-#  default_language_id :uuid             indexed
+#  default_language_id :uuid             not null, indexed
 #  university_id       :uuid             not null, indexed
 #
 # Indexes
diff --git a/app/models/communication/website/configs/development_config.rb b/app/models/communication/website/configs/development_config.rb
index 3d9d48815c05fc28c0ff74085f4531d1bfb20bfa..f4f672d4507333934399bfb2196d587e7c0aee6a 100644
--- a/app/models/communication/website/configs/development_config.rb
+++ b/app/models/communication/website/configs/development_config.rb
@@ -18,7 +18,7 @@
 #  created_at          :datetime         not null
 #  updated_at          :datetime         not null
 #  about_id            :uuid             indexed => [about_type]
-#  default_language_id :uuid             indexed
+#  default_language_id :uuid             not null, indexed
 #  university_id       :uuid             not null, indexed
 #
 # Indexes
diff --git a/app/models/communication/website/configs/production_config.rb b/app/models/communication/website/configs/production_config.rb
index f16360bd6b1efed75d11cc29e341e1b1e1998a6e..e40eb7abddcc0b4e78202afdaee949e564da4798 100644
--- a/app/models/communication/website/configs/production_config.rb
+++ b/app/models/communication/website/configs/production_config.rb
@@ -18,7 +18,7 @@
 #  created_at          :datetime         not null
 #  updated_at          :datetime         not null
 #  about_id            :uuid             indexed => [about_type]
-#  default_language_id :uuid             indexed
+#  default_language_id :uuid             not null, indexed
 #  university_id       :uuid             not null, indexed
 #
 # Indexes
diff --git a/app/views/admin/communication/websites/_form.html.erb b/app/views/admin/communication/websites/_form.html.erb
index 30a3dcc406b453afbe3d1a9931cd2fb758fd61db..9530351b137b23096920305065a86952aed822fd 100644
--- a/app/views/admin/communication/websites/_form.html.erb
+++ b/app/views/admin/communication/websites/_form.html.erb
@@ -12,8 +12,8 @@
           <%= f.input :name %>
           <%= f.input :url %>
           <%= render 'admin/communication/abouts', f: f, i18n_key: 'activerecord.attributes.communication/website.about_' %>
-          <%= f.association :languages, as: :check_boxes %>
-          <%= f.association :default_language %>
+          <%= f.association :languages, as: :check_boxes, required: true, wrapper_html: { class: "js-languages" } %>
+          <%= f.association :default_language, include_blank: t('simple_form.include_blanks.defaults.language'), input_html: { class: "js-default-language" } %>
           <%= f.input :in_production %>
         </div>
       </div>
diff --git a/config/locales/communication/en.yml b/config/locales/communication/en.yml
index 70427fee49d968c6dccc64995eb0479c3dc0df0c..246b6fbeab2597ce5b56eafcb8119df82f2700bd 100644
--- a/config/locales/communication/en.yml
+++ b/config/locales/communication/en.yml
@@ -701,7 +701,4 @@ en:
         description: If this field is empty, the "lead text" field will be used. If also emty the main text's begining will be used.
         full_width: On large screens, a full width page uses all available space for the content. This is good for landing pages, or to make them spectacular. If the page is not full width, the content column will be smaller to make reading easier. The unused space might be used for a table of contents.
       communication_website_post:
-        description: If this field is empty, the "lead text" field will be used. If also emty the main text's begining will be used.
-  include_blanks:
-    communication_website:
-      default_language: "Select a language"
\ No newline at end of file
+        description: If this field is empty, the "lead text" field will be used. If also emty the main text's begining will be used.
\ No newline at end of file
diff --git a/config/locales/communication/fr.yml b/config/locales/communication/fr.yml
index 1f034044e31a9239d1f0dc5e57a38046e472a29d..2f51d094b17fd5b42f3b564e216a987c12de08e1 100644
--- a/config/locales/communication/fr.yml
+++ b/config/locales/communication/fr.yml
@@ -701,7 +701,4 @@ fr:
         description: Si ce champ est vide le "chapô" sera utilisé. Si il est également vide le début du texte principal sera utilisé.
         full_width: Sur de grands écrans, la page en pleine largeur utilisera tout l'espace disponible, ce qui est pertinent pour événementialiser une page. Si la page n'est pas en pleine largeur, l'espace dédié au contenu sera réduit pour faciliter la lecture, et l'espace libre pourra être utilisé pour une table des matières facilitant la navigation.
       communication_website_post:
-        description: Si ce champ est vide le "chapô" sera utilisé. Si il est également vide le début du texte principal sera utilisé.
-  include_blanks:
-    communication_website:
-      default_language: "Sélectionnez une langue"
\ No newline at end of file
+        description: Si ce champ est vide le "chapô" sera utilisé. Si il est également vide le début du texte principal sera utilisé.
\ No newline at end of file
diff --git a/db/migrate/20221219174414_set_required_default_language_to_communication_websites.rb b/db/migrate/20221219174414_set_required_default_language_to_communication_websites.rb
new file mode 100644
index 0000000000000000000000000000000000000000..16679cb3cd6985986f7e875b8c84b671fdf5176b
--- /dev/null
+++ b/db/migrate/20221219174414_set_required_default_language_to_communication_websites.rb
@@ -0,0 +1,5 @@
+class SetRequiredDefaultLanguageToCommunicationWebsites < ActiveRecord::Migration[7.0]
+  def change
+    change_column_null :communication_websites, :default_language_id, false
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 67d83dd2b8d70a5ab403956b0ba6e31f885faca6..067bb08ac7172ea6e676271f1480c5a3ba6b7dd9 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.0].define(version: 2022_12_19_170849) do
+ActiveRecord::Schema[7.0].define(version: 2022_12_19_174414) do
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
   enable_extension "plpgsql"
@@ -382,7 +382,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_12_19_170849) do
     t.string "plausible_url"
     t.string "git_branch"
     t.boolean "in_production", default: false
-    t.uuid "default_language_id"
+    t.uuid "default_language_id", null: false
     t.index ["about_type", "about_id"], name: "index_communication_websites_on_about"
     t.index ["default_language_id"], name: "index_communication_websites_on_default_language_id"
     t.index ["university_id"], name: "index_communication_websites_on_university_id"
diff --git a/test/fixtures/communication/websites.yml b/test/fixtures/communication/websites.yml
index 4b9fff274b838f934c6d579d822c1250060ca233..d8b3f38cc7e9c0e121ea05a81c1629d1aa08e8ee 100644
--- a/test/fixtures/communication/websites.yml
+++ b/test/fixtures/communication/websites.yml
@@ -18,7 +18,7 @@
 #  created_at          :datetime         not null
 #  updated_at          :datetime         not null
 #  about_id            :uuid             indexed => [about_type]
-#  default_language_id :uuid             indexed
+#  default_language_id :uuid             not null, indexed
 #  university_id       :uuid             not null, indexed
 #
 # Indexes