diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index a8bbb15b5771ead860d763f6a912a815f15719c5..7df30acd873166e5327fb3cb4b70450df2434b3f 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -11,46 +11,9 @@ module ApplicationHelper
     classes
   end
 
-  def social_website_to_url(string)
-    string = "https://#{string}" unless string.start_with?('http')
-    string.gsub('http://', 'https://')
-  end
-
-  def social_website_to_s(string)
-    string.gsub('http://', '')
-          .gsub('https://', '')
-          .delete_suffix('/')
-  end
-
-  def social_linkedin_to_url(string)
-    string.gsub('http://', 'https://')
-  end
-
-  def social_linkedin_to_s(string)
-    string.gsub('http://', 'https://')
-          .delete_prefix('https://www.linkedin.com/in/')
-          .delete_suffix('/')
-  end
-
-  def social_twitter_to_url(string)
-    string = "https://twitter.com/#{string}" unless 'twitter.com'.in? string
-    string = "https://#{string}" unless string.start_with?('http')
-    string.gsub('http://', 'https://')
-  end
-
-  def social_twitter_to_s(string)
-    string.gsub('http://', 'https://')
-          .gsub('https://www.twitter.com/', 'https://twitter.com/')
-          .gsub('https://twitter.com/', '')
-  end
-
-  def social_mastodon_to_url(string)
-    string.gsub('http://', 'https://')
-  end
-
-  def social_mastodon_to_s(string)
-    string.gsub('http://', 'https://')
-          .remove('https://')
+  def contact_link(string, kind)
+    service = ContactDetails.for(kind, string)
+    link_to service.label, service.value, target: '_blank', rel: 'noreferrer'
   end
 
   def masked_email(string)
diff --git a/app/services/contact_details.rb b/app/services/contact_details.rb
new file mode 100644
index 0000000000000000000000000000000000000000..06a84507ad2aab6db5c08c508902aad0a8ee5fc3
--- /dev/null
+++ b/app/services/contact_details.rb
@@ -0,0 +1,9 @@
+class ContactDetails
+  def self.with_kind(kind)
+    "ContactDetails::#{kind.to_s.camelize}".constantize
+  end
+
+  def self.for(kind, string)
+    with_kind(kind).new(string)
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/country.rb b/app/services/contact_details/country.rb
index 0a006beb47a728d5aba977cc9fe223bbda4866b9..ce36f29c62fbd5cb645f525791efc5b781432a85 100644
--- a/app/services/contact_details/country.rb
+++ b/app/services/contact_details/country.rb
@@ -3,7 +3,19 @@ class ContactDetails::Country < ContactDetails::Base
   protected
 
   def prepare_label
-    @label = ISO3166::Country[@string].common_name
+    @label = country&.common_name || @string.to_s.titleize
+  end
+
+  def prepare_value
+    @value = country&.alpha2 || @string.to_s[0..1].upcase
+  end
+
+  def country
+    if @string.in? ISO3166::Country.codes
+      ISO3166::Country[@string]
+    else
+      ISO3166::Country.find_country_by_any_name @string
+    end
   end
 
 end
\ No newline at end of file
diff --git a/app/services/contact_details/facebook.rb b/app/services/contact_details/facebook.rb
new file mode 100644
index 0000000000000000000000000000000000000000..83eb9d33d7bcc52c93c3f98ba5f931f0b0d4ed0f
--- /dev/null
+++ b/app/services/contact_details/facebook.rb
@@ -0,0 +1,17 @@
+class ContactDetails::Facebook < ContactDetails::SocialNetwork
+
+  protected
+
+  def url
+    'https://www.facebook.com/'
+  end
+
+  def handle
+    @handle ||=  @string.remove('https://')
+                        .remove('http://')
+                        .remove('www.')
+                        .remove('facebook.com')
+                        .remove('@')
+                        .remove('/')
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/github.rb b/app/services/contact_details/github.rb
new file mode 100644
index 0000000000000000000000000000000000000000..aab84716099ce13befb74936a1a606e67ba4ec3a
--- /dev/null
+++ b/app/services/contact_details/github.rb
@@ -0,0 +1,17 @@
+class ContactDetails::Github < ContactDetails::SocialNetwork
+
+  protected
+
+  def url
+    'https://github.com/'
+  end
+
+  def handle
+    @handle ||=  @string.remove('https://')
+                        .remove('http://')
+                        .remove('www.')
+                        .remove('github.com')
+                        .remove('@')
+                        .remove('/')
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/instagram.rb b/app/services/contact_details/instagram.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dbb67f7532d480a380be2fb8f3819258b12f9e7d
--- /dev/null
+++ b/app/services/contact_details/instagram.rb
@@ -0,0 +1,17 @@
+class ContactDetails::Instagram < ContactDetails::SocialNetwork
+
+  protected
+
+  def url
+    'https://instagram.com/'
+  end
+
+  def handle
+    @handle ||=  @string.remove('https://')
+                        .remove('http://')
+                        .remove('www.')
+                        .remove('instagram.com')
+                        .remove('@')
+                        .remove('/')
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/linkedin.rb b/app/services/contact_details/linkedin.rb
index bcedeed093aad63ed4856ac095516ba00181f22a..5aa7142b010ddc25ae56837e1a20ff391efa2d95 100644
--- a/app/services/contact_details/linkedin.rb
+++ b/app/services/contact_details/linkedin.rb
@@ -1,11 +1,18 @@
-class ContactDetails::Linkedin < ContactDetails::Website
-  ROOT = 'www.linkedin.com/in/'
+class ContactDetails::Linkedin < ContactDetails::Base
 
   protected
 
+  def prepare_value
+    @value = @string
+  end
+
   def prepare_label
-    super
-    @label.remove! ROOT
-    @label.chomp! '/'
+    @label = @string.remove('https://')
+                    .remove('http://')
+                    .remove('www.')
+                    .remove('linkedin.com/in/')
+                    .remove('linkedin.com/company/')
+                    .remove('@')
+                    .remove('/')
   end
 end
\ No newline at end of file
diff --git a/app/services/contact_details/peertube.rb b/app/services/contact_details/peertube.rb
new file mode 100644
index 0000000000000000000000000000000000000000..338f30d2a6e66ed15cac11cd051d94bf20761c2c
--- /dev/null
+++ b/app/services/contact_details/peertube.rb
@@ -0,0 +1,2 @@
+class ContactDetails::Peertube < 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
index f874ccab2203a82c4b85d974e16eba0ee16d1078..2ee0781ff89e58c555ed2f54be20188f8f77f6f1 100644
--- a/app/services/contact_details/phone.rb
+++ b/app/services/contact_details/phone.rb
@@ -1,5 +1,4 @@
 class ContactDetails::Phone < ContactDetails::Base
-  PREFIX = "tel:"
 
   protected
 
@@ -7,10 +6,11 @@ class ContactDetails::Phone < ContactDetails::Base
     super
     @value.remove! ' '
     @value.remove! '.'
-    @value = "#{PREFIX}#{@value}"
+    @value = "tel:#{@value}"
   end
 
   def prepare_label
-    @label = @value.remove PREFIX
+    super
+    @label.gsub! '.', ' '
   end
 end
\ No newline at end of file
diff --git a/app/services/contact_details/social_network.rb b/app/services/contact_details/social_network.rb
new file mode 100644
index 0000000000000000000000000000000000000000..66ea67078386eff5453ea307a0e605891d09b83a
--- /dev/null
+++ b/app/services/contact_details/social_network.rb
@@ -0,0 +1,20 @@
+class ContactDetails::SocialNetwork < ContactDetails::Base
+
+  protected
+
+  def url
+    ''
+  end
+
+  def prepare_value
+    @value = "#{url}#{handle}"
+  end
+
+  def prepare_label
+    @label = handle
+  end
+
+  def handle
+    @string
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/tiktok.rb b/app/services/contact_details/tiktok.rb
new file mode 100644
index 0000000000000000000000000000000000000000..82d9b920f88eb4c889e39c6c39b2423082139230
--- /dev/null
+++ b/app/services/contact_details/tiktok.rb
@@ -0,0 +1,17 @@
+class ContactDetails::Tiktok < ContactDetails::SocialNetwork
+
+  protected
+
+  def url
+    'https://www.tiktok.com/@'
+  end
+
+  def handle
+    @handle ||=  @string.remove('https://')
+                        .remove('http://')
+                        .remove('www.')
+                        .remove('tiktok.com')
+                        .remove('@')
+                        .remove('/')
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/twitter.rb b/app/services/contact_details/twitter.rb
index 18d1270a8706dc4e54909a5c716c612248002a81..9b2ca7e1beb39573434418b9c683076027787cbe 100644
--- a/app/services/contact_details/twitter.rb
+++ b/app/services/contact_details/twitter.rb
@@ -1,19 +1,18 @@
-class ContactDetails::Twitter < ContactDetails::Base
-  URL = 'https://twitter.com/'
-  DOMAIN = 'twitter.com'
+class ContactDetails::Twitter < ContactDetails::SocialNetwork
 
   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}"
+  def url
+    'https://x.com/'
   end
 
-  def prepare_label
-    @label = @value.remove URL
+  def handle
+    @handle ||=  @string.remove('https://')
+                        .remove('http://')
+                        .remove('www.')
+                        .remove('x.com')
+                        .remove('twitter.com')
+                        .remove('@')
+                        .remove('/')
   end
 end
\ No newline at end of file
diff --git a/app/services/contact_details/vimeo.rb b/app/services/contact_details/vimeo.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b69fb2bfccc6a737d3a7218ba793b99255846647
--- /dev/null
+++ b/app/services/contact_details/vimeo.rb
@@ -0,0 +1,17 @@
+class ContactDetails::Vimeo < ContactDetails::SocialNetwork
+
+  protected
+
+  def url
+    'https://vimeo.com/'
+  end
+
+  def handle
+    @handle ||=  @string.remove('https://')
+                        .remove('http://')
+                        .remove('www.')
+                        .remove('vimeo.com')
+                        .remove('@')
+                        .remove('/')
+  end
+end
\ No newline at end of file
diff --git a/app/services/contact_details/x.rb b/app/services/contact_details/x.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e2e5b7a725f3577559e7a19652229a87006aa6cb
--- /dev/null
+++ b/app/services/contact_details/x.rb
@@ -0,0 +1,3 @@
+class ContactDetails::X < ContactDetails::Twitter
+
+end
\ No newline at end of file
diff --git a/app/services/contact_details/youtube.rb b/app/services/contact_details/youtube.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2c83ebc2d184d268399c793ebc3084422925f80d
--- /dev/null
+++ b/app/services/contact_details/youtube.rb
@@ -0,0 +1,18 @@
+class ContactDetails::Youtube < ContactDetails::SocialNetwork
+
+  protected
+
+  def url
+    'https://www.youtube.com/@'
+  end
+
+  def handle
+    @handle ||=  @string.remove('https://')
+                        .remove('http://')
+                        .remove('www.')
+                        .remove('youtube.com')
+                        .remove('youtu.be')
+                        .remove('@')
+                        .remove('/')
+  end
+end
\ No newline at end of file
diff --git a/app/views/admin/communication/blocks/edit.html.erb b/app/views/admin/communication/blocks/edit.html.erb
index 485ae64269fdfaedb41b05b6abea7a46e52c3e06..1625c11a32fd389af815ad47d396ba4820f44519 100644
--- a/app/views/admin/communication/blocks/edit.html.erb
+++ b/app/views/admin/communication/blocks/edit.html.erb
@@ -3,6 +3,7 @@
   <%= t "enums.communication.block.template_kind.#{@block.template_kind}" %>
 <% end %>
 <div  id="app"
+      class="pb-5"
       v-cloak
       data-languagetool-locale="<%= I18n.locale %>"
       data-languagetool-email="<%= ENV['LANGUAGE_TOOL_USERNAME'] %>"
diff --git a/app/views/admin/communication/blocks/templates/contact/_show.html.erb b/app/views/admin/communication/blocks/templates/contact/_show.html.erb
index 515f2b36d4c9e144b9249e1e046b0eab8c914f80..aa8c93a0c1f207bae92bc02d2ad14f8da879ddde 100644
--- a/app/views/admin/communication/blocks/templates/contact/_show.html.erb
+++ b/app/views/admin/communication/blocks/templates/contact/_show.html.erb
@@ -41,10 +41,7 @@
                   <p><a itemprop="email" href="mailto:<%= email %>%>"><%= email %></a></p>
                 <% end %>
                 <% if block.template.url.present? %>
-                  <% url = block.template.url %>
-                  <a href="<%= social_website_to_url url %>" target="_blank" rel="noreferrer">
-                    <%= social_website_to_s url %>
-                  </a>
+                  <%= contact_link block.template.url, :website %>
                 <% end %>
               </div>
             <% end %>
diff --git a/app/views/admin/communication/blocks/templates/contact/_static.html.erb b/app/views/admin/communication/blocks/templates/contact/_static.html.erb
index 2c804e09145de742df4011da95860d041b8cdf69..2a0d90a913443b373d59dd13926d1f9eeba13f6d 100644
--- a/app/views/admin/communication/blocks/templates/contact/_static.html.erb
+++ b/app/views/admin/communication/blocks/templates/contact/_static.html.erb
@@ -6,6 +6,143 @@
 <%= block_component_static block, :zipcode, depth: 4 %>
 <%= block_component_static block, :city, depth: 4 %>
 <%= block_component_static block, :country, depth: 4 %>
+      contact_details:
+<%
+if block.template.url.present?
+  detail = ContactDetails::Website.new block.template.url
+  %>
+        url:
+          label: >-
+            <%= detail.label %>
+          value: >-
+            <%= detail.value %>
+<% end %>
+<% if block.template.phone_numbers.any? %>
+        phone_numbers:
+<% 
+block.template.phone_numbers.each do |phone|
+  detail = ContactDetails::Phone.new phone
+  %>
+          - label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% end %>
+<% if block.template.emails.any? %>
+        emails:
+<% 
+block.template.emails.each do |email|
+  detail = ContactDetails::Email.new email
+  %>
+          - label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% end %>
+        social_networks:
+<% 
+if block.template.social_facebook.present?
+  detail = ContactDetails::Facebook.new block.template.social_facebook
+  %>
+          facebook:
+            label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% 
+if block.template.social_github.present?
+  detail = ContactDetails::Github.new block.template.social_github
+  %>
+          github:
+            label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% 
+if block.template.social_instagram.present?
+  detail = ContactDetails::Instagram.new block.template.social_instagram
+  %>
+          instagram:
+            label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% 
+if block.template.social_linkedin.present?
+  detail = ContactDetails::Linkedin.new block.template.social_linkedin
+  %>
+          linkedin:
+            label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% 
+if block.template.social_mastodon.present?
+  detail = ContactDetails::Mastodon.new block.template.social_mastodon
+  %>
+          mastodon:
+            label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% 
+if block.template.social_peertube.present?
+  detail = ContactDetails::Peertube.new block.template.social_peertube
+  %>
+          peertube:
+            label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% 
+if block.template.social_tiktok.present?
+  detail = ContactDetails::Tiktok.new block.template.social_tiktok
+  %>
+          tiktok:
+            label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% 
+if block.template.social_vimeo.present?
+  detail = ContactDetails::Vimeo.new block.template.social_vimeo
+  %>
+          vimeo:
+            label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% 
+if block.template.social_x.present?
+  detail = ContactDetails::X.new block.template.social_x
+  %>
+          x:
+            label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% 
+if block.template.social_youtube.present?
+  detail = ContactDetails::Youtube.new block.template.social_youtube
+  %>
+          youtube:
+            label: >-
+              <%= detail.label %>
+            value: >-
+              <%= detail.value %>
+<% end %>
+<% # deprecated %>
 <%= block_component_static block, :phone_numbers %>
 <%= block_component_static block, :url %>
 <%= block_component_static block, :emails %>
@@ -29,6 +166,7 @@
         <%= network.to_s.remove('social_') %>: >-
           <%= prepare_text_for_static value %>
 <% end %>
+<% #/ deprecated %>
       timetable:
 <% block.template.elements.each do |element| %>
 <%= block_component_static block, :title, template: element, list: true, depth: 4 %>
diff --git a/app/views/admin/education/schools/static.html.erb b/app/views/admin/education/schools/static.html.erb
index 3e3c242534af25d35f4e40eb2c2bbaafc12d0336..dabd2a4689f2e4c97330a8bd8a5e9c904e5cc239 100644
--- a/app/views/admin/education/schools/static.html.erb
+++ b/app/views/admin/education/schools/static.html.erb
@@ -11,6 +11,27 @@ city: "<%= prepare_text_for_static school.city %>"
 country: "<%= prepare_text_for_static school.country_common_name %>"
 phone: "<%= prepare_text_for_static school.phone %>"
 url: "<%= prepare_text_for_static @l10n.url %>"
+contact_details:
+<%
+if @l10n.url.present?
+  detail = ContactDetails::Website.new @l10n.url
+  %>
+  url:
+    label: >-
+      <%= detail.label %>
+    value: >-
+      <%= detail.value %>
+<% end %>
+<%
+if school.phone.present?
+  detail = ContactDetails::Phone.new school.phone
+  %>
+  phone:
+    label: >-
+      <%= detail.label %>
+    value: >-
+      <%= detail.value %>
+<% end %>
 <% if @l10n.logo.attached? %>
 logo:
   id: "<%= @l10n.logo.blob.id %>"
diff --git a/app/views/extranet/application/_footer.html.erb b/app/views/extranet/application/_footer.html.erb
index bc05b2b2dbb911aef7a31c32ec01ecba77f79a0b..954668dbc0f7d203aaf12670c796e34d4eff5978 100644
--- a/app/views/extranet/application/_footer.html.erb
+++ b/app/views/extranet/application/_footer.html.erb
@@ -22,7 +22,7 @@ about = current_extranet.about
               <span itemprop="addressLocality"><%= about.city %></span><br>
             </div>
             <% if about_l10n.present? && about_l10n.url.present? %>
-              <a href="<%= social_website_to_url about_l10n.url %>" target="_blank" property="url"><%= social_website_to_s about_l10n.url %></a>
+              <%= contact_link about_l10n.url, :website %>
             <% end %>
           </address>
         <% elsif current_extranet.about.is_a?(Education::Program) %>
diff --git a/app/views/extranet/contacts/persons/_details.html.erb b/app/views/extranet/contacts/persons/_details.html.erb
index b689fb0ed5572a31462383a5f07f33bc3a83cea5..7095f86ffa46ab3c30016ce63f2cafa6dc28044b 100644
--- a/app/views/extranet/contacts/persons/_details.html.erb
+++ b/app/views/extranet/contacts/persons/_details.html.erb
@@ -27,26 +27,18 @@
   <% end %>
   <% if l10n.url.present? %>
     <dt class="fw-normal small"><%= University::Person::Localization.human_attribute_name(:url) %></dt>
-    <dd>
-      <a href="<%= social_website_to_url l10n.url %>" target="_blank" rel="noreferrer">
-        <%= social_website_to_s l10n.url %>
-      </a>
-    </dd>
+    <dd><%= contact_link l10n.url, :website %></dd>
   <% end %>
   <% if l10n.linkedin.present? && !person.linkedin_is_private? %>
     <dt class="fw-normal small"><%= University::Person::Localization.human_attribute_name(:linkedin) %></dt>
-    <dd>
-      <a href="<%= social_linkedin_to_url l10n.linkedin %>" target="_blank" rel="noreferrer">
-        <%= social_linkedin_to_s l10n.linkedin %>
-      </a>
-    </dd>
+    <dd><%= contact_link l10n.linkedin, :linkedin %></dd>
   <% end %>
   <% if l10n.twitter.present? && !person.twitter_is_private? %>
     <dt class="fw-normal small"><%= University::Person::Localization.human_attribute_name(:twitter) %></dt>
-    <dd>
-      <a href="<%= social_twitter_to_url l10n.twitter %>" target="_blank" rel="noreferrer">
-        <%= social_twitter_to_s l10n.twitter %>
-      </a>
-    </dd>
+    <dd><%= contact_link l10n.twitter, :twitter %></dd>
+  <% end %>
+  <% if l10n.mastodon.present? && !person.mastodon_is_private? %>
+    <dt class="fw-normal small"><%= University::Person::Localization.human_attribute_name(:mastodon) %></dt>
+    <dd><%= contact_link l10n.mastodon, :mastodon %></dd>
   <% end %>
 </dl>
diff --git a/app/views/extranet/organizations/show/_details.html.erb b/app/views/extranet/organizations/show/_details.html.erb
index 93d826a867f9b47651fc5229501de7eef462295f..dd12ddbb2c3dc1c14f099ee96d5ecde68639cd40 100644
--- a/app/views/extranet/organizations/show/_details.html.erb
+++ b/app/views/extranet/organizations/show/_details.html.erb
@@ -16,11 +16,7 @@
   <% end %>
   <% if l10n.url.present? %>
     <dt class="fw-normal small"><%= University::Organization::Localization.human_attribute_name(:url) %></dt>
-    <dd>
-      <a href="<%= social_website_to_url l10n.url %>" target="_blank" rel="noreferrer">
-        <%= social_website_to_s l10n.url %>
-      </a>
-    </dd>
+    <dd><%= contact_link l10n.url, :website %></dd>
   <% end %>
   <% if organization.geolocated? %>
     <%# Include map.js before call Leaflet (map helper) %>
diff --git a/app/views/extranet/personal_data/_details.html.erb b/app/views/extranet/personal_data/_details.html.erb
index 6a82b4260f7d36b554c388457b674516f81522d0..c1cba48f16ccd527ebf14370bfcfdcba9210e4a6 100644
--- a/app/views/extranet/personal_data/_details.html.erb
+++ b/app/views/extranet/personal_data/_details.html.erb
@@ -1,10 +1,7 @@
 <dl>
   <% [:phone_mobile, :phone_personal, :phone_professional].each do |attribute_name| %>
     <% next if person.public_send(attribute_name).blank? %>
-    <dt class="fw-normal small">
-      <%= University::Person.human_attribute_name(attribute_name) %>
-      <%= personal_attribute_visibility_tag(person.public_send("#{attribute_name}_visibility")) %>
-    </dt>
+    <dt class="fw-normal small"><%= University::Person.human_attribute_name(attribute_name) %></dt>
     <dd>
       <a href="tel:<%= person.public_send(attribute_name) %>" target="_blank" rel="noreferrer">
         <%= person.public_send(attribute_name) %>
@@ -12,10 +9,7 @@
     </dd>
   <% end %>
   <% if person.email.present? %>
-    <dt class="fw-normal small">
-      <%= University::Person.human_attribute_name(:email) %>
-      <%= personal_attribute_visibility_tag(person.email_visibility) %>
-    </dt>
+    <dt class="fw-normal small"><%= University::Person.human_attribute_name(:email) %></dt>
     <dd>
       <a href="mailto:<%= person.email %>" target="_blank" rel="noreferrer">
         <%= person.email %>
@@ -23,10 +17,7 @@
     </dd>
   <% end %>
   <% if person.full_street_address.present? %>
-    <dt class="fw-normal small">
-      <%= University::Person.human_attribute_name("address") %>
-      <%= personal_attribute_visibility_tag(person.address_visibility) %>
-    </dt>
+    <dt class="fw-normal small"><%= University::Person.human_attribute_name("address") %></dt>
     <dd>
       <%= person.address %>
       <% if person.address.present? && (person.city.present? || person.zipcode.present?) %><br><% end %>
@@ -36,43 +27,18 @@
   <% end %>
   <% if l10n.url.present? %>
     <dt class="fw-normal small"><%= University::Person::Localization.human_attribute_name(:url) %></dt>
-    <dd>
-      <a href="<%= social_website_to_url l10n.url %>" target="_blank" rel="noreferrer">
-        <%= social_website_to_s l10n.url %>
-      </a>
-    </dd>
+    <dd><%= contact_link l10n.url, :website %></dd>
   <% end %>
   <% if l10n.linkedin.present? %>
-    <dt class="fw-normal small">
-      <%= University::Person::Localization.human_attribute_name(:linkedin) %>
-      <%= personal_attribute_visibility_tag(person.linkedin_visibility) %>
-    </dt>
-    <dd>
-      <a href="<%= social_linkedin_to_url l10n.linkedin %>" target="_blank" rel="noreferrer">
-        <%= social_linkedin_to_s l10n.linkedin %>
-      </a>
-    </dd>
+    <dt class="fw-normal small"><%= University::Person::Localization.human_attribute_name(:linkedin) %></dt>
+    <dd><%= contact_link l10n.linkedin, :linkedin %></dd>
   <% end %>
   <% if l10n.twitter.present? %>
-    <dt class="fw-normal small">
-      <%= University::Person::Localization.human_attribute_name(:twitter) %>
-      <%= personal_attribute_visibility_tag(person.twitter_visibility) %>
-    </dt>
-    <dd>
-      <a href="<%= social_twitter_to_url l10n.twitter %>" target="_blank" rel="noreferrer">
-        <%= social_twitter_to_s l10n.twitter %>
-      </a>
-    </dd>
+    <dt class="fw-normal small"><%= University::Person::Localization.human_attribute_name(:twitter) %></dt>
+    <dd><%= contact_link l10n.twitter, :twitter %></dd>
   <% end %>
   <% if l10n.mastodon.present? %>
-    <dt class="fw-normal small">
-      <%= University::Person::Localization.human_attribute_name(:mastodon) %>
-      <%= personal_attribute_visibility_tag(person.mastodon_visibility) %>
-    </dt>
-    <dd>
-      <a href="<%= social_mastodon_to_url l10n.mastodon %>" target="_blank" rel="noreferrer">
-        <%= social_mastodon_to_s l10n.mastodon %>
-      </a>
-    </dd>
+    <dt class="fw-normal small"><%= University::Person::Localization.human_attribute_name(:mastodon) %></dt>
+    <dd><%= contact_link l10n.mastodon, :mastodon %></dd>
   <% end %>
 </dl>
\ No newline at end of file
diff --git a/app/views/showcase/home/_list.html.erb b/app/views/showcase/home/_list.html.erb
index 91cf4fdee33c9648c315c974866432040e01877a..0ef78ef6146dadbe08917945b92473dcf7b09eb1 100644
--- a/app/views/showcase/home/_list.html.erb
+++ b/app/views/showcase/home/_list.html.erb
@@ -16,20 +16,12 @@
         <div class="col-lg-10">
           <h2 class="h4"><%= website.original_localization.to_s %></h2>
           <div class="small mb-1">
-            <%= link_to website.url, 
-                        target: :_blank, 
-                        class: 'text-dark' do %>
-              <i class="bi bi-compass-fill me-1"></i>
-              <%= social_website_to_s(website.url) %>
-            <% end %>
+            <i class="bi bi-compass-fill me-1"></i>
+            <%= contact_link website.url, :website %>
           </div>
           <div class="small mb-1">
-            <%= link_to website.repository_url, 
-                        target: :_blank, 
-                        class: 'text-dark' do %>
-              <i class="bi bi-github me-1"></i>
-              <%= website.repository_url.remove('https://github.com/') %>
-            <% end %>
+            <i class="bi bi-github me-1"></i>
+            <%= contact_link website.repository_url, :github %>
           </div>
           <% website.showcase_tags.each do |tag| %>
             <%= link_to tag, 
diff --git a/test/services/contact_details_test.rb b/test/services/contact_details_test.rb
index b08bab06f711b5ce4930028d67485e453aed33eb..48c096db597f8c28702470b9dfaa74774ebf89ce 100644
--- a/test/services/contact_details_test.rb
+++ b/test/services/contact_details_test.rb
@@ -2,88 +2,172 @@ require "test_helper"
 
 class ContactDetailsTest < ActiveSupport::TestCase
 
-  test "country nil" do
-    detail = ContactDetails::Country.new nil
-    assert_nil detail.label
-    assert_nil detail.value
+  KINDS = [
+    :country,
+    :email,
+    :facebook,
+    :github,
+    :instagram,
+    :linkedin,
+    :mastodon,
+    :peertube,
+    :phone,
+    :tiktok,
+    :twitter,
+    :vimeo,
+    :website,
+    :youtube
+  ]
+
+  test "nil is nil" do
+    KINDS.each do |kind|
+      detail = service_for(kind).new nil
+      assert_nil detail.label
+      assert_nil detail.value
+    end
   end
 
-  test "country FR" do
-    detail = ContactDetails::Country.new 'FR'
-    assert_equal 'France', detail.label
-    assert_equal 'FR', detail.value
+  test "'' is nil" do
+    KINDS.each do |kind|
+      detail = service_for(kind).new ''
+      assert_nil detail.label
+      assert_nil detail.value
+    end
   end
 
-  test "email nil" do
-    detail = ContactDetails::Email.new nil
-    assert_nil detail.label
-    assert_nil detail.value
+  test "country" do
+    batch_test :country, 'France', 'FR', [
+        'FR',
+        'France',
+        'FRANCE'
+      ]
   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
+  test "email" do
+    batch_test :email, 'arnaud.levy@noesya.coop', 'mailto:arnaud.levy@noesya.coop', [
+        'arnaud.levy@noesya.coop'
+      ]
   end
 
-  test "twitter nil" do
-    detail = ContactDetails::Twitter.new nil
-    assert_nil detail.label
-    assert_nil detail.value
+  test 'facebook' do
+    batch_test :facebook, 'noesya.coop', 'https://www.facebook.com/noesya.coop', [
+        'noesya.coop',
+        '@noesya.coop',
+        'https://www.facebook.com/noesya.coop',
+      ]
   end
 
-  test "twitter handle" do
-    detail = ContactDetails::Twitter.new 'arnaudlevy'
-    assert_equal 'arnaudlevy', detail.label
-    assert_equal 'https://twitter.com/arnaudlevy', detail.value
+  test 'github' do
+    batch_test :github, 'noesya', 'https://github.com/noesya', [
+        'noesya',
+        'github.com/noesya',
+        'https://github.com/noesya',
+        'https://www.github.com/noesya',
+      ]
   end
 
-  test "mastodon nil" do
-    detail = ContactDetails::Mastodon.new nil
-    assert_nil detail.label
-    assert_nil detail.value
+  test 'instagram' do
+    batch_test :instagram, 'noesya_coop', 'https://instagram.com/noesya_coop', [
+        'noesya_coop',
+        '@noesya_coop',
+        'https://instagram.com/noesya_coop',
+      ]
   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
+  test 'linkedin person' do
+    batch_test :linkedin, 'arnaudlevy', 'https://www.linkedin.com/in/arnaudlevy/', [
+        'https://www.linkedin.com/in/arnaudlevy/',
+      ]
   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
+  test 'linkedin company' do
+    batch_test :linkedin, 'noesyacoop', 'https://www.linkedin.com/company/noesyacoop/', [
+        'https://www.linkedin.com/company/noesyacoop/',
+      ]
   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
+  test "mastodon" do
+    batch_test :mastodon, 'mastodon.social/@arnaudlevy', 'https://mastodon.social/@arnaudlevy', [
+        'mastodon.social/@arnaudlevy',
+        'https://mastodon.social/@arnaudlevy'
+      ]
   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
+  test "peertube" do
+    batch_test :peertube, 'peertube.designersethiques.org', 'https://peertube.designersethiques.org', [
+        'peertube.designersethiques.org',
+        'https://peertube.designersethiques.org'
+      ]
   end
 
-  test "website nil" do
-    detail = ContactDetails::Website.new nil
-    assert_nil detail.label
-    assert_nil detail.value
+  test "phone" do
+    batch_test :phone, '+33 5 05 05 05 05', 'tel:+33505050505', [
+        '+33 5 05 05 05 05',
+        '+33.5.05.05.05.05',
+      ]
   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
+  test 'tiktok' do
+    batch_test :tiktok, 'aliemeriaud', 'https://www.tiktok.com/@aliemeriaud', [
+        'aliemeriaud',
+        '@aliemeriaud',
+        'https://www.tiktok.com/@aliemeriaud',
+      ]
   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
+  test "twitter or x" do
+    batch_test :twitter, 'arnaudlevy', 'https://x.com/arnaudlevy', [
+        'arnaudlevy',
+        '@arnaudlevy',
+        'twitter.com/arnaudlevy',
+        'www.twitter.com/arnaudlevy',
+        'http://twitter.com/arnaudlevy',
+        'http://www.twitter.com/arnaudlevy',
+        'https://twitter.com/arnaudlevy',
+        'https://www.twitter.com/arnaudlevy',
+        'x.com/arnaudlevy',
+        'www.x.com/arnaudlevy',
+        'http://x.com/arnaudlevy',
+        'http://www.x.com/arnaudlevy',
+        'https://x.com/arnaudlevy',
+        'https://www.x.com/arnaudlevy'
+      ]
   end
 
+  test 'vimeo' do
+    batch_test :vimeo, 'noesya', 'https://vimeo.com/noesya', [
+        'noesya',
+        '@noesya',
+        'https://vimeo.com/noesya',
+      ]
+  end
+
+  test 'website' do
+    batch_test :website, 'www.noesya.coop', 'https://www.noesya.coop', [
+        'www.noesya.coop',
+        'https://www.noesya.coop'
+      ]
+  end
+
+  test 'youtube' do
+    batch_test :youtube, 'MMIBordeaux', 'https://www.youtube.com/@MMIBordeaux', [
+        'MMIBordeaux',
+        '@MMIBordeaux',
+        'https://www.youtube.com/@MMIBordeaux',
+      ]
+  end
+
+  protected
+
+  def batch_test(kind, label, value, options)
+    options.each do |option|
+      detail = service_for(kind).new option
+      assert_equal label, detail.label
+      assert_equal value, detail.value
+    end
+  end
+
+  def service_for(kind)
+    ContactDetails.with_kind kind
+  end
 end
\ No newline at end of file