diff --git a/app/assets/javascripts/application/plugins/summernote.js b/app/assets/javascripts/application/plugins/summernote.js
index 756bc99c539b925a21a5297dba6cb49513604784..97027abf497ff990b0dd33ead9d3328912d8c93e 100644
--- a/app/assets/javascripts/application/plugins/summernote.js
+++ b/app/assets/javascripts/application/plugins/summernote.js
@@ -15,7 +15,7 @@ $(function () {
     configs['mini'] = {
         toolbar: [
             ['font', ['bold', 'italic']],
-            ['position', ['superscript', 'subscript']],
+            ['position', ['superscript']],
             ['insert', ['link', 'unlink']],
             ['view', ['codeview']]
         ],
@@ -26,7 +26,7 @@ $(function () {
     configs['mini-list'] = {
         toolbar: [
             ['font', ['bold', 'italic']],
-            ['position', ['superscript', 'subscript']],
+            ['position', ['superscript']],
             ['para', ['ul', 'ol']],
             ['insert', ['link', 'unlink']],
             ['view', ['codeview']]
diff --git a/app/assets/stylesheets/commons/_forms.sass b/app/assets/stylesheets/commons/_forms.sass
index a61cc00e3f6861e75ff75e2ed7f7daa7bd2ebeba..51c7e93552771765a4dea9ecef6b3b88c6b97d1d 100644
--- a/app/assets/stylesheets/commons/_forms.sass
+++ b/app/assets/stylesheets/commons/_forms.sass
@@ -7,3 +7,13 @@
 
 legend ~ *
     clear: left
+
+input.form-control[type=text],
+input.form-control[type=email],
+input.form-control[type=tel],
+input.form-control[type=password],
+input.form-control[type=url],
+textarea.form-control
+    font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif
+    font-size: 1rem
+    color: black
diff --git a/app/assets/stylesheets/commons/_summernote.sass b/app/assets/stylesheets/commons/_summernote.sass
index d0c877bbb19710f07890ee9980743f38c8b4df46..3c2ee90286a008664a9d1cd6469aeb5fa2ba7a44 100644
--- a/app/assets/stylesheets/commons/_summernote.sass
+++ b/app/assets/stylesheets/commons/_summernote.sass
@@ -1,5 +1,16 @@
 .summernote
     color: black
+    .note-editor
+        .note-editing-area
+            .note-editable
+                min-height: 50px
+                *
+                    font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif
+                &, p, div
+                    font-size: 1rem
+                sup
+                    top: inherit
+                    padding-left: 2px
     b
         color: black
         font-weight: bold
diff --git a/app/controllers/admin/university/organizations_controller.rb b/app/controllers/admin/university/organizations_controller.rb
index bdf31d43785af6cde432ca58abd79ceb77472552..3f56e50328a8d0a8952682f20049316c13b00157 100644
--- a/app/controllers/admin/university/organizations_controller.rb
+++ b/app/controllers/admin/university/organizations_controller.rb
@@ -71,7 +71,7 @@ class Admin::University::OrganizationsController < Admin::University::Applicatio
           .permit(
             :name, :long_name, :slug, :meta_description, :summary, :active, :siren, :kind,
             :address, :zipcode, :city, :country, :text,
-            :url, :phone, :email, :linkedin, :twitter,
+            :url, :phone, :email, :linkedin, :twitter, :mastodon,
             :logo, :logo_delete, :logo_infos,
             :logo_on_dark_background, :logo_on_dark_background_delete, :logo_on_dark_background_infos,
           )
diff --git a/app/controllers/admin/university/people_controller.rb b/app/controllers/admin/university/people_controller.rb
index 68c9d699bde64b82035dcdbe7deae904f9151d1e..0fde20c47221f4f77130ce72b000508af047e904 100644
--- a/app/controllers/admin/university/people_controller.rb
+++ b/app/controllers/admin/university/people_controller.rb
@@ -76,7 +76,7 @@ class Admin::University::PeopleController < Admin::University::ApplicationContro
       :address, :zipcode, :city, :country,
       :meta_description, :summary,
       :biography,  :picture, :picture_delete, :picture_infos,
-      :habilitation, :tenure, :url, :linkedin, :twitter,
+      :habilitation, :tenure, :url, :linkedin, :twitter, :mastodon,
       :is_researcher, :is_teacher, :is_administration, :is_alumnus,
       :user_id
     ).merge(university_id: current_university.id)
diff --git a/app/models/communication/block.rb b/app/models/communication/block.rb
index 4b28873c1a4834582c1efc271a31a59cc3bfbd95..29f0ef5cf08814656a2bb7a7c78b0d15db1566fc 100644
--- a/app/models/communication/block.rb
+++ b/app/models/communication/block.rb
@@ -29,6 +29,7 @@ class Communication::Block < ApplicationRecord
   include Accessible
 
   IMAGE_MAX_SIZE = 5.megabytes
+  FILE_MAX_SIZE = 100.megabytes
 
   belongs_to :about, polymorphic: true
 
diff --git a/app/models/communication/website/page/sitemap.rb b/app/models/communication/website/page/sitemap.rb
index 8848742f2dc200219bc1321f26228de9409b8567..08f797fbe37530ae92e9beae1fb74a5c07ff9a6c 100644
--- a/app/models/communication/website/page/sitemap.rb
+++ b/app/models/communication/website/page/sitemap.rb
@@ -48,5 +48,9 @@ class Communication::Website::Page::Sitemap < Communication::Website::Page
   def draftable?
     false
   end
+  
+  def static_layout
+    'sitemap'
+  end
 
 end
diff --git a/app/models/communication/website/page/with_type.rb b/app/models/communication/website/page/with_type.rb
index 48178c26fd29a2474a5910535e909827d406cb69..e8d5829bf2eb690f8179e92edff97b761a59e16c 100644
--- a/app/models/communication/website/page/with_type.rb
+++ b/app/models/communication/website/page/with_type.rb
@@ -76,6 +76,11 @@ module Communication::Website::Page::WithType
     is_regular_page?
   end
 
+  # Some pages need a specific Hugo layout
+  def static_layout
+    nil
+  end
+
   protected
 
   def default_parent
diff --git a/app/models/communication/website/post.rb b/app/models/communication/website/post.rb
index 1c2838ed8b6169547f007ade72c4c48cdcaedadf..e81056ab8e7f3ef8cb8ed10b115401719048f1db 100644
--- a/app/models/communication/website/post.rb
+++ b/app/models/communication/website/post.rb
@@ -138,7 +138,7 @@ class Communication::Website::Post < ApplicationRecord
     return if website.url.blank?
     return if website.special_page(Communication::Website::Page::CommunicationPost)&.path.blank?
     return if current_permalink_in_website(website).blank?
-    Static.clean_path "#{website.url}#{current_permalink_in_website(website).path}"
+    "#{Static.remove_trailing_slash website.url}#{Static.clean_path current_permalink_in_website(website).path}"
   end
 
   def to_s
diff --git a/app/models/university/organization.rb b/app/models/university/organization.rb
index ea328fbc38b3ad07754db97ff45f8e7104566cf0..46a5f668ec2305ea372fa5f3cfd5c28fd44bb9f2 100644
--- a/app/models/university/organization.rb
+++ b/app/models/university/organization.rb
@@ -11,6 +11,7 @@
 #  kind             :integer          default("company")
 #  linkedin         :string
 #  long_name        :string
+#  mastodon         :string
 #  meta_description :text
 #  name             :string
 #  nic              :string
diff --git a/app/models/university/person.rb b/app/models/university/person.rb
index 4a7dc6a74b110671d05dd4fae4f8a8784f2c0946..9fd05ac1e24f30b4c14a2bb1a485b4f887224905 100644
--- a/app/models/university/person.rb
+++ b/app/models/university/person.rb
@@ -2,38 +2,42 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_doc_identifier    :string
+#  hal_form_identifier   :string
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/models/university/person/administrator.rb b/app/models/university/person/administrator.rb
index 7344064b889d083fb778a272dee969f1392349b0..8532be880cb943b9417e1be51055c9ce2208e583 100644
--- a/app/models/university/person/administrator.rb
+++ b/app/models/university/person/administrator.rb
@@ -2,38 +2,42 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_doc_identifier    :string
+#  hal_form_identifier   :string
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/models/university/person/alumnus.rb b/app/models/university/person/alumnus.rb
index 768ca14261fccbad907c4cdf5bc32d7bb8838768..729d7b2125dbbefebf2fd15ee9f4b37237d4d22e 100644
--- a/app/models/university/person/alumnus.rb
+++ b/app/models/university/person/alumnus.rb
@@ -2,38 +2,42 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_doc_identifier    :string
+#  hal_form_identifier   :string
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/models/university/person/author.rb b/app/models/university/person/author.rb
index 71dbd704e4a2b25eb04d09b54429685e074461d1..3a875d33f05df556031caa3d72147c657390fcc8 100644
--- a/app/models/university/person/author.rb
+++ b/app/models/university/person/author.rb
@@ -2,38 +2,42 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_doc_identifier    :string
+#  hal_form_identifier   :string
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/models/university/person/researcher.rb b/app/models/university/person/researcher.rb
index db8d3308be0db17c636298c3eade541da03c1b16..2a36ac0640951b40e287aa14b93a28e985caffe0 100644
--- a/app/models/university/person/researcher.rb
+++ b/app/models/university/person/researcher.rb
@@ -2,38 +2,42 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_doc_identifier    :string
+#  hal_form_identifier   :string
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/models/university/person/teacher.rb b/app/models/university/person/teacher.rb
index 6dae6e68a4c8563da453dde91e2655dc0a7010d8..aaf4ac554a2374e8abf196c5bde1f22504106540 100644
--- a/app/models/university/person/teacher.rb
+++ b/app/models/university/person/teacher.rb
@@ -2,38 +2,42 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_doc_identifier    :string
+#  hal_form_identifier   :string
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/services/contact_details/base.rb b/app/services/contact_details/base.rb
new file mode 100644
index 0000000000000000000000000000000000000000..15a12c6c6fa5484796a18870c46a114e824e17b3
--- /dev/null
+++ b/app/services/contact_details/base.rb
@@ -0,0 +1,24 @@
+class ContactDetails::Base
+  attr_accessor :value, :label
+
+  def initialize(string)
+    @string = string.to_s
+    return if @string.blank?
+    prepare_value
+    prepare_label
+  end
+
+  def present?
+    value.present?
+  end
+
+  protected
+
+  def prepare_value
+    @value = @string.dup
+  end
+
+  def prepare_label
+    @label = @string.dup
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/country.rb b/app/services/contact_details/country.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0a006beb47a728d5aba977cc9fe223bbda4866b9
--- /dev/null
+++ b/app/services/contact_details/country.rb
@@ -0,0 +1,9 @@
+class ContactDetails::Country < ContactDetails::Base
+
+  protected
+
+  def prepare_label
+    @label = ISO3166::Country[@string].common_name
+  end
+
+end
\ No newline at end of file
diff --git a/app/services/contact_details/email.rb b/app/services/contact_details/email.rb
new file mode 100644
index 0000000000000000000000000000000000000000..24a2158d20c3ec175ab49a3d7042191764bcaa78
--- /dev/null
+++ b/app/services/contact_details/email.rb
@@ -0,0 +1,10 @@
+class ContactDetails::Email < ContactDetails::Base
+  PREFIX = "mailto:"
+
+  protected
+
+  def prepare_value
+    @value = "#{PREFIX}#{@string}"
+  end
+
+end
\ No newline at end of file
diff --git a/app/services/contact_details/linkedin.rb b/app/services/contact_details/linkedin.rb
new file mode 100644
index 0000000000000000000000000000000000000000..bcedeed093aad63ed4856ac095516ba00181f22a
--- /dev/null
+++ b/app/services/contact_details/linkedin.rb
@@ -0,0 +1,11 @@
+class ContactDetails::Linkedin < ContactDetails::Website
+  ROOT = 'www.linkedin.com/in/'
+
+  protected
+
+  def prepare_label
+    super
+    @label.remove! ROOT
+    @label.chomp! '/'
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/mastodon.rb b/app/services/contact_details/mastodon.rb
new file mode 100644
index 0000000000000000000000000000000000000000..51f60f79693bab757ed00bcff6560a41ec307c81
--- /dev/null
+++ b/app/services/contact_details/mastodon.rb
@@ -0,0 +1,2 @@
+class ContactDetails::Mastodon < ContactDetails::Website
+end
\ No newline at end of file
diff --git a/app/services/contact_details/phone.rb b/app/services/contact_details/phone.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f874ccab2203a82c4b85d974e16eba0ee16d1078
--- /dev/null
+++ b/app/services/contact_details/phone.rb
@@ -0,0 +1,16 @@
+class ContactDetails::Phone < ContactDetails::Base
+  PREFIX = "tel:"
+
+  protected
+
+  def prepare_value
+    super
+    @value.remove! ' '
+    @value.remove! '.'
+    @value = "#{PREFIX}#{@value}"
+  end
+
+  def prepare_label
+    @label = @value.remove PREFIX
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/twitter.rb b/app/services/contact_details/twitter.rb
new file mode 100644
index 0000000000000000000000000000000000000000..18d1270a8706dc4e54909a5c716c612248002a81
--- /dev/null
+++ b/app/services/contact_details/twitter.rb
@@ -0,0 +1,19 @@
+class ContactDetails::Twitter < ContactDetails::Base
+  URL = 'https://twitter.com/'
+  DOMAIN = 'twitter.com'
+
+  protected
+
+  def prepare_value
+    super
+    @value.remove! DOMAIN if @value.start_with? DOMAIN
+    @value.remove! URL if @value.start_with? URL
+    @value.delete_suffix! '/'
+    @value.delete_prefix! '/'
+    @value = "#{URL}#{@value}"
+  end
+
+  def prepare_label
+    @label = @value.remove URL
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/website.rb b/app/services/contact_details/website.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ee2f5b5df2bdf46152af2417eca8d7335466e49f
--- /dev/null
+++ b/app/services/contact_details/website.rb
@@ -0,0 +1,14 @@
+class ContactDetails::Website < ContactDetails::Base
+  PROTOCOL = 'https://'
+
+  protected
+
+  def prepare_value
+    super
+    @value = "#{PROTOCOL}#{@value}" unless @value.start_with? PROTOCOL
+  end
+
+  def prepare_label
+    @label = @value.remove PROTOCOL
+  end
+end
\ No newline at end of file
diff --git a/app/views/admin/application/static/_contact_detail.html.erb b/app/views/admin/application/static/_contact_detail.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..f2ceaef2045be22f371523cff8b738b452633b35
--- /dev/null
+++ b/app/views/admin/application/static/_contact_detail.html.erb
@@ -0,0 +1,8 @@
+<%
+detail = kind.new data
+if detail.present?
+%>
+  <%= variable %>:
+    label: "<%= detail.label %>"
+    value: "<%= detail.value %>"
+<% end %>
\ No newline at end of file
diff --git a/app/views/admin/communication/blocks/components/file/_edit.html.erb b/app/views/admin/communication/blocks/components/file/_edit.html.erb
index 52971a54e0e37ff8c0b443462c306c2aafd60907..9b5ddb9c6e59ecba5945637e57f53e7c155106c1 100644
--- a/app/views/admin/communication/blocks/components/file/_edit.html.erb
+++ b/app/views/admin/communication/blocks/components/file/_edit.html.erb
@@ -12,6 +12,7 @@ remove = t 'admin.communication.blocks.components.file.input.remove'
             type="file"
             accept="*"
             @change="onFileImageChange( $event, <%= model %>, '<%= property %>' )"
+            data-size-limit="<%= Communication::Block::FILE_MAX_SIZE %>"
             :id="<%= dom_id.html_safe %>">
   </div>
   <div v-if="<%= model %>.<%= property %>.id">
diff --git a/app/views/admin/communication/blocks/edit.html.erb b/app/views/admin/communication/blocks/edit.html.erb
index ff00edca28c92593efb9487ff188bb22638ef168..f0d54ec57409a5b3804d21b453925d1e4bad8478 100644
--- a/app/views/admin/communication/blocks/edit.html.erb
+++ b/app/views/admin/communication/blocks/edit.html.erb
@@ -68,10 +68,17 @@
         this.uploadFile(event.target, files[0], object, key);
       },
       uploadFile(input, file, object, key) {
-        var size = Math.round(file.size / 1024 / 1024);
-        var controller = new Vue.DirectUploadController(input, file, this.directUpload.url)
-        if (file.size > <%= Communication::Block::IMAGE_MAX_SIZE %>) {
-          alert("<%= t('admin.communication.blocks.alerts.image_is_too_big').html_safe %> (" + size + " Mo > <%= number_to_human_size Communication::Block::IMAGE_MAX_SIZE %>)");
+        var size = Math.round(file.size / 1024 / 1024), 
+            sizeLimit = <%= Communication::Block::IMAGE_MAX_SIZE %>,
+            sizeLimitMo = 0, 
+            controller;
+        if (input.hasAttribute('data-size-limit')) {
+          sizeLimit = input.getAttribute('data-size-limit');
+        }
+        sizeLimitMo = Math.round(sizeLimit / 1024 / 1024);
+        controller = new Vue.DirectUploadController(input, file, this.directUpload.url);
+        if (file.size > sizeLimit) {
+          alert("<%= t('admin.communication.blocks.alerts.file_is_too_big').html_safe %> (" + size + " Mo > " + sizeLimitMo + " Mo)");
           return;
         }
         controller.start(function (blob) {
diff --git a/app/views/admin/communication/blocks/templates/chapter/_edit.html.erb b/app/views/admin/communication/blocks/templates/chapter/_edit.html.erb
index 60946dd47bfe5d558b8225d29c03c2330beb1911..d4110b4ae09a69b65fad2c825fceb7a0c9c7f6cc 100644
--- a/app/views/admin/communication/blocks/templates/chapter/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/chapter/_edit.html.erb
@@ -1,28 +1,21 @@
 <%= block_component_edit :layout %>
 
 <div class="row mb-4">
-  <div class="col-xl-6">
+  <div class="col-xxl-8">
     <%= block_component_edit :text %>
     <%= block_component_edit :notes %>
   </div>
-  <div class="col-xl-6">
+  <div class="col-xxl-4">
     <label class="form-label">
       <%= t "admin.communication.blocks.templates.chapter.edit.image.label" %>
     </label>
-
-    <div class="row">
-      <div class="col-xxl-6">
-        <%= block_component_edit :image %>
-      </div>
-      <div class="col-xxl-6">
-        <%= block_component_edit :alt,
-              label: t('admin.communication.blocks.components.image.alt.label'),
-              placeholder: t('admin.communication.blocks.components.image.alt.placeholder') %>
-        <%= block_component_edit :credit,
-              label: t('admin.communication.blocks.components.image.credit.label'),
-              placeholder: t('admin.communication.blocks.components.image.credit.placeholder'),
-              summernote_config: 'link' %>
-      </div>
-    </div>
+    <%= block_component_edit :image %>
+    <%= block_component_edit :alt,
+          label: t('admin.communication.blocks.components.image.alt.label'),
+          placeholder: t('admin.communication.blocks.components.image.alt.placeholder') %>
+    <%= block_component_edit :credit,
+          label: t('admin.communication.blocks.components.image.credit.label'),
+          placeholder: t('admin.communication.blocks.components.image.credit.placeholder'),
+          summernote_config: 'link' %>
   </div>
 </div>
diff --git a/app/views/admin/communication/unsplash/_selector.html.erb b/app/views/admin/communication/unsplash/_selector.html.erb
index 5974eb5f6e18a9b99953f65fc6f7b954b08641d9..93de143eef4042fe5d188ad450d8f0ddac98c6dd 100644
--- a/app/views/admin/communication/unsplash/_selector.html.erb
+++ b/app/views/admin/communication/unsplash/_selector.html.erb
@@ -194,7 +194,6 @@ path = admin_communication_unsplash_path(website_id: nil, format: :json)
         inputImage.setAttribute('src', image.preview);
         inputImageContainer.parentElement.classList.add('sdfi-deletable-file--with-file');
 
-        inputAlt.value = image.alt;
         $(inputCredit).summernote('code', image.credit);
         this.modal.hide();
       }
diff --git a/app/views/admin/communication/websites/menus/items/show.html.erb b/app/views/admin/communication/websites/menus/items/show.html.erb
index fc9bc13687011e54597764925e40f9d079b629ad..11db1678a5c1fae6f2f9b4dc3f293ce729879ce4 100644
--- a/app/views/admin/communication/websites/menus/items/show.html.erb
+++ b/app/views/admin/communication/websites/menus/items/show.html.erb
@@ -28,7 +28,7 @@
             <p><%= link_to @item.url, @item.url, target: '_blank' unless @item.url.blank? %></p>
           <% elsif @item.has_about? %>
             <h3 class="h5"><%= Communication::Website::Menu::Item.human_attribute_name('about') %></h3>
-            <p><%= link_to_if can?(:read, @item.about), @item.about, [:admin, @item.about] %></p>
+            <p><%= link_to_if can?(:read, @item.about), @item.about, [:admin, @item.about.becomes(@item.about.class.base_class)] %></p>
           <% end %>
         </div>
       </div>
diff --git a/app/views/admin/communication/websites/pages/static.html.erb b/app/views/admin/communication/websites/pages/static.html.erb
index 211f38113bb59e5e27121d35142f36e45a727893..e9297aaa5b6d4a3948eb63d95c6d2fed6e4196d6 100644
--- a/app/views/admin/communication/websites/pages/static.html.erb
+++ b/app/views/admin/communication/websites/pages/static.html.erb
@@ -4,6 +4,9 @@ title: >
 breadcrumb_title: "<%= @about.breadcrumb_title.blank? ? @about.title : @about.breadcrumb_title  %>"
 <%= render 'admin/application/static/permalink' %>
 <%= render 'admin/application/static/design' %>
+<% if @about.static_layout %>
+layout: <%= @about.static_layout %>
+<% end %>
 <% if @about.is_a?(Communication::Website::Page::Person) %>
 has:
   administrators: <%= @website.has_administrators? %>
diff --git a/app/views/admin/education/programs/_form.html.erb b/app/views/admin/education/programs/_form.html.erb
index 6a0272b412347ac7ffa1123250d3a64ae920afb5..298753bae10b132792d21b26a3a2c175a264d8cb 100644
--- a/app/views/admin/education/programs/_form.html.erb
+++ b/app/views/admin/education/programs/_form.html.erb
@@ -36,7 +36,11 @@
       <%= render 'admin/education/programs/forms/part', part: :presentation do %>
         <div class="row">
           <div class="col-xxl-6">
-            <%= f.input :presentation %>
+            <%= f.input :presentation,
+                        as: :summernote,
+                        input_html: {
+                          data: { 'summernote-config' => 'link' }
+                        } %>
           </div>
           <div class="col-xxl-6">
             <%= render 'admin/education/programs/forms/input_with_inheritance', f: f, property: :objectives %>
diff --git a/app/views/admin/university/organizations/_form.html.erb b/app/views/admin/university/organizations/_form.html.erb
index 27ff1003ec04b56fe2d0215378d251c549f4e444..2332c6f6e9fc03c433bec16498fd98071ec85a2f 100644
--- a/app/views/admin/university/organizations/_form.html.erb
+++ b/app/views/admin/university/organizations/_form.html.erb
@@ -38,6 +38,7 @@
               <%= f.input :email %>
               <%= f.input :linkedin %>
               <%= f.input :twitter %>
+              <%= f.input :mastodon %>
             </div>
           </div>
         </div>
diff --git a/app/views/admin/university/organizations/show.html.erb b/app/views/admin/university/organizations/show.html.erb
index 69532f016efea6e4aa51044e46c3c734e7ba3651..3bb0d28adcdaea22ba3b28566c283f7790b0510f 100644
--- a/app/views/admin/university/organizations/show.html.erb
+++ b/app/views/admin/university/organizations/show.html.erb
@@ -21,7 +21,12 @@
       <div class="card-body">
         <div class="row">
           <div class="col-md-6">
-            <% [:address, :zipcode, :city, :country].each do |property| %>
+            <% [
+                  :address, 
+                  :zipcode, 
+                  :city, 
+                  :country
+                ].each do |property| %>
               <% value = @organization.send property %>
               <% next if value.blank? %>
               <h3 class="h5">
@@ -39,7 +44,13 @@
                               @organization.url,
                               target: :_blank %></p>
             <% end %>
-            <% [:phone, :email, :linkedin, :twitter].each do |property| %>
+            <% [
+                  :phone, 
+                  :email, 
+                  :linkedin, 
+                  :twitter, 
+                  :mastodon
+                ].each do |property| %>
               <% value = @organization.send property %>
               <% next if value.blank? %>
               <h3 class="h5">
diff --git a/app/views/admin/university/organizations/static.html.erb b/app/views/admin/university/organizations/static.html.erb
index 21a7b574624a87f1eb48cbef27e8f8e3dc5e1267..50fe16931b7282fc64bd02e40628535ac5ee3b8f 100644
--- a/app/views/admin/university/organizations/static.html.erb
+++ b/app/views/admin/university/organizations/static.html.erb
@@ -27,6 +27,18 @@ kind:
 <% # url is a reserved keyword for Hugo %>
 website: >
   <%= prepare_text_for_static @about.url %>
+contact_details:
+<%= render 'admin/application/static/contact_detail', variable: :address, data: @about.address, kind: ContactDetails::Base %>
+<%= render 'admin/application/static/contact_detail', variable: :zipcode, data: @about.zipcode, kind: ContactDetails::Base %>
+<%= render 'admin/application/static/contact_detail', variable: :city, data: @about.city, kind: ContactDetails::Base %>
+<%= render 'admin/application/static/contact_detail', variable: :country, data: @about.country, kind: ContactDetails::Country %>
+<%= render 'admin/application/static/contact_detail', variable: :address, data: @about.address, kind: ContactDetails::Base %>
+<%= render 'admin/application/static/contact_detail', variable: :website, data: @about.url, kind: ContactDetails::Website %>
+<%= render 'admin/application/static/contact_detail', variable: :linkedin, data: @about.linkedin, kind: ContactDetails::Linkedin %>
+<%= render 'admin/application/static/contact_detail', variable: :twitter, data: @about.twitter, kind: ContactDetails::Twitter %>
+<%= render 'admin/application/static/contact_detail', variable: :mastodon, data: @about.mastodon, kind: ContactDetails::Mastodon %>
+<%= render 'admin/application/static/contact_detail', variable: :phone, data: @about.phone, kind: ContactDetails::Phone %>
+<%= render 'admin/application/static/contact_detail', variable: :email, data: @about.email, kind: ContactDetails::Email %>
 <% if @about.logo.attached? %>
 logo: "<%= @about.logo.blob.id %>"
 <% end %>
diff --git a/app/views/admin/university/people/_form.html.erb b/app/views/admin/university/people/_form.html.erb
index eb779753b07d82c90ced9616a05f1db067272520..1c96a3da2c6984d3350ab5ddfe775ee13e767e53 100644
--- a/app/views/admin/university/people/_form.html.erb
+++ b/app/views/admin/university/people/_form.html.erb
@@ -91,6 +91,7 @@
             </div>
             <div class="col-md-6">
               <%= f.input :twitter %>
+              <%= f.input :mastodon %>
             </div>
           </div>
         </div>
diff --git a/app/views/admin/university/people/_main_infos.html.erb b/app/views/admin/university/people/_main_infos.html.erb
index c5ba7226d311eb98ae327b8a8e8f5f89636fafe1..6ab39d44f189aae92cb461f60af9e395563f513f 100644
--- a/app/views/admin/university/people/_main_infos.html.erb
+++ b/app/views/admin/university/people/_main_infos.html.erb
@@ -54,7 +54,11 @@
           <% end %>
           <% unless person.twitter.blank? %>
             <h3 class="h5"><%= University::Person.human_attribute_name('twitter') %></h3>
-            <%= link_to person.twitter, "https://twitter.com/#{person.twitter}", target: '_blank' %>
+            <p><%= link_to person.twitter, "https://twitter.com/#{person.twitter}", target: '_blank' %></p>
+          <% end %>
+          <% unless person.mastodon.blank? %>
+            <h3 class="h5"><%= University::Person.human_attribute_name('mastodon') %></h3>
+            <p><%= link_to person.mastodon, person.mastodon, target: '_blank' %></p>
           <% end %>
         </div>
       </div>
diff --git a/app/views/admin/university/people/static.html.erb b/app/views/admin/university/people/static.html.erb
index 8e58f1a9edf61c3f56e0f18287ce10aa73d4278c..5c3cb9a62b35b7277bcaae1a9817a1384050b6f0 100644
--- a/app/views/admin/university/people/static.html.erb
+++ b/app/views/admin/university/people/static.html.erb
@@ -19,6 +19,17 @@ linkedin: >-
   <%= @about.linkedin %>
 website: >-
   <%= @about.url %>
+contact_details:
+<%= render 'admin/application/static/contact_detail', variable: :address, data: @about.address, kind: ContactDetails::Base %>
+<%= render 'admin/application/static/contact_detail', variable: :zipcode, data: @about.zipcode, kind: ContactDetails::Base %>
+<%= render 'admin/application/static/contact_detail', variable: :city, data: @about.city, kind: ContactDetails::Base %>
+<%= render 'admin/application/static/contact_detail', variable: :country, data: @about.country, kind: ContactDetails::Country %>
+<%= render 'admin/application/static/contact_detail', variable: :website, data: @about.url, kind: ContactDetails::Website %>
+<%= render 'admin/application/static/contact_detail', variable: :linkedin, data: @about.linkedin, kind: ContactDetails::Linkedin %>
+<%= render 'admin/application/static/contact_detail', variable: :twitter, data: @about.twitter, kind: ContactDetails::Twitter %>
+<%= render 'admin/application/static/contact_detail', variable: :mastodon, data: @about.mastodon, kind: ContactDetails::Mastodon %>
+<%= render 'admin/application/static/contact_detail', variable: :phone, data: @about.phone_mobile, kind: ContactDetails::Phone %>
+<%= render 'admin/application/static/contact_detail', variable: :email, data: @about.email, kind: ContactDetails::Email %>
 <% if @about.best_picture.attached? %>
 image: "<%= @about.best_picture.blob.id %>"
 <% end %>
diff --git a/config/locales/communication/en.yml b/config/locales/communication/en.yml
index 25fe01c37e8266330e52a26ad7325dc23df7ed22..31032486bb73e8546e078cb80d062c31ad30e50a 100644
--- a/config/locales/communication/en.yml
+++ b/config/locales/communication/en.yml
@@ -151,7 +151,7 @@ en:
     communication:
       blocks:
         alerts:
-          image_is_too_big: Image is too big!
+          file_is_too_big: File is too big!
         categories:
           basic:
             label: Basic blocks
@@ -424,17 +424,17 @@ en:
           partners:
             description: A list of organizations with logo, name and website.
             edit:
-              add_partner: Add partner
+              add_partner: Add organization
               alphabetical:
                 label: Alphabetical order
               description:
                 label: Description
               element:
                 id:
-                  label: Partner
+                  label: Organization
                   name:
                     label: Nom
-                    placeholder: Enter partner's name
+                    placeholder: Enter organization's name
                     url:
                       label: Website
                       logo_label: Logo
@@ -442,7 +442,7 @@ en:
                       remove_logo: Remove logo
                   placeholder: Choose organization
                   unregistered: Unregistered organization
-              remove_partner: Remove partner
+              remove_partner: Remove organization
               with_link:
                 label: With clickable link to each organization's page?
           posts:
@@ -634,9 +634,9 @@ en:
           gallery: Gallery
           image: Image
           key_figures: Key figures
-          organization_chart: Organization chart
+          organization_chart: People
           pages: Pages
-          partners: Partners
+          partners: Organizations
           posts: Posts
           programs: Programs
           testimonials: Testimonials
diff --git a/config/locales/communication/fr.yml b/config/locales/communication/fr.yml
index fb1cf9db0a94cb396d7400ba0a495ab50dc53e3c..9592afc31c250fe29f67bcfd5e06064492826d5c 100644
--- a/config/locales/communication/fr.yml
+++ b/config/locales/communication/fr.yml
@@ -151,7 +151,7 @@ fr:
     communication:
       blocks:
         alerts:
-          image_is_too_big: L'image est trop grosse !
+          file_is_too_big: Le fichier est trop lourd !
         categories:
           basic:
             label: Blocs de base
diff --git a/config/locales/education/en.yml b/config/locales/education/en.yml
index a55b2560703b58df704aec88c1ba9742e55bb2ad..ac13e8f926e31c23b40f80bfe0601a29cd7de7e2 100644
--- a/config/locales/education/en.yml
+++ b/config/locales/education/en.yml
@@ -55,7 +55,7 @@ en:
         other: Other
         pedagogy: Méthodes mobilisées
         prerequisites: Prérequis
-        presentation: Presentation
+        presentation: In brief
         pricing: Tarifs
         published: Published?
         registration: Modalités et délais d’accès
diff --git a/config/locales/education/fr.yml b/config/locales/education/fr.yml
index afe79e85b5e83c198395300c34a49d1376da0d7a..77e0483a0c33e463c9d4c6c6a129fee08f808753 100644
--- a/config/locales/education/fr.yml
+++ b/config/locales/education/fr.yml
@@ -55,7 +55,7 @@ fr:
         other: Autre
         pedagogy: Méthodes mobilisées
         prerequisites: Prérequis
-        presentation: Présentation
+        presentation: En bref
         pricing: Tarifs
         published: Publiée ?
         registration: Modalités et délais d’accès
diff --git a/db/migrate/20230118155630_add_mastodon_to_persons_and_organizations.rb b/db/migrate/20230118155630_add_mastodon_to_persons_and_organizations.rb
new file mode 100644
index 0000000000000000000000000000000000000000..200bf80657ce3370ea3add0ba89bae0fa8bcd4dd
--- /dev/null
+++ b/db/migrate/20230118155630_add_mastodon_to_persons_and_organizations.rb
@@ -0,0 +1,6 @@
+class AddMastodonToPersonsAndOrganizations < ActiveRecord::Migration[7.0]
+  def change
+    add_column :university_people, :mastodon, :string
+    add_column :university_organizations, :mastodon, :string
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 042e3b820bbf50485f0917f9fb22c68a9f5e1463..317c9d831a3e1be7975386c68e4ad29d4038bd0d 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: 2023_01_12_151136) do
+ActiveRecord::Schema[7.0].define(version: 2023_01_18_155630) do
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
   enable_extension "plpgsql"
@@ -639,6 +639,13 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_12_151136) do
     t.index ["university_id"], name: "index_research_laboratories_on_university_id"
   end
 
+  create_table "research_laboratories_publications", id: false, force: :cascade do |t|
+    t.uuid "research_publication_id", null: false
+    t.uuid "research_laboratory_id", null: false
+    t.index ["research_laboratory_id", "research_publication_id"], name: "index_laboratory_publication"
+    t.index ["research_publication_id", "research_laboratory_id"], name: "index_publication_laboratory"
+  end
+
   create_table "research_laboratory_axes", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "research_laboratory_id", null: false
@@ -653,6 +660,27 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_12_151136) do
     t.index ["university_id"], name: "index_research_laboratory_axes_on_university_id"
   end
 
+  create_table "research_publications", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.string "docid"
+    t.jsonb "data"
+    t.string "title"
+    t.string "url"
+    t.string "ref"
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.string "hal_url"
+    t.date "publication_date"
+    t.string "doi"
+    t.string "slug"
+  end
+
+  create_table "research_publications_university_people", id: false, force: :cascade do |t|
+    t.uuid "research_publication_id", null: false
+    t.uuid "university_person_id", null: false
+    t.index ["research_publication_id", "university_person_id"], name: "index_publication_person"
+    t.index ["university_person_id", "research_publication_id"], name: "index_person_publication"
+  end
+
   create_table "research_theses", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "research_laboratory_id", null: false
@@ -719,6 +747,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_12_151136) do
     t.text "summary"
     t.string "twitter"
     t.string "linkedin"
+    t.string "mastodon"
     t.index ["university_id"], name: "index_university_organizations_on_university_id"
   end
 
@@ -754,6 +783,10 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_12_151136) do
     t.string "zipcode"
     t.string "city"
     t.string "country"
+    t.string "hal_person_identifier"
+    t.string "hal_doc_identifier"
+    t.string "hal_form_identifier"
+    t.string "mastodon"
     t.index ["university_id"], name: "index_university_people_on_university_id"
     t.index ["user_id"], name: "index_university_people_on_user_id"
   end
diff --git a/test/fixtures/university/organizations.yml b/test/fixtures/university/organizations.yml
index 5f6726cfb064620894dc13138a86a4c7e80eb96b..08514e6ab2b50be732b4a828a535e525f17036fc 100644
--- a/test/fixtures/university/organizations.yml
+++ b/test/fixtures/university/organizations.yml
@@ -11,6 +11,7 @@
 #  kind             :integer          default("company")
 #  linkedin         :string
 #  long_name        :string
+#  mastodon         :string
 #  meta_description :text
 #  name             :string
 #  nic              :string
diff --git a/test/models/university/organization_test.rb b/test/models/university/organization_test.rb
index 051333211e94bc132746bef850713dab3111021b..56f0523c14d85df0edb489caebaad3ebb0d13d0a 100644
--- a/test/models/university/organization_test.rb
+++ b/test/models/university/organization_test.rb
@@ -11,6 +11,7 @@
 #  kind             :integer          default("company")
 #  linkedin         :string
 #  long_name        :string
+#  mastodon         :string
 #  meta_description :text
 #  name             :string
 #  nic              :string
diff --git a/test/services/contact_details_test.rb b/test/services/contact_details_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b08bab06f711b5ce4930028d67485e453aed33eb
--- /dev/null
+++ b/test/services/contact_details_test.rb
@@ -0,0 +1,89 @@
+require "test_helper"
+
+class ContactDetailsTest < ActiveSupport::TestCase
+
+  test "country nil" do
+    detail = ContactDetails::Country.new nil
+    assert_nil detail.label
+    assert_nil detail.value
+  end
+
+  test "country FR" do
+    detail = ContactDetails::Country.new 'FR'
+    assert_equal 'France', detail.label
+    assert_equal 'FR', detail.value
+  end
+
+  test "email nil" do
+    detail = ContactDetails::Email.new nil
+    assert_nil detail.label
+    assert_nil detail.value
+  end
+
+  test "email arnaud.levy@noesya.coop" do
+    detail = ContactDetails::Email.new 'arnaud.levy@noesya.coop'
+    assert_equal 'arnaud.levy@noesya.coop', detail.label
+    assert_equal 'mailto:arnaud.levy@noesya.coop', detail.value
+  end
+
+  test "twitter nil" do
+    detail = ContactDetails::Twitter.new nil
+    assert_nil detail.label
+    assert_nil detail.value
+  end
+
+  test "twitter handle" do
+    detail = ContactDetails::Twitter.new 'arnaudlevy'
+    assert_equal 'arnaudlevy', detail.label
+    assert_equal 'https://twitter.com/arnaudlevy', detail.value
+  end
+
+  test "mastodon nil" do
+    detail = ContactDetails::Mastodon.new nil
+    assert_nil detail.label
+    assert_nil detail.value
+  end
+
+  test "mastodon mastodon.social/@arnaudlevy" do
+    detail = ContactDetails::Mastodon.new 'mastodon.social/@arnaudlevy'
+    assert_equal 'mastodon.social/@arnaudlevy', detail.label
+    assert_equal 'https://mastodon.social/@arnaudlevy', detail.value
+  end
+
+  test "mastodon https://mastodon.social/@arnaudlevy" do
+    detail = ContactDetails::Mastodon.new 'https://mastodon.social/@arnaudlevy'
+    assert_equal 'mastodon.social/@arnaudlevy', detail.label
+    assert_equal 'https://mastodon.social/@arnaudlevy', detail.value
+  end
+
+  test "twitter twitter.com/arnaudlevy" do
+    detail = ContactDetails::Twitter.new 'twitter.com/arnaudlevy'
+    assert_equal 'arnaudlevy', detail.label
+    assert_equal 'https://twitter.com/arnaudlevy', detail.value
+  end
+
+  test "twitter https://twitter.com/arnaudlevy" do
+    detail = ContactDetails::Twitter.new 'https://twitter.com/arnaudlevy'
+    assert_equal 'arnaudlevy', detail.label
+    assert_equal 'https://twitter.com/arnaudlevy', detail.value
+  end
+
+  test "website nil" do
+    detail = ContactDetails::Website.new nil
+    assert_nil detail.label
+    assert_nil detail.value
+  end
+
+  test "website www.noesya.coop" do
+    detail = ContactDetails::Website.new 'www.noesya.coop'
+    assert_equal 'www.noesya.coop', detail.label
+    assert_equal 'https://www.noesya.coop', detail.value
+  end
+
+  test "website https://www.noesya.coop" do
+    detail = ContactDetails::Website.new 'https://www.noesya.coop'
+    assert_equal 'www.noesya.coop', detail.label
+    assert_equal 'https://www.noesya.coop', detail.value
+  end
+
+end
\ No newline at end of file