diff --git a/app/controllers/admin/education/programs_controller.rb b/app/controllers/admin/education/programs_controller.rb
index 858e124aaf59ac2c3725ddfe2697fe4d8f4339a1..25a6e312a0878a22e5e17d0f86de5bd96fd31627 100644
--- a/app/controllers/admin/education/programs_controller.rb
+++ b/app/controllers/admin/education/programs_controller.rb
@@ -56,6 +56,6 @@ class Admin::Education::ProgramsController < Admin::Education::ApplicationContro
     params.require(:education_program)
           .permit(:name, :level, :capacity, :ects, :continuing,
             :prerequisites, :objectives, :duration, :registration, :pedagogy,
-            :evaluation, :accessibility, :pricing, :contacts, :opportunities, :other, school_ids: [])
+            :evaluation, :accessibility, :pricing, :contacts, :opportunities, :other, school_ids: [], teacher_ids: [])
   end
 end
diff --git a/app/controllers/admin/education/teachers_controller.rb b/app/controllers/admin/education/teachers_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..adc6bdbd623e0a338acdb708b3d2622f324a121e
--- /dev/null
+++ b/app/controllers/admin/education/teachers_controller.rb
@@ -0,0 +1,65 @@
+class Admin::Education::TeachersController < Admin::Education::ApplicationController
+  load_and_authorize_resource class: Education::Teacher
+
+  def index
+    @teachers = current_university.teachers.ordered.page(params[:page])
+    breadcrumb
+  end
+
+  def show
+    breadcrumb
+  end
+
+  def publish
+    @teacher.force_publish!
+    redirect_to admin_education_teacher_path(@teacher), notice: t('admin.will_be_published_html', model: @teacher.to_s)
+  end
+
+  def new
+    breadcrumb
+  end
+
+  def edit
+    breadcrumb
+    add_breadcrumb t('edit')
+  end
+
+  def create
+    if @teacher.save
+      redirect_to admin_education_teacher_path(@teacher), notice: t('admin.successfully_created_html', model: @teacher.to_s)
+    else
+      breadcrumb
+      render :new, status: :unprocessable_entity
+    end
+  end
+
+  def update
+    if @teacher.update(teacher_params)
+      redirect_to admin_education_teacher_path(@teacher), notice: t('admin.successfully_updated_html', model: @teacher.to_s)
+    else
+      breadcrumb
+      add_breadcrumb t('edit')
+      render :edit, status: :unprocessable_entity
+    end
+  end
+
+  def destroy
+    @teacher.destroy
+    redirect_to admin_education_teachers_url, notice: t('admin.successfully_destroyed_html', model: @teacher.to_s)
+  end
+
+  protected
+
+  def breadcrumb
+    super
+    add_breadcrumb  Education::Teacher.model_name.human(count: 2),
+                    admin_education_teachers_path
+    breadcrumb_for @teacher
+  end
+
+  def teacher_params
+    params.require(:education_teacher)
+          .permit(:first_name, :last_name, :biography, :slug, :user_id)
+          .merge(university_id: current_university.id)
+  end
+end
diff --git a/app/models/concerns/with_slug.rb b/app/models/concerns/with_slug.rb
index cec6fd76aef447ba36fed0f321811b1d3a56b1d4..81ec3bc25299ccd0f01729c3665ea52eead0fef1 100644
--- a/app/models/concerns/with_slug.rb
+++ b/app/models/concerns/with_slug.rb
@@ -3,7 +3,8 @@ module WithSlug
 
   included do
     validates :slug,
-              uniqueness: { scope: :university_id },
+              uniqueness: { scope: :university_id }
+    validates :slug,
               format: { with: /\A[a-z0-9\-]+\z/, message: "ne peut contenir que des lettres minuscules, des chiffres et des traits d'union." },
               allow_blank: true
   end
diff --git a/app/models/education/program.rb b/app/models/education/program.rb
index 4a4fa6f9d687f29600fcf1aa13a57748b5d88873..6cb08e5d8c59773edcb8d40999d8c384f2e5fb55 100644
--- a/app/models/education/program.rb
+++ b/app/models/education/program.rb
@@ -39,6 +39,11 @@ class Education::Program < ApplicationRecord
                           join_table: 'education_programs_schools',
                           foreign_key: 'education_program_id',
                           association_foreign_key: 'education_school_id'
+  has_and_belongs_to_many :teachers,
+                          class_name: 'Education::Teacher',
+                          join_table: 'education_programs_teachers',
+                          foreign_key: 'education_program_id',
+                          association_foreign_key: 'education_teacher_id'
 
   enum level: {
     bachelor: 300,
diff --git a/app/models/education/teacher.rb b/app/models/education/teacher.rb
new file mode 100644
index 0000000000000000000000000000000000000000..41ad533f93b0746638c62bc451973805c2ceac5c
--- /dev/null
+++ b/app/models/education/teacher.rb
@@ -0,0 +1,57 @@
+# == Schema Information
+#
+# Table name: education_teachers
+#
+#  id            :uuid             not null, primary key
+#  first_name    :string
+#  github_path   :text
+#  last_name     :string
+#  slug          :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  university_id :uuid             not null
+#  user_id       :uuid
+#
+# Indexes
+#
+#  index_education_teachers_on_university_id  (university_id)
+#  index_education_teachers_on_user_id        (user_id)
+#
+# Foreign Keys
+#
+#  fk_rails_...  (university_id => universities.id)
+#  fk_rails_...  (user_id => users.id)
+#
+class Education::Teacher < ApplicationRecord
+  include WithGithub
+  include WithSlug
+
+  has_rich_text :biography
+
+  belongs_to :university
+  belongs_to :user, optional: true
+  has_and_belongs_to_many :programs,
+                          class_name: 'Education::Program',
+                          join_table: 'education_programs_teachers',
+                          foreign_key: 'education_teacher_id',
+                          association_foreign_key: 'education_program_id'
+
+
+  scope :ordered, -> { order(:last_name, :first_name) }
+
+  def to_s
+    "#{last_name} #{first_name}"
+  end
+
+  def github_path_generated
+    "_teachers/#{slug}.html"
+  end
+
+  def to_jekyll
+    ApplicationController.render(
+      template: 'admin/education/teachers/jekyll',
+      layout: false,
+      assigns: { teacher: self }
+    )
+  end
+end
diff --git a/app/models/university/with_education.rb b/app/models/university/with_education.rb
index 5acddc90f4055bb204487797d97d6994c82a189e..786749c3ed9cbd68d69179609186859d5fd08f1f 100644
--- a/app/models/university/with_education.rb
+++ b/app/models/university/with_education.rb
@@ -2,6 +2,7 @@ module University::WithEducation
   extend ActiveSupport::Concern
 
   included do
+    has_many :teachers, class_name: 'Education::Teacher', dependent: :destroy
     has_many :education_programs, class_name: 'Education::Program', dependent: :destroy
     has_many :education_schools, class_name: 'Education::School', dependent: :destroy
   end
diff --git a/app/views/admin/education/programs/_form.html.erb b/app/views/admin/education/programs/_form.html.erb
index 1a38d3141b767bef9b73bea8d1c051eccc198fff..4f54820cbaf34aeeb697cea5dfc740486255d1ce 100644
--- a/app/views/admin/education/programs/_form.html.erb
+++ b/app/views/admin/education/programs/_form.html.erb
@@ -9,8 +9,7 @@
       <%= f.input :continuing %>
       <%= f.association :schools,
                         as: :check_boxes,
-                        collection: current_university.education_schools.ordered
-                             %>
+                        collection: current_university.education_schools.ordered %>
     </div>
     <div class="col-md-8">
       <h2 class="h4"><%= t('education.program.useful_informations') %></h2>
@@ -32,6 +31,9 @@
     <div class="col-md-6">
       <%= f.input :pedagogy, as: :rich_text_area %>
       <%= f.input :evaluation, as: :rich_text_area %>
+      <%= f.association :teachers,
+                        as: :check_boxes,
+                        collection: current_university.teachers.ordered %>
     </div>
   </div>
   <% content_for :action_bar_right do %>
diff --git a/app/views/admin/education/teachers/_form.html.erb b/app/views/admin/education/teachers/_form.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..a84f051ff3922be78f74c441e07c8ae0ca3a4332
--- /dev/null
+++ b/app/views/admin/education/teachers/_form.html.erb
@@ -0,0 +1,37 @@
+<%= simple_form_for [:admin, teacher] do |f| %>
+  <div class="row">
+    <div class="col-md-8">
+      <div class="card flex-fill w-100">
+        <div class="card-header">
+          <h5 class="card-title mb-0"><%= t('content') %></h5>
+        </div>
+        <div class="card-body">
+          <%= f.input :first_name %>
+          <%= f.input :last_name %>
+          <%= f.input :biography, as: :rich_text_area %>
+        </div>
+      </div>
+    </div>
+    <div class="col-md-4">
+      <div class="card flex-fill w-100">
+        <div class="card-header">
+          <h5 class="card-title mb-0"><%= t('metadata') %></h5>
+        </div>
+        <div class="card-body">
+          <%= f.input :slug,
+                      as: :string,
+                      input_html: teacher.persisted? ? {} : {
+                        class: 'js-slug-input',
+                        data: { source: '#education_teacher_first_name, #education_teacher_last_name' }
+                      } %>
+          <%= f.association :user, collection: current_university.users.ordered %>
+          <ul>
+          </ul>
+        </div>
+      </div>
+    </div>
+  </div>
+  <% content_for :action_bar_right do %>
+    <%= submit f %>
+  <% end %>
+<% end %>
diff --git a/app/views/admin/education/teachers/_list.html.erb b/app/views/admin/education/teachers/_list.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..87e1befee2026a66c4609d9467f08538e50b6c33
--- /dev/null
+++ b/app/views/admin/education/teachers/_list.html.erb
@@ -0,0 +1,27 @@
+<table class="<%= table_classes %>">
+  <thead>
+    <tr>
+      <th><%= Education::Teacher.human_attribute_name('name') %></th>
+      <th></th>
+    </tr>
+  </thead>
+  <tbody>
+    <% teachers.each do |teacher| %>
+      <tr>
+        <td><%= link_to teacher, admin_education_teacher_path(teacher) %></td>
+        <td class="text-end">
+          <div class="btn-group" role="group">
+            <%= link_to t('edit'),
+                      edit_admin_education_teacher_path(teacher),
+                      class: button_classes %>
+            <%= link_to t('delete'),
+                      admin_education_teacher_path(teacher),
+                      method: :delete,
+                      data: { confirm: t('please-confirm') },
+                      class: button_classes_danger %>
+          </div>
+        </td>
+      </tr>
+    <% end %>
+  </tbody>
+</table>
diff --git a/app/views/admin/education/teachers/edit.html.erb b/app/views/admin/education/teachers/edit.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..b3f94ca300bb5361d5c000f96b377bd2bd76eb0e
--- /dev/null
+++ b/app/views/admin/education/teachers/edit.html.erb
@@ -0,0 +1,3 @@
+<% content_for :title, @teacher %>
+
+<%= render 'form', teacher: @teacher %>
diff --git a/app/views/admin/education/teachers/index.html.erb b/app/views/admin/education/teachers/index.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..44ce68d4d10ef722296bdb5430f0cf8bae26f57c
--- /dev/null
+++ b/app/views/admin/education/teachers/index.html.erb
@@ -0,0 +1,9 @@
+<% content_for :title, "#{Education::Teacher.model_name.human(count: 2)} (#{@teachers.total_count})" %>
+
+<%= render 'admin/education/teachers/list', teachers: @teachers %>
+<%= paginate @teachers, theme: 'bootstrap-5' %>
+
+
+<% content_for :action_bar_right do %>
+  <%= create_link Education::Teacher %>
+<% end %>
diff --git a/app/views/admin/education/teachers/jekyll.html.erb b/app/views/admin/education/teachers/jekyll.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..8aa58250eeda0702d4f386b63321b42378225bd3
--- /dev/null
+++ b/app/views/admin/education/teachers/jekyll.html.erb
@@ -0,0 +1,10 @@
+---
+title: "<%= @author.to_s %>"
+identifier: "<%= @author.id %>"
+first_name: "<%= @author.first_name %>"
+last_name: "<%= @author.last_name %>"
+slug: "<%= @author.slug %>"
+biography: >
+  <%= prepare_for_github @author.biography, @author.university %>
+---
+<%= @author.github_frontmatter.content.html_safe %>
diff --git a/app/views/admin/education/teachers/new.html.erb b/app/views/admin/education/teachers/new.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..9d2a7e6cf6e8da788d90d7014ed2af0fca92cd6d
--- /dev/null
+++ b/app/views/admin/education/teachers/new.html.erb
@@ -0,0 +1,3 @@
+<% content_for :title, Education::Teacher.model_name.human %>
+
+<%= render 'form', teacher: @teacher %>
diff --git a/app/views/admin/education/teachers/show.html.erb b/app/views/admin/education/teachers/show.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..41bddec60768185dac8f24bcc2d63f4457ea6028
--- /dev/null
+++ b/app/views/admin/education/teachers/show.html.erb
@@ -0,0 +1,44 @@
+<% content_for :title, @teacher %>
+
+<div class="row">
+
+  <div class="col-md-8">
+    <div class="card flex-fill w-100">
+      <div class="card-header">
+        <h2 class="card-title mb-0 h5"><%= t('content') %></h2>
+      </div>
+      <div class="card-body">
+        <h3 class="h5"><%= Education::Teacher.human_attribute_name('biography') %></h3>
+        <%= @teacher.biography %>
+      </div>
+    </div>
+  </div>
+
+  <div class="col-md-4">
+    <div class="card flex-fill w-100">
+      <div class="card-header">
+        <h2 class="card-title mb-0 h5"><%= t('metadata') %></h2>
+      </div>
+      <table class="<%= table_classes %>">
+        <tbody>
+          <tr>
+            <td width="150"><%= Education::Teacher.human_attribute_name('slug') %></td>
+            <td><%= @teacher.slug %></td>
+          </tr>
+          <% if @teacher.user %>
+            <tr>
+              <td width="150"><%= Education::Teacher.human_attribute_name('user') %></td>
+              <td><%= link_to_if can?(:read, @teacher.user), @teacher.user, admin_user_path(@teacher.user) %></td>
+            </tr>
+          <% end %>
+        </tbody>
+      </table>
+    </div>
+  </div>
+
+</div>
+
+
+<% content_for :action_bar_right do %>
+  <%= edit_link @teacher %>
+<% end %>
diff --git a/config/admin_navigation.rb b/config/admin_navigation.rb
index 5cee38c3a407b151643b9bb4fcb4722b33c2ecb1..759ca515528955b895236b599f6bc60e209224a2 100644
--- a/config/admin_navigation.rb
+++ b/config/admin_navigation.rb
@@ -8,7 +8,7 @@ SimpleNavigation::Configuration.run do |navigation|
 
     if can?(:read, Education::Program)
       primary.item :education, Education.model_name.human, nil, { kind: :header }
-      primary.item :education, 'Enseignants', nil, { icon: 'user-graduate' }
+      primary.item :education, Education::Teacher.model_name.human(count: 2), admin_education_teachers_path, { icon: 'user-graduate' }
       primary.item :education, Education::School.model_name.human(count: 2), admin_education_schools_path, { icon: 'university' } if can?(:read, Education::School)
       primary.item :education_programs, Education::Program.model_name.human(count: 2), admin_education_programs_path, { icon: 'graduation-cap' } if can?(:read, Education::Program)
       primary.item :education, 'Ressources éducatives', nil, { icon: 'laptop' }
diff --git a/config/locales/education/en.yml b/config/locales/education/en.yml
index 5ebe188817786dfc889b3d104858787fecc1fbdc..43f72170495fb0916f8117eee46ef5bb2089ae72 100644
--- a/config/locales/education/en.yml
+++ b/config/locales/education/en.yml
@@ -10,6 +10,9 @@ en:
       education/school:
         one: School
         other: Schools
+      education/teacher:
+        one: Teacher
+        other: Teachers
     attributes:
       education/program:
         accessibility: Accessibilité
@@ -28,12 +31,21 @@ en:
         prerequisites: Prérequis
         pricing: Tarifs
         registration: Modalités et délais d’accès
+        schools: Schools
+        teachers: Teachers
       education/school:
-        address:: Address
+        address: Address
         city: City
         country: Country
         name: Name
         zipcode: Zipcode
+      education/teacher:
+        biography: Biography
+        first_name: First name
+        last_name: Last name
+        name: Name
+        slug: Slug
+        user: User
   education:
     program:
       main_informations: Main informations
diff --git a/config/locales/education/fr.yml b/config/locales/education/fr.yml
index a32a5805c63bc69882d451978849357426ed8c4f..480298bcebc04998f6d7c590758ac49eedd86d59 100644
--- a/config/locales/education/fr.yml
+++ b/config/locales/education/fr.yml
@@ -10,6 +10,9 @@ fr:
       education/school:
         one: École
         other: Écoles
+      education/teacher:
+        one: Enseignant·e
+        other: Enseignants·es
     attributes:
       education/program:
         accessibility: Accessibilité
@@ -28,12 +31,21 @@ fr:
         prerequisites: Prérequis
         pricing: Tarifs
         registration: Modalités et délais d’accès
+        schools: Écoles
+        teachers: Enseignants·es
       education/school:
         address: Adresse
         city: Ville
         country: Pays
         name: Nom
         zipcode: Code postal
+      education/teacher:
+        biography: Biographie
+        first_name: Prénom
+        last_name: Nom de famille
+        name: Nom
+        slug: Slug
+        user: Utilisateur
   education:
     program:
       main_informations: Informations essentielles
diff --git a/config/routes/admin/education.rb b/config/routes/admin/education.rb
index 9f158d5913f21e726c3547314429eaeabb3901e3..6969aa6f3afd12a510125c0df297b1623f13b427 100644
--- a/config/routes/admin/education.rb
+++ b/config/routes/admin/education.rb
@@ -1,3 +1,3 @@
 namespace :education do
-  resources :programs, :schools
+  resources :programs, :schools, :teachers
 end
diff --git a/db/migrate/20211115154841_create_education_teacher.rb b/db/migrate/20211115154841_create_education_teacher.rb
new file mode 100644
index 0000000000000000000000000000000000000000..41cae970a07b96fc7787fb3d0b0533ac1eb97159
--- /dev/null
+++ b/db/migrate/20211115154841_create_education_teacher.rb
@@ -0,0 +1,15 @@
+class CreateEducationTeacher < ActiveRecord::Migration[6.1]
+  def change
+    create_table :education_teachers, id: :uuid do |t|
+      t.references :university, null: false, foreign_key: true, type: :uuid
+      t.string :first_name
+      t.string :last_name
+      t.string :slug
+      t.text :github_path
+      t.references :user, null: true, foreign_key: true, type: :uuid
+
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/migrate/20211115162245_create_join_table_programs_teachers.rb b/db/migrate/20211115162245_create_join_table_programs_teachers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1e9081128b868e6c52448d8a3df96306a05e793d
--- /dev/null
+++ b/db/migrate/20211115162245_create_join_table_programs_teachers.rb
@@ -0,0 +1,8 @@
+class CreateJoinTableProgramsTeachers < ActiveRecord::Migration[6.1]
+  def change
+    create_join_table :education_programs, :education_teachers, column_options: {type: :uuid} do |t|
+      t.index [:education_program_id, :education_teacher_id], name: 'program_teacher'
+      t.index [:education_teacher_id, :education_program_id], name: 'teacher_program'
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index cec373177240b054194f018b73c8962e5161bce9..85299fd5125630c41413ea4cd6b9e94f1bcb2415 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.define(version: 2021_11_15_134945) do
+ActiveRecord::Schema.define(version: 2021_11_15_162245) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
@@ -345,6 +345,13 @@ ActiveRecord::Schema.define(version: 2021_11_15_134945) do
     t.index ["education_school_id", "education_program_id"], name: "school_program"
   end
 
+  create_table "education_programs_teachers", id: false, force: :cascade do |t|
+    t.uuid "education_program_id", null: false
+    t.uuid "education_teacher_id", null: false
+    t.index ["education_program_id", "education_teacher_id"], name: "program_teacher"
+    t.index ["education_teacher_id", "education_program_id"], name: "teacher_program"
+  end
+
   create_table "education_schools", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "name"
@@ -359,6 +366,19 @@ ActiveRecord::Schema.define(version: 2021_11_15_134945) do
     t.index ["university_id"], name: "index_education_schools_on_university_id"
   end
 
+  create_table "education_teachers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.uuid "university_id", null: false
+    t.string "first_name"
+    t.string "last_name"
+    t.string "slug"
+    t.text "github_path"
+    t.uuid "user_id"
+    t.datetime "created_at", precision: 6, null: false
+    t.datetime "updated_at", precision: 6, null: false
+    t.index ["university_id"], name: "index_education_teachers_on_university_id"
+    t.index ["user_id"], name: "index_education_teachers_on_user_id"
+  end
+
   create_table "languages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
     t.string "name"
     t.string "iso_code"
@@ -533,6 +553,8 @@ ActiveRecord::Schema.define(version: 2021_11_15_134945) do
   add_foreign_key "communication_websites", "universities"
   add_foreign_key "education_programs", "universities"
   add_foreign_key "education_schools", "universities"
+  add_foreign_key "education_teachers", "universities"
+  add_foreign_key "education_teachers", "users"
   add_foreign_key "research_journal_articles", "research_journal_volumes"
   add_foreign_key "research_journal_articles", "research_journals"
   add_foreign_key "research_journal_articles", "universities"