diff --git a/app/controllers/admin/communication/extranets/posts/categories_controller.rb b/app/controllers/admin/communication/extranets/posts/categories_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2459302144126dab4a7e41548101ea3159977ccb
--- /dev/null
+++ b/app/controllers/admin/communication/extranets/posts/categories_controller.rb
@@ -0,0 +1,67 @@
+class Admin::Communication::Extranets::Posts::CategoriesController < Admin::Communication::Extranets::ApplicationController
+  load_and_authorize_resource class: Communication::Extranet::Post::Category, through: :extranet, through_association: :post_categories
+
+  def index
+    @categories = @categories.ordered
+    breadcrumb
+  end
+
+  def show
+    @posts = @category.posts.ordered.page params[:page]
+    breadcrumb
+  end
+
+  def new
+    breadcrumb
+  end
+
+  def edit
+    breadcrumb
+    add_breadcrumb t('edit')
+  end
+
+  def create
+    if @category.save
+      redirect_to admin_communication_extranet_post_category_path(@category), notice: t('admin.successfully_created_html', model: @category.to_s)
+    else
+      breadcrumb
+      render :new, status: :unprocessable_entity
+    end
+  end
+
+  def update
+    if @category.update(category_params)
+      redirect_to admin_communication_extranet_post_category_path(@category), notice: t('admin.successfully_updated_html', model: @category.to_s)
+    else
+      breadcrumb
+      add_breadcrumb t('edit')
+      render :edit, status: :unprocessable_entity
+    end
+  end
+
+  def destroy
+    @category.destroy
+    redirect_to admin_communication_extranet_post_categories_url, notice: t('admin.successfully_destroyed_html', model: @category.to_s)
+  end
+
+  protected
+
+  def breadcrumb
+    super
+    add_breadcrumb Communication::Extranet.human_attribute_name(:feature_posts), admin_communication_extranet_posts_path
+    add_breadcrumb Communication::Extranet::Post::Category.model_name.human(count: 2), admin_communication_extranet_post_categories_path
+    breadcrumb_for @category
+  end
+
+  def category_params
+    params.require(:communication_extranet_post_category)
+    .permit(
+      :name,
+      :slug,
+    )
+    .merge(
+      university_id: current_university.id
+    )
+  end
+
+end
\ No newline at end of file
diff --git a/app/controllers/admin/communication/extranets/posts_controller.rb b/app/controllers/admin/communication/extranets/posts_controller.rb
index 06a45778374b6f1367e919f4cbed248891ff78c9..c63ad06a8a6d07e8e42e4cbfcca287b6907c4ff1 100644
--- a/app/controllers/admin/communication/extranets/posts_controller.rb
+++ b/app/controllers/admin/communication/extranets/posts_controller.rb
@@ -3,6 +3,7 @@ class Admin::Communication::Extranets::PostsController < Admin::Communication::E
 
   def index
     @posts = @posts.ordered.page params[:page]
+    @categories = @extranet.post_categories.ordered
     breadcrumb
   end
 
@@ -17,7 +18,6 @@ class Admin::Communication::Extranets::PostsController < Admin::Communication::E
   end
 
   def new
-    @post.extranet = @extranet
     if current_user.person.present?
       @post.author = current_user.person
     end
@@ -30,7 +30,6 @@ class Admin::Communication::Extranets::PostsController < Admin::Communication::E
   end
 
   def create
-    @post.extranet = @extranet
     @post.add_photo_import params[:photo_import]
     if @post.save
       redirect_to admin_communication_extranet_post_path(@post), notice: t('admin.successfully_created_html', model: @post.to_s)
@@ -70,7 +69,7 @@ class Admin::Communication::Extranets::PostsController < Admin::Communication::E
       :title, :summary, :text,
       :published, :published_at, :slug,
       :featured_image, :featured_image_delete, :featured_image_infos, :featured_image_alt, :featured_image_credit,
-      :author_id
+      :author_id, :category_id
     )
     .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.rb b/app/models/communication/extranet.rb
index 80bca7540d9803777a961a0a37367c821bc7177f..faabfae4280d7d6a74fa33af518642da3104aaf4 100644
--- a/app/models/communication/extranet.rb
+++ b/app/models/communication/extranet.rb
@@ -58,6 +58,7 @@ class Communication::Extranet < ApplicationRecord
   end
 
   has_many :posts
+  has_many :post_categories, class_name: 'Communication::Extranet::Post::Category'
   has_many :documents
 
   validates_presence_of :name, :host
diff --git a/app/models/communication/extranet/post.rb b/app/models/communication/extranet/post.rb
index 7c844d233c5418008e67eb29ca1edfab3b11cf6a..9161c77213f9625cc114e29a1a9450ed92086f28 100644
--- a/app/models/communication/extranet/post.rb
+++ b/app/models/communication/extranet/post.rb
@@ -13,12 +13,14 @@
 #  created_at            :datetime         not null
 #  updated_at            :datetime         not null
 #  author_id             :uuid             indexed
+#  category_id           :uuid             indexed
 #  extranet_id           :uuid             not null, indexed
 #  university_id         :uuid             not null, indexed
 #
 # Indexes
 #
 #  index_communication_extranet_posts_on_author_id      (author_id)
+#  index_communication_extranet_posts_on_category_id    (category_id)
 #  index_communication_extranet_posts_on_extranet_id    (extranet_id)
 #  index_communication_extranet_posts_on_university_id  (university_id)
 #
@@ -26,18 +28,20 @@
 #
 #  fk_rails_0232de42a1  (university_id => universities.id)
 #  fk_rails_4341823eab  (extranet_id => communication_extranets.id)
+#  fk_rails_7827da1fd1  (category_id => communication_extranet_post_categories.id)
 #  fk_rails_86cc935add  (author_id => university_people.id)
 #
 class Communication::Extranet::Post < ApplicationRecord
   include Sanitizable
-  include WithUniversity
   include WithFeaturedImage
   include WithBlocks
   include WithPublication
   include WithPermalink
   include WithSlug
+  include WithUniversity
 
   belongs_to :author, class_name: 'University::Person', optional: true
+  belongs_to :category, class_name: 'Communication::Extranet::Post::Category', optional: true
   belongs_to :extranet, class_name: 'Communication::Extranet'
 
   validates :title, presence: true
diff --git a/app/models/communication/extranet/post/category.rb b/app/models/communication/extranet/post/category.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6a5aa84a24091138bcffac2221a111bf217538eb
--- /dev/null
+++ b/app/models/communication/extranet/post/category.rb
@@ -0,0 +1,46 @@
+# == Schema Information
+#
+# Table name: communication_extranet_post_categories
+#
+#  id            :uuid             not null, primary key
+#  name          :string
+#  slug          :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  extranet_id   :uuid             not null, indexed
+#  university_id :uuid             not null, indexed
+#
+# Indexes
+#
+#  index_communication_extranet_post_categories_on_extranet_id    (extranet_id)
+#  index_communication_extranet_post_categories_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_aad7b8db63  (university_id => universities.id)
+#  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/models/communication/extranet/with_features.rb b/app/models/communication/extranet/with_features.rb
index cc55664d9a07b799c01a98f4df618ea78d742feb..d9821981ec96831e6dd0839055cfa69030622e17 100644
--- a/app/models/communication/extranet/with_features.rb
+++ b/app/models/communication/extranet/with_features.rb
@@ -3,10 +3,10 @@ module Communication::Extranet::WithFeatures
 
   included do
     FEATURES = [
-      :alumni,
-      :contacts,
       :posts,
+      :contacts,
       :library,
+      :alumni,
       :jobs,
     ]
   end
diff --git a/app/views/admin/communication/extranets/posts/_form.html.erb b/app/views/admin/communication/extranets/posts/_form.html.erb
index e82335fbeb15088be8e18bc6e108175dcef5957c..d263109d38214c1ac9ba3561d3838337293db240 100644
--- a/app/views/admin/communication/extranets/posts/_form.html.erb
+++ b/app/views/admin/communication/extranets/posts/_form.html.erb
@@ -12,16 +12,14 @@
     <div class="col-md-4">
       <%= osuny_panel t('metadata') do %>
         <% if can? :publish, post %>
-          <div class="row pure__row--small">
-            <div class="col-6">
-              <%= f.input :published %>
-            </div>
-          </div>
+          <%= f.input :published %>
           <%= f.input :published_at, html5: true, as: :date %>
         <% end %>
+        <%= f.association :category, 
+                          collection: @extranet.post_categories.ordered %>
         <%= f.association :author,
-                            collection: @extranet.connected_persons.ordered,
-                            label_method: :to_s_alphabetical %>
+                          collection: @extranet.connected_persons.ordered,
+                          label_method: :to_s_alphabetical %>
         <%= f.input :slug,
                     as: :string,
                     input_html: post.persisted? ? {} : {
diff --git a/app/views/admin/communication/extranets/posts/categories/_form.html.erb b/app/views/admin/communication/extranets/posts/categories/_form.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..e90cbfdce6aa77bebb9603d495953178ba1f92b5
--- /dev/null
+++ b/app/views/admin/communication/extranets/posts/categories/_form.html.erb
@@ -0,0 +1,25 @@
+<%= simple_form_for [:admin, category] do |f| %>
+  <%= f.error_notification %>
+  <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
+
+  <div class="row">
+    <div class="col-md-8">
+      <%= osuny_panel t('content') do %>
+        <%= f.input :name %>
+      <% 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 %>
+    <%= submit f %>
+  <% end %>
+<% end %>
diff --git a/app/views/admin/communication/extranets/posts/categories/_list.html.erb b/app/views/admin/communication/extranets/posts/categories/_list.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..e553d2d004b953398e638b9bd1ff4a7b67a2efa5
--- /dev/null
+++ b/app/views/admin/communication/extranets/posts/categories/_list.html.erb
@@ -0,0 +1,30 @@
+<div class="table-responsive">
+  <table class="<%= table_classes %>">
+    <thead>
+      <tr>
+        <th class="ps-0" width="60%"><%= Communication::Extranet::Post::Category.human_attribute_name('name') %></th>
+        <th></th>
+      </tr>
+    </thead>
+    <tbody>
+      <% categories.each do |category| %>
+        <tr>
+          <td class="ps-0"><%= link_to category, admin_communication_extranet_post_category_path(extranet_id: category.extranet.id, id: category.id) %></td>
+
+          <td>
+            <div class="btn-group" role="group">
+              <%= link_to t('edit'),
+                          edit_admin_communication_extranet_post_category_path(website_id: category.id, id: category.id),
+                          class: button_classes if can?(:update, category) %>
+              <%= link_to t('delete'),
+                          admin_communication_extranet_post_category_path(extranet_id: category.extranet.id, id: category.id),
+                          method: :delete,
+                          data: { confirm: t('please_confirm') },
+                          class: button_classes_danger if can?(:destroy, category) %>
+            </div>
+          </td>
+        </tr>
+      <% end %>
+    </tbody>
+  </table>
+</div>
diff --git a/app/views/admin/communication/extranets/posts/categories/edit.html.erb b/app/views/admin/communication/extranets/posts/categories/edit.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..213c0056b51e4ccbfb3ed8619a16bf3b0af53ef7
--- /dev/null
+++ b/app/views/admin/communication/extranets/posts/categories/edit.html.erb
@@ -0,0 +1,5 @@
+<% content_for :title, @category %>
+
+<%= render 'admin/communication/extranets/sidebar' do %>
+  <%= render 'form', category: @category %>
+<% end %>
diff --git a/app/views/admin/communication/extranets/posts/categories/index.html.erb b/app/views/admin/communication/extranets/posts/categories/index.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..421c1358200a4fba552eb203b200d2fee0a8d24f
--- /dev/null
+++ b/app/views/admin/communication/extranets/posts/categories/index.html.erb
@@ -0,0 +1,9 @@
+<% content_for :title, Communication::Extranet::Post::Category.model_name.human(count: 2) %>
+
+<%= render 'admin/communication/extranets/sidebar' do %>
+  <%= render 'admin/communication/extranets/posts/categories/list', categories: @categories %>
+<% end %>
+
+<% content_for :action_bar_right do %>
+  <%= create_link Communication::Extranet::Post::Category %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/admin/communication/extranets/posts/categories/new.html.erb b/app/views/admin/communication/extranets/posts/categories/new.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..dffe93cc2bb91a5bb9d56144cb362177247fb42d
--- /dev/null
+++ b/app/views/admin/communication/extranets/posts/categories/new.html.erb
@@ -0,0 +1,5 @@
+<% content_for :title, Communication::Extranet::Post::Category.model_name.human %>
+
+<%= render 'admin/communication/extranets/sidebar' do %>
+  <%= render 'form', category: @category %>
+<% end %>
diff --git a/app/views/admin/communication/extranets/posts/categories/preview.html.erb b/app/views/admin/communication/extranets/posts/categories/preview.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..14bd7cd482e0666eb021ef6bb70d0732497bf91f
--- /dev/null
+++ b/app/views/admin/communication/extranets/posts/categories/preview.html.erb
@@ -0,0 +1,3 @@
+<% content_for :title, @post.title %>
+<% content_for :image, kamifusen_tag(@post.featured_image) if @post.featured_image.attached? %>
+<%= render 'admin/communication/blocks/preview', about: @post %>
diff --git a/app/views/admin/communication/extranets/posts/categories/show.html.erb b/app/views/admin/communication/extranets/posts/categories/show.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..30f2bd037402f50911dbb153e9453cbcd7dcdfb9
--- /dev/null
+++ b/app/views/admin/communication/extranets/posts/categories/show.html.erb
@@ -0,0 +1,14 @@
+<% content_for :title, @category %>
+
+<%= render 'admin/communication/extranets/sidebar' do %>
+  <%= render 'admin/communication/extranets/posts/list', posts: @posts %>
+  <%= paginate @posts, theme: 'bootstrap-5' %>
+<% end %>
+
+<% content_for :action_bar_left do %>
+  <%= destroy_link @category %>
+<% end %>
+
+<% content_for :action_bar_right do %>
+  <%= edit_link @category %>
+<% end %>
diff --git a/app/views/admin/communication/extranets/posts/index.html.erb b/app/views/admin/communication/extranets/posts/index.html.erb
index e1daf4ea040673e18b2ac2d6645b03e2acd23639..cbf3d5fdf58b1c078afbc51d21172c1a77405044 100644
--- a/app/views/admin/communication/extranets/posts/index.html.erb
+++ b/app/views/admin/communication/extranets/posts/index.html.erb
@@ -1,8 +1,16 @@
 <% content_for :title, Communication::Extranet.human_attribute_name(:feature_posts) %>
 
 <%= render 'admin/communication/extranets/sidebar' do %>
-  <%= render 'admin/communication/extranets/posts/list', posts: @posts %>
-  <%= paginate @posts, theme: 'bootstrap-5' %>
+  <section class="mb-5">
+    <%= render 'admin/communication/extranets/posts/list', posts: @posts %>
+    <%= paginate @posts, theme: 'bootstrap-5' %>
+  </section>
+
+  <% action = link_to t('create'), new_admin_communication_extranet_post_category_path, class: button_classes %>
+  <%# action = create_link Communication::Website::Category %>
+  <%= osuny_panel Communication::Website::Category.model_name.human(count: 2), action: action do %>
+    <%= render 'admin/communication/extranets/posts/categories/list', categories: @categories %>
+  <% end %>
 <% end %>
 
 <% content_for :action_bar_right do %>
diff --git a/app/views/admin/communication/extranets/posts/show.html.erb b/app/views/admin/communication/extranets/posts/show.html.erb
index ad9c804d175b4e4646f32224c592078f240ca9f0..a4aa85eec80ed99554224e3cdb473d32c1e71440 100644
--- a/app/views/admin/communication/extranets/posts/show.html.erb
+++ b/app/views/admin/communication/extranets/posts/show.html.erb
@@ -25,6 +25,10 @@
             </p>
           </div>
         </div>
+        <% if @post.category %>
+          <%= osuny_label Communication::Extranet::Post.human_attribute_name('category') %>
+          <p><%= link_to @post.category, [:admin, @post.category] %></p>
+        <% end %>
         <% if @post.author %>
           <%= osuny_label Communication::Extranet::Post.human_attribute_name('author') %>
           <p><%= @post.author %></p>
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/locales/communication/en.yml b/config/locales/communication/en.yml
index 0f4b689b9124ec29809b9d8a6b0e906148b9d48a..66cb912bd3ecb57c4db5b03fd4a6882e6852d0f0 100644
--- a/config/locales/communication/en.yml
+++ b/config/locales/communication/en.yml
@@ -19,6 +19,9 @@ en:
         one: Post
         other: Posts
         all: All posts
+      communication/extranet/post/category:
+        one: Category
+        other: Categories
       communication/website:
         one: Website
         other: Websites
@@ -87,6 +90,7 @@ en:
         published_at: Publication date
       communication/extranet/post:
         author: Author
+        category: Category
         featured_image: Featured image
         featured_image_alt: Alt text
         featured_image_credit: Credit
@@ -94,6 +98,8 @@ en:
         published_at: Publication date
         slug: Slug
         title: Title
+      communication/extranet/post/category:
+        name: Name
       communication/website:
         about: About
         about_: Independent website
diff --git a/config/locales/communication/fr.yml b/config/locales/communication/fr.yml
index 007f913905480ce036ec8af0ad53005cc446d908..d5129e4f8932bd7902f731506cea13d9effd5ba1 100644
--- a/config/locales/communication/fr.yml
+++ b/config/locales/communication/fr.yml
@@ -19,6 +19,9 @@ fr:
         one: Actualité
         other: Actualités
         all: Toutes les actualités
+      communication/extranet/post/category:
+        one: Catégorie
+        other: Catégories
       communication/website:
         one: Site Web
         other: Sites Web
@@ -87,6 +90,7 @@ fr:
         published_at: Date de publication
       communication/extranet/post:
         author: Auteur·rice
+        category: Catégorie
         featured_image: Image à la une
         featured_image_alt: Texte alternatif
         featured_image_credit: Crédit
@@ -94,6 +98,8 @@ fr:
         published_at: Date de publication
         slug: Identifiant
         title: Titre
+      communication/extranet/post/category:
+        name: Nom
       communication/website:
         about: Sujet du site
         about_: Site indépendant
diff --git a/config/routes/admin/communication.rb b/config/routes/admin/communication.rb
index b9e462905f3284ebe3bc4e70198e8228ea2e33ad..5db6d8e7f5f1afcaa5be3d48e3afd530010e5dee 100644
--- a/config/routes/admin/communication.rb
+++ b/config/routes/admin/communication.rb
@@ -73,7 +73,12 @@ namespace :communication do
         post :disconnect
       end
     end
+    namespace :posts do
+    end
     resources :posts, controller: 'extranets/posts' do
+      collection do
+        resources :categories, controller: 'extranets/posts/categories', as: 'post_categories'
+      end
       member do
         get :preview
       end
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
diff --git a/db/migrate/20230309131421_create_communication_extranet_post_categories.rb b/db/migrate/20230309131421_create_communication_extranet_post_categories.rb
new file mode 100644
index 0000000000000000000000000000000000000000..63443ace3d021bcb5a644cd2e3f10f5304b1324e
--- /dev/null
+++ b/db/migrate/20230309131421_create_communication_extranet_post_categories.rb
@@ -0,0 +1,14 @@
+class CreateCommunicationExtranetPostCategories < ActiveRecord::Migration[7.0]
+  def change
+    create_table :communication_extranet_post_categories, id: :uuid do |t|
+      t.string :name
+      t.string :slug
+      t.references :extranet, null: false, foreign_key: {to_table: :communication_extranets}, type: :uuid
+      t.references :university, null: false, foreign_key: true, type: :uuid
+
+      t.timestamps
+    end
+
+    add_reference :communication_extranet_posts, :category, foreign_key: {to_table: :communication_extranet_post_categories}, type: :uuid
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a6e4c7da3607d29bc7790e3ccc1c8c3dfb5533d1..b33eb378e2f9292532f2d0c40f29124ed0acf236 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_03_09_111101) do
+ActiveRecord::Schema[7.0].define(version: 2023_03_09_131421) do
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
   enable_extension "plpgsql"
@@ -117,6 +117,17 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_09_111101) do
     t.index ["university_id"], name: "index_communication_extranet_documents_on_university_id"
   end
 
+  create_table "communication_extranet_post_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.string "name"
+    t.string "slug"
+    t.uuid "extranet_id", null: false
+    t.uuid "university_id", null: false
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["extranet_id"], name: "index_communication_extranet_post_categories_on_extranet_id"
+    t.index ["university_id"], name: "index_communication_extranet_post_categories_on_university_id"
+  end
+
   create_table "communication_extranet_posts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
     t.string "title"
     t.boolean "published", default: false
@@ -130,7 +141,9 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_09_111101) do
     t.text "summary"
     t.datetime "created_at", null: false
     t.datetime "updated_at", null: false
+    t.uuid "category_id"
     t.index ["author_id"], name: "index_communication_extranet_posts_on_author_id"
+    t.index ["category_id"], name: "index_communication_extranet_posts_on_category_id"
     t.index ["extranet_id"], name: "index_communication_extranet_posts_on_extranet_id"
     t.index ["university_id"], name: "index_communication_extranet_posts_on_university_id"
   end
@@ -201,6 +214,18 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_09_111101) do
     t.index ["communication_website_post_id", "communication_website_category_id"], name: "post_category"
   end
 
+  create_table "communication_website_connections", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.uuid "university_id", null: false
+    t.uuid "website_id", null: false
+    t.string "object_type", null: false
+    t.uuid "object_id", null: false
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["object_type", "object_id"], name: "index_communication_website_connections_on_object"
+    t.index ["university_id"], name: "index_communication_website_connections_on_university_id"
+    t.index ["website_id"], name: "index_communication_website_connections_on_website_id"
+  end
+
   create_table "communication_website_git_files", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "previous_path"
     t.string "about_type", null: false
@@ -389,7 +414,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_09_111101) do
     t.index ["university_id"], name: "index_communication_website_pages_on_university_id"
   end
 
-  create_table "communication_website_permalinks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_permalinks", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "website_id", null: false
     t.string "about_type", null: false
@@ -988,6 +1013,9 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_09_111101) do
   add_foreign_key "communication_extranet_connections", "universities"
   add_foreign_key "communication_extranet_documents", "communication_extranets", column: "extranet_id"
   add_foreign_key "communication_extranet_documents", "universities"
+  add_foreign_key "communication_extranet_post_categories", "communication_extranets", column: "extranet_id"
+  add_foreign_key "communication_extranet_post_categories", "universities"
+  add_foreign_key "communication_extranet_posts", "communication_extranet_post_categories", column: "category_id"
   add_foreign_key "communication_extranet_posts", "communication_extranets", column: "extranet_id"
   add_foreign_key "communication_extranet_posts", "universities"
   add_foreign_key "communication_extranet_posts", "university_people", column: "author_id"
@@ -998,6 +1026,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_09_111101) do
   add_foreign_key "communication_website_categories", "education_programs", column: "program_id"
   add_foreign_key "communication_website_categories", "languages"
   add_foreign_key "communication_website_categories", "universities"
+  add_foreign_key "communication_website_connections", "communication_websites", column: "website_id"
+  add_foreign_key "communication_website_connections", "universities"
   add_foreign_key "communication_website_git_files", "communication_websites", column: "website_id"
   add_foreign_key "communication_website_imported_authors", "communication_website_imported_websites", column: "website_id"
   add_foreign_key "communication_website_imported_authors", "universities"
diff --git a/test/fixtures/communication/extranet/post/categories.yml b/test/fixtures/communication/extranet/post/categories.yml
new file mode 100644
index 0000000000000000000000000000000000000000..57dfca8c4e88ad04a255f565215fc80d38df9686
--- /dev/null
+++ b/test/fixtures/communication/extranet/post/categories.yml
@@ -0,0 +1,35 @@
+# == Schema Information
+#
+# Table name: communication_extranet_post_categories
+#
+#  id            :uuid             not null, primary key
+#  name          :string
+#  slug          :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  extranet_id   :uuid             not null, indexed
+#  university_id :uuid             not null, indexed
+#
+# Indexes
+#
+#  index_communication_extranet_post_categories_on_extranet_id    (extranet_id)
+#  index_communication_extranet_post_categories_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_aad7b8db63  (university_id => universities.id)
+#  fk_rails_e53c2a25fc  (extranet_id => communication_extranets.id)
+#
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+  name: MyString
+  slug: MyString
+  extranet: one
+  university: one
+
+two:
+  name: MyString
+  slug: MyString
+  extranet: two
+  university: two
diff --git a/test/fixtures/communication/extranet/posts.yml b/test/fixtures/communication/extranet/posts.yml
index e2637a5ac93300d6819ee7fc690778d81f7e66ae..0221b524146d8f75722e8324a5c00dbb2fe08bbd 100644
--- a/test/fixtures/communication/extranet/posts.yml
+++ b/test/fixtures/communication/extranet/posts.yml
@@ -13,12 +13,14 @@
 #  created_at            :datetime         not null
 #  updated_at            :datetime         not null
 #  author_id             :uuid             indexed
+#  category_id           :uuid             indexed
 #  extranet_id           :uuid             not null, indexed
 #  university_id         :uuid             not null, indexed
 #
 # Indexes
 #
 #  index_communication_extranet_posts_on_author_id      (author_id)
+#  index_communication_extranet_posts_on_category_id    (category_id)
 #  index_communication_extranet_posts_on_extranet_id    (extranet_id)
 #  index_communication_extranet_posts_on_university_id  (university_id)
 #
@@ -26,6 +28,7 @@
 #
 #  fk_rails_0232de42a1  (university_id => universities.id)
 #  fk_rails_4341823eab  (extranet_id => communication_extranets.id)
+#  fk_rails_7827da1fd1  (category_id => communication_extranet_post_categories.id)
 #  fk_rails_86cc935add  (author_id => university_people.id)
 #
 
@@ -51,4 +54,4 @@ two:
   featured_image_alt: MyString
   featured_image_credit: MyText
   slug: MyString
-  summary: MyText
\ No newline at end of file
+  summary: MyText
diff --git a/test/models/communication/extranet/post/category_test.rb b/test/models/communication/extranet/post/category_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..34cbc4866024b628fe7a47c7c1ed38abea9ad388
--- /dev/null
+++ b/test/models/communication/extranet/post/category_test.rb
@@ -0,0 +1,29 @@
+# == Schema Information
+#
+# Table name: communication_extranet_post_categories
+#
+#  id            :uuid             not null, primary key
+#  name          :string
+#  slug          :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  extranet_id   :uuid             not null, indexed
+#  university_id :uuid             not null, indexed
+#
+# Indexes
+#
+#  index_communication_extranet_post_categories_on_extranet_id    (extranet_id)
+#  index_communication_extranet_post_categories_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_aad7b8db63  (university_id => universities.id)
+#  fk_rails_e53c2a25fc  (extranet_id => communication_extranets.id)
+#
+require "test_helper"
+
+class Communication::Extranet::Post::CategoryTest < ActiveSupport::TestCase
+  # test "the truth" do
+  #   assert true
+  # end
+end
diff --git a/test/models/communication/extranet/post_test.rb b/test/models/communication/extranet/post_test.rb
index 7ebb9729226d256d7dcfc1963f0d30598bea7724..91308df6033cd50a8f7cf6c55c58c52bdd224fb0 100644
--- a/test/models/communication/extranet/post_test.rb
+++ b/test/models/communication/extranet/post_test.rb
@@ -13,12 +13,14 @@
 #  created_at            :datetime         not null
 #  updated_at            :datetime         not null
 #  author_id             :uuid             indexed
+#  category_id           :uuid             indexed
 #  extranet_id           :uuid             not null, indexed
 #  university_id         :uuid             not null, indexed
 #
 # Indexes
 #
 #  index_communication_extranet_posts_on_author_id      (author_id)
+#  index_communication_extranet_posts_on_category_id    (category_id)
 #  index_communication_extranet_posts_on_extranet_id    (extranet_id)
 #  index_communication_extranet_posts_on_university_id  (university_id)
 #
@@ -26,6 +28,7 @@
 #
 #  fk_rails_0232de42a1  (university_id => universities.id)
 #  fk_rails_4341823eab  (extranet_id => communication_extranets.id)
+#  fk_rails_7827da1fd1  (category_id => communication_extranet_post_categories.id)
 #  fk_rails_86cc935add  (author_id => university_people.id)
 #
 require "test_helper"