diff --git a/app/controllers/admin/communication/extranets/posts/categories_controller.rb b/app/controllers/admin/communication/extranets/posts/categories_controller.rb
index 181259aec816ba1f9600327913d26dddcc344a02..2459302144126dab4a7e41548101ea3159977ccb 100644
--- a/app/controllers/admin/communication/extranets/posts/categories_controller.rb
+++ b/app/controllers/admin/communication/extranets/posts/categories_controller.rb
@@ -57,6 +57,7 @@ class Admin::Communication::Extranets::Posts::CategoriesController < Admin::Comm
     params.require(:communication_extranet_post_category)
     .permit(
       :name,
+      :slug,
     )
     .merge(
       university_id: current_university.id
diff --git a/app/controllers/extranet/posts/categories_controller.rb b/app/controllers/extranet/posts/categories_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b57aca8be03c653a2d9cb0220c278d4c833d6bbd
--- /dev/null
+++ b/app/controllers/extranet/posts/categories_controller.rb
@@ -0,0 +1,15 @@
+class Extranet::Posts::CategoriesController < Extranet::Posts::ApplicationController
+
+  def index
+    @categories = current_extranet.post_categories.ordered
+    breadcrumb
+    add_breadcrumb Communication::Extranet::Post::Category.model_name.human(count: 2)
+  end
+
+  def show
+    @category = current_extranet.post_categories.find_by slug: params[:slug]
+    @posts = @category.posts.ordered.page params[:page]
+    breadcrumb
+    add_breadcrumb @category
+  end
+end
diff --git a/app/models/communication/extranet/post/category.rb b/app/models/communication/extranet/post/category.rb
index d87ec5b7f0d8cce3e2ef67f1adcae3605c9bde88..6a5aa84a24091138bcffac2221a111bf217538eb 100644
--- a/app/models/communication/extranet/post/category.rb
+++ b/app/models/communication/extranet/post/category.rb
@@ -21,14 +21,26 @@
 #  fk_rails_e53c2a25fc  (extranet_id => communication_extranets.id)
 #
 class Communication::Extranet::Post::Category < ApplicationRecord
+  include WithSlug
   include WithUniversity
 
   belongs_to :extranet, class_name: 'Communication::Extranet'
   has_many :posts
 
+  validates :name, presence: true
+
   scope :ordered, -> { order(:name) }
 
   def to_s
     "#{name}"
   end
+
+  protected
+
+  def slug_unavailable?(slug)
+    self.class.unscoped
+              .where(extranet_id: self.extranet_id, slug: slug)
+              .where.not(id: self.id)
+              .exists?
+  end
 end
diff --git a/app/views/admin/communication/extranets/posts/categories/_form.html.erb b/app/views/admin/communication/extranets/posts/categories/_form.html.erb
index 3e20c2e4df27707303dda601a436c1e651de34ad..e90cbfdce6aa77bebb9603d495953178ba1f92b5 100644
--- a/app/views/admin/communication/extranets/posts/categories/_form.html.erb
+++ b/app/views/admin/communication/extranets/posts/categories/_form.html.erb
@@ -9,6 +9,14 @@
       <% end %>
     </div>
     <div class="col-md-4">
+      <%= osuny_panel t('metadata') do %>
+        <%= f.input :slug,
+                    as: :string,
+                    input_html: category.persisted? ? {} : {
+                      class: 'js-slug-input',
+                      data: { source: '#communication_extranet_post_category_name' }
+                    } %>
+      <% end %>
     </div>
   </div>
   <% content_for :action_bar_right do %>
diff --git a/app/views/extranet/library/documents/index.html.erb b/app/views/extranet/library/documents/index.html.erb
index cb923255bbdfebac385474bb1feb9daba9141c9c..4582b5313465a0bf84a40ac9e0c54c930e4cf8bc 100644
--- a/app/views/extranet/library/documents/index.html.erb
+++ b/app/views/extranet/library/documents/index.html.erb
@@ -15,4 +15,5 @@
       </div>
     </div>
   <% end %>
-</div>
\ No newline at end of file
+</div>
+<%= paginate @documents, theme: 'bootstrap-5' %>
\ No newline at end of file
diff --git a/app/views/extranet/posts/categories/index.html.erb b/app/views/extranet/posts/categories/index.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..01c46723514ee229b9017e931dd1a625ff5e7e19
--- /dev/null
+++ b/app/views/extranet/posts/categories/index.html.erb
@@ -0,0 +1,7 @@
+<% content_for :title, Communication::Extranet::Post::Category.model_name.human(count: 2) %>
+
+<ul>
+  <% @categories.each do |category| %>
+    <li><%= link_to category, posts_category_path(slug: category.slug) %></li>
+  <% end %>
+</ul>
\ No newline at end of file
diff --git a/app/views/extranet/posts/categories/show.html.erb b/app/views/extranet/posts/categories/show.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..9fefd9740ffe2b5cc4e56759ea901619f253b224
--- /dev/null
+++ b/app/views/extranet/posts/categories/show.html.erb
@@ -0,0 +1,4 @@
+<% content_for :title, @category %>
+
+<%= render 'extranet/posts/posts/list', posts: @posts %>
+<%= paginate @posts, theme: 'bootstrap-5' %>
\ No newline at end of file
diff --git a/app/views/extranet/posts/posts/_list.html.erb b/app/views/extranet/posts/posts/_list.html.erb
index 4c2211fb6fdc361b1b0d29381da3f7a6c0ed371e..1582e0fa981b8f20940a17e40f966ec239d80a08 100644
--- a/app/views/extranet/posts/posts/_list.html.erb
+++ b/app/views/extranet/posts/posts/_list.html.erb
@@ -9,7 +9,7 @@
           <b><%= post %></b><br>
           <span class="text-muted"><%= l post.published_at.to_date %><span>
         </p>
-        <%= link_to t('extranet.posts.read_post'), posts_communication_extranet_post_path(post.slug), class: ' btn btn-outline-primary stretched-link' %>
+        <%= link_to t('extranet.posts.read_post'), posts_post_path(post.slug), class: ' btn btn-outline-primary stretched-link' %>
       </div>
     </div>
   <% end %>
diff --git a/app/views/extranet/posts/posts/index.html.erb b/app/views/extranet/posts/posts/index.html.erb
index 635a192579918e624f85aaf80347ebd02444aaa2..1d91bfd009f56002e8b3a1ed046fd71740786859 100644
--- a/app/views/extranet/posts/posts/index.html.erb
+++ b/app/views/extranet/posts/posts/index.html.erb
@@ -1,3 +1,4 @@
 <% content_for :title, Communication::Extranet::Post.model_name.human(count: 2) %>
 
-<%= render 'extranet/posts/posts/list', posts: @posts %>
\ No newline at end of file
+<%= render 'extranet/posts/posts/list', posts: @posts %>
+<%= paginate @posts, theme: 'bootstrap-5' %>
\ No newline at end of file
diff --git a/app/views/extranet/posts/posts/show.html.erb b/app/views/extranet/posts/posts/show.html.erb
index bb4f8f186f1de7ad8b7846236bc9b5093bee5fa9..8f3410964550a0c559909163a89113c92d96c499 100644
--- a/app/views/extranet/posts/posts/show.html.erb
+++ b/app/views/extranet/posts/posts/show.html.erb
@@ -6,6 +6,8 @@
   <% end %>
 <% end %>
 
+<%= link_to @post.category, posts_category_path(slug: @post.category.slug) if @post.category %>
+
 </main>
 <%= render 'admin/communication/blocks/preview', about: @post %>
 <main>
diff --git a/config/routes/extranet.rb b/config/routes/extranet.rb
index 33ef5dcb5825064d32fd1b23c3d121f256a07b05..8ea81aaa667989b9db0cf730edf47d903a4a1fc7 100644
--- a/config/routes/extranet.rb
+++ b/config/routes/extranet.rb
@@ -20,7 +20,10 @@ namespace :alumni do
   root to: 'persons#index'
 end
 namespace :posts do
-  get ':slug' => 'posts#show', as: :communication_extranet_post
+  get 'categories' => 'categories#index', as: :categories
+  get 'categories/:slug' => 'categories#show', as: :category
+  # Categories before slug !
+  get ':slug' => 'posts#show', as: :post
   root to: 'posts#index'
 end
 namespace :library do