diff --git a/app/assets/javascripts/ci/runner/components/registration/registration_dropdown.vue b/app/assets/javascripts/ci/runner/components/registration/registration_dropdown.vue
index c1e862f6fa889ac53d6ad85cf87c0b92bb0bc0eb..2fdf8456615a0ef8fb632052faac54e115fa30e3 100644
--- a/app/assets/javascripts/ci/runner/components/registration/registration_dropdown.vue
+++ b/app/assets/javascripts/ci/runner/components/registration/registration_dropdown.vue
@@ -3,7 +3,15 @@ import { GlDropdown, GlDropdownForm, GlDropdownItem, GlDropdownDivider, GlIcon }
 import { s__ } from '~/locale';
 import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
 import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue';
-import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../../constants';
+import {
+  INSTANCE_TYPE,
+  GROUP_TYPE,
+  PROJECT_TYPE,
+  I18N_REGISTER_INSTANCE_TYPE,
+  I18N_REGISTER_GROUP_TYPE,
+  I18N_REGISTER_PROJECT_TYPE,
+  I18N_REGISTER_RUNNER,
+} from '../../constants';
 import RegistrationToken from './registration_token.vue';
 import RegistrationTokenResetDropdownItem from './registration_token_reset_dropdown_item.vue';
 
@@ -51,20 +59,23 @@ export default {
         this.glFeatures?.createRunnerWorkflowForNamespace
       );
     },
-    dropdownText() {
-      if (this.isDeprecated) {
-        return '';
-      }
+    actionText() {
       switch (this.type) {
         case INSTANCE_TYPE:
-          return s__('Runners|Register an instance runner');
+          return I18N_REGISTER_INSTANCE_TYPE;
         case GROUP_TYPE:
-          return s__('Runners|Register a group runner');
+          return I18N_REGISTER_GROUP_TYPE;
         case PROJECT_TYPE:
-          return s__('Runners|Register a project runner');
+          return I18N_REGISTER_PROJECT_TYPE;
         default:
-          return s__('Runners|Register a runner');
+          return I18N_REGISTER_RUNNER;
+      }
+    },
+    dropdownText() {
+      if (this.isDeprecated) {
+        return '';
       }
+      return this.actionText;
     },
     dropdownToggleClass() {
       if (this.isDeprecated) {
@@ -109,6 +120,7 @@ export default {
     v-bind="$attrs"
   >
     <template v-if="isDeprecated" #button-content>
+      <span class="gl-sr-only">{{ actionText }}</span>
       <gl-icon name="ellipsis_v" />
     </template>
     <gl-dropdown-form class="gl-p-4!">
diff --git a/app/assets/javascripts/ci/runner/constants.js b/app/assets/javascripts/ci/runner/constants.js
index 84b2ed010e610f8181f72627ddc5a5d785dcdfd8..1225c0d758365d7a1f3c40ddaeadd7db5c71ed00 100644
--- a/app/assets/javascripts/ci/runner/constants.js
+++ b/app/assets/javascripts/ci/runner/constants.js
@@ -71,6 +71,12 @@ export const I18N_STALE_NEVER_CONTACTED_TOOLTIP = s__(
   'Runners|Runner is stale; it has never contacted this instance',
 );
 
+// Registration dropdown
+export const I18N_REGISTER_INSTANCE_TYPE = s__('Runners|Register an instance runner');
+export const I18N_REGISTER_GROUP_TYPE = s__('Runners|Register a group runner');
+export const I18N_REGISTER_PROJECT_TYPE = s__('Runners|Register a project runner');
+export const I18N_REGISTER_RUNNER = s__('Runners|Register a runner');
+
 // Actions
 export const I18N_EDIT = __('Edit');
 
diff --git a/app/assets/javascripts/ci/runner/project_runners/register/index.js b/app/assets/javascripts/ci/runner/project_runners/register/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..9986c93c91819733d3a3f7fd7263954a0e2ddde1
--- /dev/null
+++ b/app/assets/javascripts/ci/runner/project_runners/register/index.js
@@ -0,0 +1,39 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import RegistrationDropdown from '~/ci/runner/components/registration/registration_dropdown.vue';
+import { PROJECT_TYPE } from '~/ci/runner/constants';
+
+Vue.use(VueApollo);
+
+export const initProjectRunnersRegistrationDropdown = (
+  selector = '#js-project-runner-registration-dropdown',
+) => {
+  const el = document.querySelector(selector);
+
+  if (!el) {
+    return null;
+  }
+
+  const { registrationToken, projectId } = el.dataset;
+
+  const apolloProvider = new VueApollo({
+    defaultClient: createDefaultClient(),
+  });
+
+  return new Vue({
+    el,
+    apolloProvider,
+    provide: {
+      projectId,
+    },
+    render(h) {
+      return h(RegistrationDropdown, {
+        props: {
+          registrationToken,
+          type: PROJECT_TYPE,
+        },
+      });
+    },
+  });
+};
diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
index 9ec560154054129904d650255242387744123d7d..731b1373987b4a2a3b654d63a975f8a8cf9a4d77 100644
--- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
@@ -12,6 +12,7 @@ import { initTokenAccess } from '~/token_access';
 import { initCiSecureFiles } from '~/ci_secure_files';
 import initDeployTokens from '~/deploy_tokens';
 import { initProjectRunners } from '~/ci/runner/project_runners';
+import { initProjectRunnersRegistrationDropdown } from '~/ci/runner/project_runners/register';
 
 // Initialize expandable settings panels
 initSettingsPanels();
@@ -42,6 +43,7 @@ initSettingsPipelinesTriggers();
 initArtifactsSettings();
 
 initProjectRunners();
+initProjectRunnersRegistrationDropdown();
 initSharedRunnersToggle();
 initRefSwitcherBadges();
 initInstallRunner();
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index 28ae730eda583ff093382eaf32ff34bc9f31ae16..626587deb710da702a4b50d33b15e8f3c3a01384 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -15,6 +15,7 @@ class CiCdController < Projects::ApplicationController
       before_action do
         push_frontend_feature_flag(:ci_variables_pages, current_user)
         push_frontend_feature_flag(:ci_limit_environment_scope, @project)
+        push_frontend_feature_flag(:create_runner_workflow_for_namespace, @project.namespace)
       end
 
       helper_method :highlight_badge
diff --git a/app/views/projects/runners/_project_runners.html.haml b/app/views/projects/runners/_project_runners.html.haml
index 9b401711ec5a3d84e027836c263a6dfe261c6f24..1d4e45c71b5b7651411fb6684b87d6a24f45b094 100644
--- a/app/views/projects/runners/_project_runners.html.haml
+++ b/app/views/projects/runners/_project_runners.html.haml
@@ -7,6 +7,7 @@
     - if can?(current_user, :create_runner, @project)
       = render Pajamas::ButtonComponent.new(href: new_project_runner_path(@project), variant: :confirm) do
         = s_('Runners|New project runner')
+      #js-project-runner-registration-dropdown{ data: { registration_token: @project.runners_token, project_id: @project.id } }
     - else
       = _('Please contact an admin to create runners.')
       = link_to _('Learn more.'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'restrict-runner-registration-by-all-users-in-an-instance'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index d82f9acdd074e878eae53852f5e1627b9c49e821..582535790bdd321e3b75b956bece6b3b06237dd6 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -32,15 +32,30 @@
     end
 
     describe "runners registration" do
-      before do
-        stub_feature_flags(create_runner_workflow_for_admin: false)
+      context 'when create_runner_workflow_for_namespace is enabled' do
+        before do
+          stub_feature_flags(create_runner_workflow_for_admin: true)
 
-        visit admin_runners_path
+          visit admin_runners_path
+        end
+
+        it_behaves_like "shows and resets runner registration token" do
+          let(:dropdown_text) { s_('Runners|Register an instance runner') }
+          let(:registration_token) { Gitlab::CurrentSettings.runners_registration_token }
+        end
       end
 
-      it_behaves_like "shows and resets runner registration token" do
-        let(:dropdown_text) { s_('Runners|Register an instance runner') }
-        let(:registration_token) { Gitlab::CurrentSettings.runners_registration_token }
+      context 'when create_runner_workflow_for_namespace is disabled' do
+        before do
+          stub_feature_flags(create_runner_workflow_for_admin: false)
+
+          visit admin_runners_path
+        end
+
+        it_behaves_like "shows and resets runner registration token" do
+          let(:dropdown_text) { s_('Runners|Register an instance runner') }
+          let(:registration_token) { Gitlab::CurrentSettings.runners_registration_token }
+        end
       end
     end
 
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index 54482d141c71164c71b2df21da8bdeab8e8c5fa4..2de95c21003caf798fe6a2aae3afaa47d8c6fd1a 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -21,19 +21,28 @@
         project.add_maintainer(user)
       end
 
-      context 'when create_runner_workflow_for_namespace is enabled' do
+      context 'when create_runner_workflow_for_namespace is enabled', :js do
         before do
           stub_feature_flags(create_runner_workflow_for_namespace: [project.namespace])
-        end
 
-        it 'user can see a link with instructions on how to install GitLab Runner' do
           visit project_runners_path(project)
+        end
 
+        it 'user can see a link with instructions on how to install GitLab Runner' do
           expect(page).to have_link(s_('Runners|New project runner'), href: new_project_runner_path(project))
         end
 
-        describe 'runner registration', :js do
+        it_behaves_like "shows and resets runner registration token" do
+          let(:dropdown_text) { s_('Runners|Register a project runner') }
+          let(:registration_token) { project.runners_token }
+        end
+      end
+
+      context 'when user views new runner page' do
+        context 'when create_runner_workflow_for_namespace is enabled', :js do
           before do
+            stub_feature_flags(create_runner_workflow_for_namespace: [project.namespace])
+
             visit new_project_runner_path(project)
           end
 
diff --git a/spec/frontend/ci/runner/components/registration/registration_dropdown_spec.js b/spec/frontend/ci/runner/components/registration/registration_dropdown_spec.js
index 9df7a974af38320b5634d4d1f2ea7076d9ba0867..e564cf49ca0d813a2a092210251ed1a982490626 100644
--- a/spec/frontend/ci/runner/components/registration/registration_dropdown_spec.js
+++ b/spec/frontend/ci/runner/components/registration/registration_dropdown_spec.js
@@ -12,7 +12,14 @@ import RegistrationDropdown from '~/ci/runner/components/registration/registrati
 import RegistrationToken from '~/ci/runner/components/registration/registration_token.vue';
 import RegistrationTokenResetDropdownItem from '~/ci/runner/components/registration/registration_token_reset_dropdown_item.vue';
 
-import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/ci/runner/constants';
+import {
+  INSTANCE_TYPE,
+  GROUP_TYPE,
+  PROJECT_TYPE,
+  I18N_REGISTER_INSTANCE_TYPE,
+  I18N_REGISTER_GROUP_TYPE,
+  I18N_REGISTER_PROJECT_TYPE,
+} from '~/ci/runner/constants';
 
 import getRunnerPlatformsQuery from '~/vue_shared/components/runner_instructions/graphql/get_runner_platforms.query.graphql';
 import getRunnerSetupInstructionsQuery from '~/vue_shared/components/runner_instructions/graphql/get_runner_setup.query.graphql';
@@ -81,13 +88,13 @@ describe('RegistrationDropdown', () => {
 
   it.each`
     type             | text
-    ${INSTANCE_TYPE} | ${s__('Runners|Register an instance runner')}
-    ${GROUP_TYPE}    | ${s__('Runners|Register a group runner')}
-    ${PROJECT_TYPE}  | ${s__('Runners|Register a project runner')}
-  `('Dropdown text for type $type is "$text"', () => {
-    createComponent({ props: { type: INSTANCE_TYPE } }, mountExtended);
+    ${INSTANCE_TYPE} | ${I18N_REGISTER_INSTANCE_TYPE}
+    ${GROUP_TYPE}    | ${I18N_REGISTER_GROUP_TYPE}
+    ${PROJECT_TYPE}  | ${I18N_REGISTER_PROJECT_TYPE}
+  `('Dropdown text for type $type is "$text"', ({ type, text }) => {
+    createComponent({ props: { type } }, mountExtended);
 
-    expect(wrapper.text()).toContain('Register an instance runner');
+    expect(wrapper.text()).toContain(text);
   });
 
   it('Passes attributes to dropdown', () => {
@@ -214,7 +221,7 @@ describe('RegistrationDropdown', () => {
     { createRunnerWorkflowForAdmin: true },
     { createRunnerWorkflowForNamespace: true },
   ])('When showing a "deprecated" warning', (glFeatures) => {
-    it('Passes deprecated variant props and attributes to dropdown', () => {
+    it('passes deprecated variant props and attributes to dropdown', () => {
       createComponent({
         provide: { glFeatures },
       });
@@ -230,6 +237,17 @@ describe('RegistrationDropdown', () => {
       });
     });
 
+    it.each`
+      type             | text
+      ${INSTANCE_TYPE} | ${I18N_REGISTER_INSTANCE_TYPE}
+      ${GROUP_TYPE}    | ${I18N_REGISTER_GROUP_TYPE}
+      ${PROJECT_TYPE}  | ${I18N_REGISTER_PROJECT_TYPE}
+    `('dropdown text for type $type is "$text"', ({ type, text }) => {
+      createComponent({ props: { type } }, mountExtended);
+
+      expect(wrapper.text()).toContain(text);
+    });
+
     it('shows warning text', () => {
       createComponent(
         {
@@ -243,7 +261,7 @@ describe('RegistrationDropdown', () => {
       expect(text.exists()).toBe(true);
     });
 
-    it('button shows only ellipsis icon', () => {
+    it('button shows ellipsis icon', () => {
       createComponent(
         {
           provide: { glFeatures },
@@ -251,7 +269,6 @@ describe('RegistrationDropdown', () => {
         mountExtended,
       );
 
-      expect(findDropdownBtn().text()).toBe('');
       expect(findDropdownBtn().findComponent(GlIcon).props('name')).toBe('ellipsis_v');
       expect(findDropdownBtn().findAllComponents(GlIcon)).toHaveLength(1);
     });