diff --git a/app/assets/javascripts/pages/projects/settings/branch_rules/index.js b/app/assets/javascripts/pages/projects/settings/branch_rules/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..c3d36ad565181d430c6ae2cf3eeeae4623289ed4
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/settings/branch_rules/index.js
@@ -0,0 +1,3 @@
+import mountBranchRules from '~/projects/settings/branch_rules/mount_branch_rules';
+
+mountBranchRules(document.getElementById('js-branch-rules'));
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue b/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue
new file mode 100644
index 0000000000000000000000000000000000000000..941da667a0569e2436f0cb659be20743743a0490
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue
@@ -0,0 +1,11 @@
+<script>
+export default {
+  name: 'RuleEdit',
+};
+</script>
+
+<template>
+  <div>
+    <!-- TODO - Add branch protections (https://gitlab.com/gitlab-org/gitlab/-/issues/362212) -->
+  </div>
+</template>
diff --git a/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js b/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js
new file mode 100644
index 0000000000000000000000000000000000000000..716281c4a3e21f268f6975176b20214714806473
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js
@@ -0,0 +1,15 @@
+import Vue from 'vue';
+import RuleEdit from './components/rule_edit.vue';
+
+export default function mountBranchRules(el) {
+  if (!el) {
+    return null;
+  }
+
+  return new Vue({
+    el,
+    render(h) {
+      return h(RuleEdit);
+    },
+  });
+}
diff --git a/app/controllers/projects/settings/branch_rules_controller.rb b/app/controllers/projects/settings/branch_rules_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0a415b60124f9da16f35021da1b4c25190dc7e05
--- /dev/null
+++ b/app/controllers/projects/settings/branch_rules_controller.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Projects
+  module Settings
+    class BranchRulesController < Projects::ApplicationController
+      before_action :authorize_admin_project!
+
+      feature_category :source_code_management
+
+      def index
+        render_404 unless Feature.enabled?(:branch_rules, project)
+      end
+    end
+  end
+end
diff --git a/app/views/projects/settings/branch_rules/index.html.haml b/app/views/projects/settings/branch_rules/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..13612f375c1e176c7d1fba34324b50ff55ba9c1e
--- /dev/null
+++ b/app/views/projects/settings/branch_rules/index.html.haml
@@ -0,0 +1,6 @@
+- add_to_breadcrumbs _('Repository Settings'), project_settings_repository_path(@project)
+- page_title _('Branch rules')
+
+%h3= _('Branch rules')
+
+#js-branch-rules
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 90400bc4c297fa2eef5b3151081cd6f8472276c5..e8c7333b261e6dbbcb9492a3f7d3443b69caab04 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -147,6 +147,8 @@
             # See MR comment for more detail: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27059#note_311585356
             post :create_deploy_token, path: 'deploy_token/create'
             post :cleanup
+
+            resources :branch_rules, only: [:index]
           end
 
           resources :access_tokens, only: [:index, :create] do
diff --git a/spec/features/projects/settings/branch_rules_settings_spec.rb b/spec/features/projects/settings/branch_rules_settings_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5cc35f108b59dc32a9f372a336a5a8d2270ab25d
--- /dev/null
+++ b/spec/features/projects/settings/branch_rules_settings_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Projects > Settings > Repository > Branch rules settings' do
+  let(:project) { create(:project_empty_repo) }
+  let(:user) { create(:user) }
+  let(:role) { :developer }
+
+  subject(:request) { visit project_settings_repository_branch_rules_path(project) }
+
+  before do
+    project.add_role(user, role)
+    sign_in(user)
+  end
+
+  context 'for developer' do
+    let(:role) { :developer }
+
+    it 'is not allowed to view' do
+      request
+
+      expect(page).to have_gitlab_http_status(:not_found)
+    end
+  end
+
+  context 'for maintainer' do
+    let(:role) { :maintainer }
+
+    context 'Branch rules', :js do
+      it 'renders branch rules page' do
+        request
+
+        expect(page).to have_content('Branch rules')
+      end
+    end
+
+    context 'branch_rules feature flag disabled' do
+      it 'does not render branch rules content' do
+        stub_feature_flags(branch_rules: false)
+        request
+
+        expect(page).to have_gitlab_http_status(:not_found)
+      end
+    end
+  end
+end