diff --git a/app/controllers/admin/education/programs_controller.rb b/app/controllers/admin/education/programs_controller.rb
index 46e8e91d448d03fd5f8a584d91abd4d4794ee6fa..bfe44a0bf666f8b48eeaab15357487309076b609 100644
--- a/app/controllers/admin/education/programs_controller.rb
+++ b/app/controllers/admin/education/programs_controller.rb
@@ -21,12 +21,15 @@ class Admin::Education::ProgramsController < Admin::Education::ApplicationContro
       program.update(
         parent_id: parent_id,
         position: index + 1,
-        skip_github_publication: true
+        skip_github_publication: true,
+        skip_websites_categories_callback: true
       )
     end
     website_ids.uniq.each do |website_id|
-      github = Github.with_website current_university.communication_websites.find(website_id)
+      website = current_university.communication_websites.find(website_id)
+      github = Github.with_website website
       github.send_batch_to_website(programs, message: '[Program] Reorder programs.')
+      website.set_programs_categories!
     end
   end
 
diff --git a/app/models/communication/website/category.rb b/app/models/communication/website/category.rb
index a055f367a59257ab701a278c6d8b3326ec6715f6..79a489d5c42c3185cc6239615dd19037d7be910e 100644
--- a/app/models/communication/website/category.rb
+++ b/app/models/communication/website/category.rb
@@ -34,7 +34,7 @@
 class Communication::Website::Category < ApplicationRecord
   include WithGithubFiles
   include WithMenuItemTarget
-  include WithSlug
+  include WithSlug # We override slug_unavailable? method
   include WithTree
 
   has_one :imported_category,
@@ -63,7 +63,6 @@ class Communication::Website::Category < ApplicationRecord
                           association_foreign_key: 'communication_website_post_id'
 
   validates :name, presence: true
-  validates :slug, uniqueness: { scope: :communication_website_id }
 
   after_save :update_children_paths, if: :saved_change_to_path?
 
diff --git a/app/models/communication/website/page.rb b/app/models/communication/website/page.rb
index 4259488271bad604a922afbe6dad363a07d84bde..3763dd68e34b8a501dd8c853b9fe409a54774a3f 100644
--- a/app/models/communication/website/page.rb
+++ b/app/models/communication/website/page.rb
@@ -41,7 +41,7 @@ class Communication::Website::Page < ApplicationRecord
   include Communication::Website::WithMedia
   include WithGithubFiles
   include WithMenuItemTarget
-  include WithSlug
+  include WithSlug # We override slug_unavailable? method
   include WithTree
 
   has_rich_text :text
@@ -65,7 +65,6 @@ class Communication::Website::Page < ApplicationRecord
              dependent: :destroy
 
   validates :title, presence: true
-  validates :slug, uniqueness: { scope: :communication_website_id }
 
   after_save :update_children_paths, if: :saved_change_to_path?
 
diff --git a/app/models/communication/website/post.rb b/app/models/communication/website/post.rb
index 912f6e30aa3445c0eb6e75d0be75ea3fe5e8071e..3158b28873e3e12c968caf27221d045b73c295bf 100644
--- a/app/models/communication/website/post.rb
+++ b/app/models/communication/website/post.rb
@@ -34,7 +34,7 @@ class Communication::Website::Post < ApplicationRecord
   include Communication::Website::WithMedia
   include WithGithubFiles
   include WithMenuItemTarget
-  include WithSlug
+  include WithSlug # We override slug_unavailable? method
 
   has_rich_text :text
   has_one_attached_deletable :featured_image
@@ -56,7 +56,6 @@ class Communication::Website::Post < ApplicationRecord
                           association_foreign_key: 'communication_website_category_id'
 
   validates :title, presence: true
-  validates :slug, uniqueness: { scope: :communication_website_id }
 
   before_validation :set_published_at, if: :published_changed?
 
diff --git a/app/models/communication/website/with_categories.rb b/app/models/communication/website/with_categories.rb
index 81e54190199d3a94ec34d6b8e5bdc2d97fa20500..9548f6a337614142bd9d4d570eea934121ef1628 100644
--- a/app/models/communication/website/with_categories.rb
+++ b/app/models/communication/website/with_categories.rb
@@ -8,15 +8,17 @@ module Communication::Website::WithCategories
         name: 'Offre de formation',
         slug: 'offre-de-formation',
         is_programs_root: true,
-        university_id: university.id
+        university_id: university.id,
+        skip_github_publication: true
       )
-      create_programs_categories_level(programs_root_category, about.programs.root.ordered)
+      programs_categories = [programs_root_category, programs_categories_level(programs_root_category, about.programs.root.ordered)].flatten
+      github.send_batch_to_website(programs_categories, message: '[Category] Set programs categories.')
     end
 
     protected
 
-    def create_programs_categories_level(parent_category, programs)
-      programs.each_with_index do |program, index|
+    def programs_categories_level(parent_category, programs)
+      programs.map.with_index do |program, index|
         program_category = categories.where(program_id: program.id).first_or_initialize(
           name: program.name,
           slug: program.name.parameterize,
@@ -24,11 +26,12 @@ module Communication::Website::WithCategories
         )
         program_category.parent = parent_category
         program_category.position = index + 1
+        program_category.skip_github_publication = true
         program_category.save
         program_children = about.programs.where(parent_id: program.id).ordered
-        create_programs_categories_level(program_category, program_children)
+        [program_category, programs_categories_level(program_category, program_children)].flatten
       end
     end
-    
+
   end
 end
diff --git a/app/models/concerns/with_slug.rb b/app/models/concerns/with_slug.rb
index ac3272e2a3f686f3004d9e3c4e3178c6ae57950b..31de976234557b771e03d8ff6b974febfc7aae82 100644
--- a/app/models/concerns/with_slug.rb
+++ b/app/models/concerns/with_slug.rb
@@ -2,10 +2,8 @@ module WithSlug
   extend ActiveSupport::Concern
 
   included do
-    validates :slug,
-              uniqueness: { scope: :university_id }
-    validates :slug,
-              format: { with: /\A[a-z0-9\-]+\z/, message: I18n.t('slug_error') }
+    validate :slug_must_be_unique
+    validates :slug, format: { with: /\A[a-z0-9\-]+\z/, message: I18n.t('slug_error') }
 
     before_validation :regenerate_slug, :make_path
 
@@ -35,5 +33,9 @@ module WithSlug
       return unless respond_to?(:path) && respond_to?(:parent)
       self.path = generated_path
     end
+
+    def slug_must_be_unique
+      errors.add(:slug, ActiveRecord::Errors.default_error_messages[:taken]) if slug_unavailable?(slug)
+    end
   end
 end
diff --git a/app/models/education/program.rb b/app/models/education/program.rb
index f9b15c3add7cbb337a142dfb2ea315bc8d296ed3..ceef499a71268bcefb656987f910b9ffbf3f4645 100644
--- a/app/models/education/program.rb
+++ b/app/models/education/program.rb
@@ -124,6 +124,6 @@ class Education::Program < ApplicationRecord
   end
 
   def set_websites_categories
-    # websites.find_each(&:set_programs_categories!)
+    websites.find_each(&:set_programs_categories!)
   end
 end