diff --git a/app/assets/javascripts/projects/details/upload_button.vue b/app/assets/javascripts/projects/details/upload_button.vue
index e1c8c66a2144aba8199332a2d5d3838968bb30c2..d19ec4bcab6cc40441a26f2b18550e9ca316f8df 100644
--- a/app/assets/javascripts/projects/details/upload_button.vue
+++ b/app/assets/javascripts/projects/details/upload_button.vue
@@ -36,7 +36,10 @@ export default {
   <span>
     <gl-button
       v-gl-modal="$options.uploadBlobModalId"
+      variant="link"
       icon="upload"
+      class="stat-link gl-px-0!"
+      button-text-classes="gl-ml-2"
       data-testid="upload-file-button"
       >{{ __('Upload File') }}</gl-button
     >
diff --git a/app/assets/stylesheets/page_bundles/project.scss b/app/assets/stylesheets/page_bundles/project.scss
index 504f14051482d5172f2642a4abb6c12dd59513e1..b3477b5d4c577714c8f7441e0e57a27bf142615b 100644
--- a/app/assets/stylesheets/page_bundles/project.scss
+++ b/app/assets/stylesheets/page_bundles/project.scss
@@ -134,7 +134,7 @@
 
     .stat-text,
     .stat-link {
-      padding: $gl-btn-vert-padding 0;
+      padding: $gl-btn-vert-padding;
       background-color: transparent;
       font-size: $gl-font-size;
       line-height: $gl-btn-line-height;
@@ -149,7 +149,6 @@
       &:hover,
       &:focus {
         text-decoration: underline;
-        border-bottom: 0;
       }
 
       .project-stat-value {
@@ -159,13 +158,6 @@
       .icon {
         color: var(--gray-500, $gl-text-color-secondary);
       }
-
-      .add-license-link {
-        &,
-        .icon {
-          color: var(--blue-600, $blue-600);
-        }
-      }
     }
 
     .btn {
@@ -186,3 +178,60 @@
     color: var(--gl-text-color, $gl-text-color);
   }
 }
+
+// FF :project_overview_reorg enabled
+.project-page-indicator:not(.hidden) + .project-page-layout {
+  --project-overview-sidebar-width: 290px;
+
+  @include media-breakpoint-up(lg) {
+    display: grid;
+    grid-template-columns: auto var(--project-overview-sidebar-width);
+    gap: 2rem;
+
+    .project-page-layout-content,
+    .project-page-layout-sidebar {
+      min-width: 1px;
+    }
+
+    .project-page-layout-sidebar {
+      order: 2;
+      overflow-x: clip;
+      margin-right: -$gl-padding-8;
+    }
+
+    .project-page-sidebar {
+      position: sticky;
+      top: calc(#{$calc-application-header-height} + #{$gl-spacing-scale-4});
+      width: calc(100% + 100px);
+      height: calc(
+        #{$calc-application-viewport-height} - #{$gl-spacing-scale-4}
+      );
+      padding-inline: $gl-padding-4;
+      overflow-y: scroll;
+      overflow-x: hidden;
+      -webkit-overflow-scrolling: touch;
+
+      .project-page-sidebar-block {
+        width: calc(var(--project-overview-sidebar-width) - 1px);
+
+        &:first-of-type {
+          padding-top: $gl-spacing-scale-1;
+        }
+      }
+
+      .nav {
+        > li {
+          width: 100%;
+        }
+
+        .btn {
+          justify-content: flex-start;
+
+          &:not(.btn-dashed) {
+            box-shadow: none;
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/app/assets/stylesheets/page_bundles/projects.scss b/app/assets/stylesheets/page_bundles/projects.scss
index d252afd0b29442c533196576c6e12010aa1bb909..1afc456a16a41f6dbf87f02ec5e6a57aca527f07 100644
--- a/app/assets/stylesheets/page_bundles/projects.scss
+++ b/app/assets/stylesheets/page_bundles/projects.scss
@@ -235,8 +235,7 @@
 }
 
 .repository-languages-bar {
-  height: 8px;
-  margin-bottom: $gl-padding;
+  height: 0.5rem;
   background-color: var(--white, $white);
   border-radius: $border-radius-default;
 
diff --git a/app/helpers/stat_anchors_helper.rb b/app/helpers/stat_anchors_helper.rb
index 957985d695339719234c4a2d13c8fcf434dd249e..31f5d73d020f149eab894ee2bc4df9c685eeaff6 100644
--- a/app/helpers/stat_anchors_helper.rb
+++ b/app/helpers/stat_anchors_helper.rb
@@ -11,12 +11,22 @@ def stat_anchor_attrs(anchor)
 
   private
 
+  def new_button_attribute(anchor)
+    anchor.class_modifier || 'btn-link gl-text-blue-500!'
+  end
+
   def button_attribute(anchor)
     anchor.class_modifier || 'btn-dashed'
   end
 
   def extra_classes(anchor)
-    if anchor.is_link
+    if Feature.enabled?(:project_overview_reorg)
+      if anchor.is_link
+        'stat-link gl-px-0! gl-pb-2!'
+      else
+        "stat-link gl-px-0! gl-pb-2! #{new_button_attribute(anchor)}"
+      end
+    elsif anchor.is_link
       'stat-link'
     else
       "gl-button btn #{button_attribute(anchor)}"
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index c983d8623d2fe9981a5e9377144f30c937c30ee1..a7c8f9a469df78746429a527d30415325e522f2e 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -21,8 +21,16 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
   AnchorData = Struct.new(:is_link, :label, :link, :class_modifier, :icon, :itemprop, :data)
   MAX_TOPICS_TO_SHOW = 3
 
-  def statistic_icon(icon_name = 'plus-square-o')
-    sprite_icon(icon_name, css_class: 'icon gl-mr-2 gl-text-gray-500')
+  def statistic_default_class_list
+    Feature.enabled?(:project_overview_reorg) ? 'icon gl-mr-3 gl-text-gray-500' : 'icon gl-mr-2 gl-text-gray-500'
+  end
+
+  def statistic_default_icon
+    Feature.enabled?(:project_overview_reorg) ? 'plus' : 'plus-square-o'
+  end
+
+  def statistic_icon(icon_name = statistic_default_icon, class_list = statistic_default_class_list)
+    sprite_icon(icon_name, css_class: class_list)
   end
 
   def statistics_anchors(show_auto_devops_callout:)
@@ -288,13 +296,19 @@ def new_file_anchor_data
     if can_current_user_push_to_default_branch?
       new_file_path = empty_repo? ? ide_edit_path(project, default_branch_or_main) : project_new_blob_path(project, default_branch_or_main)
 
-      AnchorData.new(false, statistic_icon + _('New file'), new_file_path, 'btn-dashed')
+      if Feature.enabled?(:project_overview_reorg)
+        AnchorData.new(false, statistic_icon('plus', 'gl-text-blue-500! gl-mr-3') + _('New file'), new_file_path)
+      else
+        AnchorData.new(false, statistic_icon + _('New file'), new_file_path, 'btn-dashed')
+      end
     end
   end
 
   def readme_anchor_data
     if can_current_user_push_to_default_branch? && readme_path.nil?
-      AnchorData.new(false, statistic_icon + _('Add README'), empty_repo? ? add_readme_ide_path : add_readme_path)
+      icon = Feature.enabled?(:project_overview_reorg) ? statistic_icon('plus', 'gl-text-blue-500! gl-mr-3') : statistic_icon
+      label = icon + _('Add README')
+      AnchorData.new(false, label, empty_repo? ? add_readme_ide_path : add_readme_path)
     elsif readme_path
       AnchorData.new(
         false,
@@ -308,9 +322,11 @@ def readme_anchor_data
 
   def changelog_anchor_data
     if can_current_user_push_to_default_branch? && repository.changelog.blank?
+      icon = Feature.enabled?(:project_overview_reorg) ? statistic_icon('plus', 'gl-mr-3') : statistic_icon
+      label = icon + _('Add CHANGELOG')
       AnchorData.new(
         false,
-        statistic_icon + _('Add CHANGELOG'),
+        label,
         empty_repo? ? add_changelog_ide_path : add_changelog_path
       )
     elsif repository.changelog.present?
@@ -336,9 +352,11 @@ def license_anchor_data
         'license'
       )
     elsif can_current_user_push_to_default_branch?
+      icon = Feature.enabled?(:project_overview_reorg) ? statistic_icon('plus', 'gl-text-blue-500! gl-mr-3') : statistic_icon
+      label = icon + _('Add LICENSE')
       AnchorData.new(
         false,
-        content_tag(:span, statistic_icon + _('Add LICENSE'), class: 'add-license-link d-flex'),
+        content_tag(:span, label, class: 'add-license-link d-flex'),
         empty_repo? ? add_license_ide_path : add_license_path
       )
     end
@@ -346,9 +364,11 @@ def license_anchor_data
 
   def contribution_guide_anchor_data
     if can_current_user_push_to_default_branch? && repository.contribution_guide.blank?
+      icon = Feature.enabled?(:project_overview_reorg) ? statistic_icon('plus', 'gl-text-blue-500! gl-mr-3') : statistic_icon
+      label = icon + _('Add CONTRIBUTING')
       AnchorData.new(
         false,
-        statistic_icon + _('Add CONTRIBUTING'),
+        label,
         empty_repo? ? add_contribution_guide_ide_path : add_contribution_guide_path
       )
     elsif repository.contribution_guide.present?
@@ -387,7 +407,11 @@ def autodevops_anchor_data(show_auto_devops_callout: false)
   def kubernetes_cluster_anchor_data
     if can_instantiate_cluster?
       if clusters.empty?
-        AnchorData.new(false, statistic_icon + _('Add Kubernetes cluster'), project_clusters_path(project))
+        if Feature.enabled?(:project_overview_reorg)
+          AnchorData.new(false, content_tag(:span, statistic_icon('plus', 'gl-mr-3') + _('Add Kubernetes cluster'), class: 'btn-link'), project_clusters_path(project))
+        else
+          AnchorData.new(false, content_tag(:span, statistic_icon + _('Add Kubernetes cluster')), project_clusters_path(project))
+        end
       else
         cluster_link = clusters.count == 1 ? project_cluster_path(project, clusters.first) : project_clusters_path(project)
 
@@ -402,7 +426,7 @@ def gitlab_ci_anchor_data
     if cicd_missing?
       AnchorData.new(false, statistic_icon + _('Set up CI/CD'), project_ci_pipeline_editor_path(project))
     elsif repository.gitlab_ci_yml.present?
-      AnchorData.new(false, statistic_icon('doc-text') + _('CI/CD configuration'), project_ci_pipeline_editor_path(project), 'btn-default')
+      AnchorData.new(false, statistic_icon('rocket') + _('CI/CD configuration'), project_ci_pipeline_editor_path(project), 'btn-default')
     end
   end
 
@@ -412,7 +436,9 @@ def wiki_anchor_data
     if project.wiki.has_home_page?
       AnchorData.new(false, statistic_icon('book') + _('Wiki'), project_wiki_path, 'btn-default', nil, nil)
     elsif can_create_wiki?
-      AnchorData.new(false, statistic_icon + _('Add Wiki'), project_create_wiki_path, nil, nil, nil)
+      icon = Feature.enabled?(:project_overview_reorg) ? statistic_icon('plus', 'gl-mr-3') : statistic_icon
+      label = icon + _('Add Wiki')
+      AnchorData.new(false, label, project_create_wiki_path, nil, nil, nil)
     end
   end
 
@@ -457,8 +483,11 @@ def all_clusters_empty?
   def integrations_anchor_data
     return unless can?(current_user, :admin_project, project)
 
-    label = statistic_icon('settings') + _('Configure Integrations')
-    AnchorData.new(false, label, project_settings_integrations_path(project), nil, nil, nil)
+    if Feature.enabled?(:project_overview_reorg)
+      AnchorData.new(false, content_tag(:span, statistic_icon('plus', 'gl-blue-500! gl-mr-3') + _('Configure Integrations'), class: 'btn-link'), project_settings_integrations_path(project), nil, nil, nil)
+    else
+      AnchorData.new(false, content_tag(:span, statistic_icon('settings') + _('Configure Integrations')), project_settings_integrations_path(project), nil, nil, nil)
+    end
   end
 
   def cicd_missing?
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
index fded6fe8abb17d97bf82da307f1c1e70d5441ff2..b958c8f8035a99bd76b3a2608774ccc5fafe09a8 100644
--- a/app/views/projects/_files.html.haml
+++ b/app/views/projects/_files.html.haml
@@ -8,23 +8,27 @@
   - add_page_startup_api_call project_blob_path(@project, tree_join(@ref, readme_path), viewer: "rich", format: "json")
 
 #tree-holder.tree-holder.clearfix.js-per-page{ data: { blame_per_page: Gitlab::Git::BlamePagination::PAGINATION_PER_PAGE } }
+  - if Feature.enabled?(:project_overview_reorg)
+    .nav-block.gl-display-flex.gl-flex-direction-column.gl-sm-flex-direction-row.gl-align-items-stretch
+      = render 'projects/tree/tree_header', tree: @tree
+
   .info-well.gl-display-none.gl-sm-display-flex.project-last-commit.gl-flex-direction-column.gl-mt-5
     #js-last-commit.gl-m-auto{ data: {ref_type: @ref_type.to_s} }
       = gl_loading_icon(size: 'md')
     - if project.licensed_feature_available?(:code_owners)
       #js-code-owners{ data: { branch: @ref, can_view_branch_rules: can_view_branch_rules?, branch_rules_path: branch_rules_path } }
 
-  .nav-block.gl-display-flex.gl-flex-direction-column.gl-sm-flex-direction-row.gl-align-items-stretch
-    = render 'projects/tree/tree_header', tree: @tree
+  - if Feature.disabled?(:project_overview_reorg)
+    .nav-block.gl-display-flex.gl-flex-direction-column.gl-sm-flex-direction-row.gl-align-items-stretch
+      = render 'projects/tree/tree_header', tree: @tree
 
   - if project.forked?
     #js-fork-info{ data: vue_fork_divergence_data(project, ref) }
 
-  - if is_project_overview && has_project_shortcut_buttons
+  - if Feature.disabled?(:project_overview_reorg) && is_project_overview && has_project_shortcut_buttons
     .project-buttons.gl-mb-5.js-show-on-project-root{ data: { testid: 'project-buttons' } }
       = render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout), project_buttons: true
 
   #js-tree-list{ data: vue_file_list_data(project, ref) }
   - if can_edit_tree?
     = render 'projects/blob/new_dir'
-
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index af48bbd262feeb142ff9d4f02aca7ad8b38fa8b3..4ade8ccf348bb24439d1dbbec62045b650d39462 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -1,9 +1,9 @@
 - empty_repo = @project.empty_repo?
-- show_auto_devops_callout = show_auto_devops_callout?(@project)
 - emails_disabled = @project.emails_disabled?
+- ff_reorg_disabled = Feature.disabled?(:project_overview_reorg)
 
-.project-home-panel.js-show-on-project-root.gl-mt-4.gl-mb-5{ class: [("empty-project" if empty_repo)] }
-  .gl-display-flex.gl-justify-content-space-between.gl-flex-wrap.gl-flex-direction-column.gl-md-flex-direction-row.gl-mb-3.gl-gap-5
+%header.project-home-panel.js-show-on-project-root.gl-mt-5{ class: [("empty-project" if empty_repo)] }
+  .gl-display-flex.gl-justify-content-space-between.gl-flex-wrap.gl-flex-direction-column.gl-md-flex-direction-row.gl-gap-5
     .home-panel-title-row.gl-display-flex.gl-align-items-center
       %div{ class: 'avatar-container rect-avatar s64 home-panel-avatar gl-flex-shrink-0 gl-w-11 gl-h-11 gl-mr-3! float-none' }
         = project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s64', width: 64, height: 64, itemprop: 'image')
@@ -35,25 +35,29 @@
       = render 'projects/buttons/star'
       = render 'projects/buttons/fork'
 
-  - if can?(current_user, :read_code, @project)
-    %nav.project-stats
-      - if @project.empty_repo?
-        = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_anchors
-      - else
-        = render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
-  .gl-my-3
-    = render "shared/projects/topics", project: @project
-  .home-panel-home-desc.mt-1
-    - if @project.description.present?
-      .home-panel-description.text-break
-        .home-panel-description-markdown.read-more-container{ itemprop: 'description' }
-          = markdown_field(@project, :description)
-        = render Pajamas::ButtonComponent.new(category: :tertiary, variant: :link, button_options: { class: 'js-read-more-trigger gl-lg-display-none' }) do
-          = _("Read more")
+  - if ff_reorg_disabled
+    - if can?(current_user, :read_code, @project)
+      - show_auto_devops_callout = show_auto_devops_callout?(@project)
+
+      %nav.project-stats.gl-mt-3
+        - if @project.empty_repo?
+          = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_anchors
+        - else
+          = render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
+    .gl-my-3
+      = render "shared/projects/topics", project: @project
+
+    .home-panel-home-desc.mt-1
+      - if @project.description.present?
+        .home-panel-description.text-break
+          .home-panel-description-markdown.read-more-container{ itemprop: 'description' }
+            = markdown_field(@project, :description)
+          = render Pajamas::ButtonComponent.new(category: :tertiary, variant: :link, button_options: { class: 'js-read-more-trigger gl-lg-display-none' }) do
+            = _("Read more")
 
     = render_if_exists "projects/home_mirror"
 
-  - if @project.badges.present?
+  - if ff_reorg_disabled && @project.badges.present?
     .project-badges.mb-2{ data: { testid: 'project-badges-content' } }
       - @project.badges.each do |badge|
         - badge_link_url = badge.rendered_link_url(@project)
diff --git a/app/views/projects/_invite_members_empty_project.html.haml b/app/views/projects/_invite_members_empty_project.html.haml
index 14b0e82e021977daf76505a1441b612752f7b215..730021f345a929d6c9dc3c29eabc2af890253607 100644
--- a/app/views/projects/_invite_members_empty_project.html.haml
+++ b/app/views/projects/_invite_members_empty_project.html.haml
@@ -1,9 +1,20 @@
-%h4.gl-mt-0.gl-mb-3{ data: { testid: 'invite-member-section',
-  track_label: 'invite_members_empty_project',
-  track_action: 'render' } }
-  = s_('InviteMember|Invite your team')
-%p= s_('InviteMember|Add members to this project and start collaborating with your team.')
-.js-invite-members-trigger{ data: { variant: 'confirm',
-  classes: 'gl-mb-8 gl-w-full gl-sm-w-auto',
-  display_text: s_('InviteMember|Invite members'),
-  trigger_source: 'project_empty_page' } }
+- if Feature.enabled?(:project_overview_reorg)
+  %p.gl-font-weight-bold.gl-text-gray-900.gl-mt-0.gl-mt-n1.gl-mb-3{ data: { testid: 'invite-member-section',
+    track_label: 'invite_members_empty_project',
+    track_action: 'render' } }
+    = s_('InviteMember|Invite your team')
+  %p.gl-mb-3= s_('InviteMember|Add members to this project and start collaborating with your team.')
+  .js-invite-members-trigger{ data: { variant: 'confirm',
+    classes: 'gl-mb-3 gl-w-full gl-sm-w-auto',
+    display_text: s_('InviteMember|Invite members'),
+    trigger_source: 'project_empty_page' } }
+- else
+  %h4.gl-mt-0.gl-mb-3{ data: { testid: 'invite-member-section',
+    track_label: 'invite_members_empty_project',
+    track_action: 'render' } }
+    = s_('InviteMember|Invite your team')
+  %p= s_('InviteMember|Add members to this project and start collaborating with your team.')
+  .js-invite-members-trigger{ data: { variant: 'confirm',
+    classes: 'gl-mb-8 gl-w-full gl-sm-w-auto',
+    display_text: s_('InviteMember|Invite members'),
+    trigger_source: 'project_empty_page' } }
diff --git a/app/views/projects/_sidebar.html.haml b/app/views/projects/_sidebar.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..565f14d01d96337aff1dac76c84eb4c5b8ae0b7a
--- /dev/null
+++ b/app/views/projects/_sidebar.html.haml
@@ -0,0 +1,61 @@
+- has_project_shortcut_buttons = !current_user || current_user.project_shortcut_buttons
+- show_auto_devops_callout = show_auto_devops_callout?(@project)
+
+%aside.project-page-sidebar
+  - if @project.description.present? || @project.badges.present?
+    .project-page-sidebar-block.home-panel-home-desc.gl-py-4.gl-border-b.gl-border-gray-50
+      -# Project description
+      - if @project.description.present?
+        .gl-display-flex.gl-justify-content-space-between.gl-mt-1.gl-pr-2
+          %p.gl-font-weight-bold.gl-text-gray-900.gl-m-0= s_('ProjectPage|Project information')
+          = render Pajamas::ButtonComponent.new(href: edit_project_path(@project),
+            category: :tertiary,
+            icon: 'settings',
+            size: :small,
+            button_options: { class: 'has-tooltip', title: s_('ProjectPage|Project settings'), 'aria-label' => s_('ProjectPage|Project settings') })
+        .home-panel-description.text-break
+          .home-panel-description-markdown{ itemprop: 'description' }
+            = markdown_field(@project, :description)
+
+      -# Topics
+      - if @project.topics.present?
+        .gl-mb-5
+          = render "shared/projects/topics", project: @project
+
+      -# Programming languages
+      - if can?(current_user, :read_code, @project) && @project.repository_languages.present?
+        .gl-mb-2{ class: ('gl-mb-4!' if @project.badges.present?) }
+          = repository_languages_bar(@project.repository_languages)
+
+      -# Badges
+      - if @project.badges.present?
+        .project-badges.gl-mb-2{ data: { testid: 'project-badges-content' } }
+          - @project.badges.each do |badge|
+            - badge_link_url = badge.rendered_link_url(@project)
+            %a.gl-mr-3{ href: badge_link_url,
+              target: '_blank',
+              rel: 'noopener noreferrer',
+              data: { testid: 'badge-image-link', qa_link_url: badge_link_url } }>
+              %img.project-badge{ src: badge.rendered_image_url(@project),
+                'aria-hidden': true,
+                alt: 'Project badge' }>
+
+  -# Invite members
+  - if @project.empty_repo?
+    .project-page-sidebar-block.gl-py-4.gl-border-b.gl-border-gray-50
+      = render "invite_members_empty_project" if can_admin_project_member?(@project)
+
+  -# Buttons
+  - if can?(current_user, :read_code, @project) && !@project.empty_repo?
+    .project-page-sidebar-block.gl-py-4.gl-border-b.gl-border-gray-50
+      %nav.project-stats
+        = render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
+
+  -# Buttons
+  - if has_project_shortcut_buttons
+    .project-page-sidebar-block.gl-py-4
+      .project-buttons.gl-mb-2.js-show-on-project-root{ data: { testid: 'project-buttons' } }
+        - if @project.empty_repo?
+          = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons, project_buttons: true
+        - else
+          = render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout), project_buttons: true
diff --git a/app/views/projects/_stat_anchor_list.html.haml b/app/views/projects/_stat_anchor_list.html.haml
index 1409b28e735b4a8614f46d658150bdb80db7e2f7..8cad1974ffa4d0ff409f615192f004d21447d83d 100644
--- a/app/views/projects/_stat_anchor_list.html.haml
+++ b/app/views/projects/_stat_anchor_list.html.haml
@@ -2,8 +2,9 @@
 - project_buttons = local_assigns.fetch(:project_buttons, false)
 
 - return unless anchors.any?
-%ul.nav{ class: (project_buttons ? 'gl-gap-3' : 'gl-gap-5') }
+
+%ul.nav.gl-gap-2
   - anchors.each do |anchor|
     %li.nav-item
       = link_to_if(anchor.link, anchor.label, anchor.link, stat_anchor_attrs(anchor)) do
-        .stat-text.d-flex.align-items-center{ class: ('btn gl-button btn-default disabled' if project_buttons) }= anchor.label
+        .stat-text.d-flex.align-items-center{ class: ('btn gl-button btn-default gl-px-0! disabled' if project_buttons) }= anchor.label
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index ca9900a646e4d0cc7de04625552f4b72a98cf25d..a260dd2bf286d34e4420c186c5285cbdec0c190a 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -9,68 +9,142 @@
 = render "home_panel"
 = render "archived_notice", project: @project
 
-= render "invite_members_empty_project" if can_admin_project_member?(@project)
+- if Feature.enabled?(:project_overview_reorg)
+  - add_page_specific_style 'page_bundles/project'
 
-%h4.gl-mt-0.gl-mb-3
-  = _('The repository for this project is empty')
+  .project-page-indicator.js-show-on-project-root
 
-- if @project.can_current_user_push_code?
-  %p
-    = _('You can get started by cloning the repository or start adding files to it with one of the following options.')
+  .project-page-layout
+    .project-page-layout-content.gl-mt-5
+      .project-buttons.gl-mb-5{ data: { testid: 'quick-actions-container' } }
+        .project-clone-holder.d-block.d-md-none
+          = render "shared/mobile_clone_panel"
 
-.project-buttons{ data: { testid: 'quick-actions-container' } }
-  .project-code-holder.d-block.d-md-none.gl-mt-3.gl-mr-3
-    = render "shared/mobile_clone_panel"
+        .project-clone-holder.gl-display-none.gl-md-display-flex.gl-justify-content-end.gl-w-full.gl-mt-2
+          = render "projects/buttons/code", ref: @ref
 
-  .project-code-holder.d-none.d-md-inline-block.gl-mb-3.gl-mr-3.float-left
-    = render "projects/buttons/code", ref: @ref
-  = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons, project_buttons: true
+      = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-new-card-body gl-bg-gray-10 gl-p-5' }) do |c|
+        - c.with_body do
+          %h4.gl-font-lg.gl-mt-0.gl-mb-2= _('The repository for this project is empty')
+          - if @project.can_current_user_push_code?
+            %p.gl-m-0.gl-text-secondary= _('You can get started by cloning the repository or start adding files to it with one of the following options.')
 
-- if can?(current_user, :push_code, @project)
-  .empty-wrapper.gl-mt-4
-    %h3#repo-command-line-instructions.page-title-empty
-      = _('Command line instructions')
+      - if can?(current_user, :push_code, @project)
+        = render Pajamas::CardComponent.new(header_options: { class: 'gl-py-4' }) do |c|
+          - c.with_header do
+            %h5.gl-font-lg.gl-m-0= _('Command line instructions')
+          - c.with_body do
+            %p
+              = _('You can also upload existing files from your computer using the instructions below.')
+            .git-empty.js-git-empty
+              %h5= _('Git global setup')
+              %pre.gl-bg-gray-10
+                :preserve
+                  git config --global user.name "#{h git_user_name}"
+                  git config --global user.email "#{h git_user_email}"
+
+              %h5= _('Create a new repository')
+              %pre.gl-bg-gray-10
+                :preserve
+                  git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+                  cd #{h @project.path}
+                  git switch --create #{h escaped_default_branch_name}
+                  touch README.md
+                  git add README.md
+                  git commit -m "add README"
+                - if @project.can_current_user_push_to_default_branch?
+                  %span><
+                    git push --set-upstream origin #{h escaped_default_branch_name }
+
+              %h5= _('Push an existing folder')
+              %pre.gl-bg-gray-10
+                :preserve
+                  cd existing_folder
+                  git init --initial-branch=#{h escaped_default_branch_name}
+                  git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+                  git add .
+                  git commit -m "Initial commit"
+                - if @project.can_current_user_push_to_default_branch?
+                  %span><
+                    git push --set-upstream origin #{h escaped_default_branch_name }
+
+              %h5= _('Push an existing Git repository')
+              %pre.gl-bg-gray-10
+                :preserve
+                  cd existing_repo
+                  git remote rename origin old-origin
+                  git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+                - if @project.can_current_user_push_to_default_branch?
+                  %span><
+                    git push --set-upstream origin --all
+                    git push --set-upstream origin --tags
+
+    .project-page-layout-sidebar.js-show-on-project-root.gl-mt-5
+      = render "sidebar"
+
+- else
+  = render "invite_members_empty_project" if can_admin_project_member?(@project)
+
+  %h4.gl-mt-0.gl-mb-3
+    = _('The repository for this project is empty')
+
+  - if @project.can_current_user_push_code?
     %p
-      = _('You can also upload existing files from your computer using the instructions below.')
-    .git-empty.js-git-empty
-      %h5= _('Git global setup')
-      %pre.bg-light
-        :preserve
-          git config --global user.name "#{h git_user_name}"
-          git config --global user.email "#{h git_user_email}"
-
-      %h5= _('Create a new repository')
-      %pre.bg-light
-        :preserve
-          git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
-          cd #{h @project.path}
-          git switch --create #{h escaped_default_branch_name}
-          touch README.md
-          git add README.md
-          git commit -m "add README"
-        - if @project.can_current_user_push_to_default_branch?
-          %span><
-            git push --set-upstream origin #{h escaped_default_branch_name }
-
-      %h5= _('Push an existing folder')
-      %pre.bg-light
-        :preserve
-          cd existing_folder
-          git init --initial-branch=#{h escaped_default_branch_name}
-          git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
-          git add .
-          git commit -m "Initial commit"
-        - if @project.can_current_user_push_to_default_branch?
-          %span><
-            git push --set-upstream origin #{h escaped_default_branch_name }
-
-      %h5= _('Push an existing Git repository')
-      %pre.bg-light
-        :preserve
-          cd existing_repo
-          git remote rename origin old-origin
-          git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
-        - if @project.can_current_user_push_to_default_branch?
-          %span><
-            git push --set-upstream origin --all
-            git push --set-upstream origin --tags
+      = _('You can get started by cloning the repository or start adding files to it with one of the following options.')
+
+  .project-buttons{ data: { testid: 'quick-actions-container' } }
+    .project-clone-holder.d-block.d-md-none.gl-mt-3.gl-mr-3
+      = render "shared/mobile_clone_panel"
+
+    .project-clone-holder.d-none.d-md-inline-block.gl-mb-3.gl-mr-3.float-left
+      = render "projects/buttons/code", ref: @ref
+    = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons, project_buttons: true
+
+  - if can?(current_user, :push_code, @project)
+    .empty-wrapper.gl-mt-4
+      %h3#repo-command-line-instructions.page-title-empty
+        = _('Command line instructions')
+      %p
+        = _('You can also upload existing files from your computer using the instructions below.')
+      .git-empty.js-git-empty
+        %h5= _('Git global setup')
+        %pre.bg-light
+          :preserve
+            git config --global user.name "#{h git_user_name}"
+            git config --global user.email "#{h git_user_email}"
+
+        %h5= _('Create a new repository')
+        %pre.bg-light
+          :preserve
+            git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+            cd #{h @project.path}
+            git switch --create #{h escaped_default_branch_name}
+            touch README.md
+            git add README.md
+            git commit -m "add README"
+          - if @project.can_current_user_push_to_default_branch?
+            %span><
+              git push --set-upstream origin #{h escaped_default_branch_name }
+
+        %h5= _('Push an existing folder')
+        %pre.bg-light
+          :preserve
+            cd existing_folder
+            git init --initial-branch=#{h escaped_default_branch_name}
+            git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+            git add .
+            git commit -m "Initial commit"
+          - if @project.can_current_user_push_to_default_branch?
+            %span><
+              git push --set-upstream origin #{h escaped_default_branch_name }
+
+        %h5= _('Push an existing Git repository')
+        %pre.bg-light
+          :preserve
+            cd existing_repo
+            git remote rename origin old-origin
+            git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+          - if @project.can_current_user_push_to_default_branch?
+            %span><
+              git push --set-upstream origin --all
+              git push --set-upstream origin --tags
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index c76fa5e2220ab2774501cadb0c96bdc5d981d870..9c0badf40904b7b1c1e2a12222731320b06b46c9 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -15,15 +15,35 @@
 
 = render "home_panel"
 
-- if can?(current_user, :read_code, @project) && @project.repository_languages.present?
-  - add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path || "" })
-  = repository_languages_bar(@project.repository_languages)
+- if Feature.enabled?(:project_overview_reorg)
+  .project-page-indicator.js-show-on-project-root
 
-= render "archived_notice", project: @project
-= render_if_exists "projects/marked_for_deletion_notice", project: @project
-= render_if_exists "projects/ancestor_group_marked_for_deletion_notice", project: @project
+  .project-page-layout
+    .project-page-layout-sidebar.js-show-on-project-root.gl-mt-5
+      = render "sidebar"
 
-- view_path = @project.default_view
+    .project-page-layout-content.gl-mt-5
+      - if can?(current_user, :read_code, @project) && @project.repository_languages.present?
+        - add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path || "" })
 
-%div{ class: project_child_container_class(view_path) }
-  = render view_path, is_project_overview: true
+      = render "archived_notice", project: @project
+      = render_if_exists "projects/marked_for_deletion_notice", project: @project
+      = render_if_exists "projects/ancestor_group_marked_for_deletion_notice", project: @project
+
+      - view_path = @project.default_view
+
+      %div{ class: project_child_container_class(view_path) }
+        = render view_path, is_project_overview: true
+- else
+  - if can?(current_user, :read_code, @project) && @project.repository_languages.present?
+    - add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path || "" })
+    = repository_languages_bar(@project.repository_languages)
+
+  = render "archived_notice", project: @project
+  = render_if_exists "projects/marked_for_deletion_notice", project: @project
+  = render_if_exists "projects/ancestor_group_marked_for_deletion_notice", project: @project
+
+  - view_path = @project.default_view
+
+  %div{ class: project_child_container_class(view_path) }
+    = render view_path, is_project_overview: true
diff --git a/app/views/shared/projects/_topics.html.haml b/app/views/shared/projects/_topics.html.haml
index c4524125a21e487706c4ef45a393f6afdb56f70b..33e4ac58fa5a3eb60b06d707514e5b7bea5f57ea 100644
--- a/app/views/shared/projects/_topics.html.haml
+++ b/app/views/shared/projects/_topics.html.haml
@@ -2,8 +2,9 @@
 
 - if project.topics.present?
   .gl-w-full.gl-display-inline-flex.gl-flex-wrap.gl-font-base.gl-font-weight-normal.gl-align-items-center.gl-mx-n2.gl-my-n2{ 'data-testid': 'project_topic_list' }
-    %span.gl-p-2.gl-text-gray-500
-      = _('Topics') + ':'
+    - if Feature.disabled?(:project_overview_reorg)
+      %span.gl-p-2.gl-text-gray-500
+        = _('Topics') + ':'
     - project.topics_to_show.each do |topic|
       - explore_project_topic_path = topic_explore_projects_cleaned_path(topic_name: topic[:name])
       - if topic[:title].length > max_project_topic_length
diff --git a/config/feature_flags/development/project_overview_reorg.yml b/config/feature_flags/development/project_overview_reorg.yml
new file mode 100644
index 0000000000000000000000000000000000000000..994c17aada6c124ef2dbdc03404d338ce951ead1
--- /dev/null
+++ b/config/feature_flags/development/project_overview_reorg.yml
@@ -0,0 +1,8 @@
+---
+name: project_overview_reorg
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/137025
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/432034
+milestone: '16.7'
+type: development
+group: group::ux paper cuts
+default_enabled: false
diff --git a/ee/spec/features/projects/show_project_spec.rb b/ee/spec/features/projects/show_project_spec.rb
index fefb922885b13e9a5509844224544edcf3688247..a6b3ac080477466b32cfe7e7effbee34c4a06fd3 100644
--- a/ee/spec/features/projects/show_project_spec.rb
+++ b/ee/spec/features/projects/show_project_spec.rb
@@ -36,6 +36,10 @@
       create(:project, :repository, mirror: true, mirror_user: user, import_url: 'http://user:pass@test.com')
     end
 
+    before do
+      stub_feature_flags(project_overview_reorg: false)
+    end
+
     context 'for maintainer' do
       before do
         project.add_maintainer(user)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 453b983fddba2231e627c5faed9548961db30114..3466049ec218d0f5ecccfa78df18c4fe56607377 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -37438,6 +37438,12 @@ msgstr ""
 msgid "ProjectPage|Project ID: %{project_id}"
 msgstr ""
 
+msgid "ProjectPage|Project information"
+msgstr ""
+
+msgid "ProjectPage|Project settings"
+msgstr ""
+
 msgid "ProjectQualitySummary|An error occurred while trying to fetch project quality statistics"
 msgstr ""
 
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 3223b2b488ddd311514f1d2c10a35c9b1f3f6a31..93383a8daa0af91d9258b7cfd9ae9af4eddcec40 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -36,6 +36,9 @@ class Show < Page::Base
         view 'app/views/projects/_home_panel.html.haml' do
           element 'project-name-content'
           element 'project-id-content'
+        end
+
+        view 'app/views/projects/_sidebar.html.haml' do
           element 'project-badges-content'
           element 'badge-image-link'
         end
diff --git a/spec/features/projects/show/user_sees_git_instructions_spec.rb b/spec/features/projects/show/user_sees_git_instructions_spec.rb
index 5e6857843a672104aaed89c4b0a2f3299d82e971..4933b3f239c6b5a1183645351344ec7b34f8816a 100644
--- a/spec/features/projects/show/user_sees_git_instructions_spec.rb
+++ b/spec/features/projects/show/user_sees_git_instructions_spec.rb
@@ -10,6 +10,7 @@
     # validation failure on NotificationSetting.
     # See https://gitlab.com/gitlab-org/gitlab/-/issues/299822#note_492817174
     user.notification_settings.reset
+    stub_feature_flags(project_overview_reorg: false)
   end
 
   shared_examples_for 'redirects to the sign in page' do
diff --git a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
index 41eab966895362022f9833d2c639de500c20493d..674c7db83f1b3f39be8f4621f377b19c4aa147e9 100644
--- a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
+++ b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
@@ -17,8 +17,8 @@
 
     describe 'as a normal user' do
       before do
+        stub_feature_flags(project_overview_reorg: false)
         sign_in(user)
-
         visit project_path(project)
       end
 
@@ -40,6 +40,7 @@
 
     describe 'as a maintainer' do
       before do
+        stub_feature_flags(project_overview_reorg: false)
         project.add_maintainer(user)
         sign_in(user)
 
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index c6966e47f0ac83a701dd4df1799f82abbf98b94e..77ba5c53a35ebf0a3abe6e8d65762bd9111d5817 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -12,6 +12,7 @@
     before do
       sign_in user
       visit new_project_path
+      stub_feature_flags(project_overview_reorg: false)
     end
 
     shared_examples 'creates from template' do |template, sub_template_tab = nil|
@@ -99,6 +100,7 @@
 
     before do
       sign_in(project.first_owner)
+      stub_feature_flags(project_overview_reorg: false)
     end
 
     it 'parses Markdown' do
@@ -164,6 +166,7 @@
     before do
       sign_in(project.first_owner)
       visit path
+      stub_feature_flags(project_overview_reorg: false)
     end
 
     it 'shows project topics' do
@@ -195,6 +198,7 @@
     before do
       sign_in(project.first_owner)
       visit path
+      stub_feature_flags(project_overview_reorg: false)
     end
 
     context 'desktop component' do
@@ -427,6 +431,10 @@
     let(:project) { create(:project, :repository) }
     let(:user) { create(:user) }
 
+    before do
+      stub_feature_flags(project_overview_reorg: false)
+    end
+
     it 'does not contain default branch information in its content', :js do
       default_branch = 'merge-commit-analyze-side-branch'
 
diff --git a/spec/frontend/read_more_spec.js b/spec/frontend/read_more_spec.js
index 5f7bd32e23101b47d1fc5b9ddd18f371a4bf8853..9b25c56f19322d8ad768e77c90748027f49acc04 100644
--- a/spec/frontend/read_more_spec.js
+++ b/spec/frontend/read_more_spec.js
@@ -1,4 +1,3 @@
-import htmlProjectsOverview from 'test_fixtures/projects/overview.html';
 import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
 import initReadMore from '~/read_more';
 
@@ -11,7 +10,12 @@ describe('Read more click-to-expand functionality', () => {
 
   describe('expands target element', () => {
     beforeEach(() => {
-      setHTMLFixture(htmlProjectsOverview);
+      setHTMLFixture(`
+        <p class="read-more-container">Target</p>
+        <button type="button" class="js-read-more-trigger">
+          <span>Button text</span>
+        </button>
+      `);
     });
 
     it('adds "is-expanded" class to target element', () => {
diff --git a/spec/helpers/stat_anchors_helper_spec.rb b/spec/helpers/stat_anchors_helper_spec.rb
index f3830bf4172120d94bea1947c08ebe40ff963767..41ac7509c39f97030cee7147120c0b5a295b8d69 100644
--- a/spec/helpers/stat_anchors_helper_spec.rb
+++ b/spec/helpers/stat_anchors_helper_spec.rb
@@ -8,6 +8,10 @@
   describe '#stat_anchor_attrs' do
     subject { helper.stat_anchor_attrs(anchor) }
 
+    before do
+      stub_feature_flags(project_overview_reorg: false)
+    end
+
     context 'when anchor is a link' do
       let(:anchor) { anchor_klass.new(true) }
 
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index 48db41ea8e34403fa9eecbead572171e10820837..d7738023805b4717acc7e33cca4be6b001a5a793 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -428,6 +428,10 @@
     end
 
     describe '#new_file_anchor_data' do
+      before do
+        stub_feature_flags(project_overview_reorg: false)
+      end
+
       it 'returns new file data if user can push' do
         project.add_developer(user)
 
@@ -751,6 +755,7 @@
     subject(:empty_repo_statistics_buttons) { presenter.empty_repo_statistics_buttons }
 
     before do
+      stub_feature_flags(project_overview_reorg: false)
       allow(project).to receive(:auto_devops_enabled?).and_return(false)
     end
 
diff --git a/spec/views/projects/_files.html.haml_spec.rb b/spec/views/projects/_files.html.haml_spec.rb
index 96c6c2bdfab8d2f9b2010b483ffd8d051c0e7378..870d436ca888443f512e78f348a364dc5bdd434c 100644
--- a/spec/views/projects/_files.html.haml_spec.rb
+++ b/spec/views/projects/_files.html.haml_spec.rb
@@ -35,6 +35,8 @@
     before do
       allow(view).to receive(:current_user).and_return(user)
       allow(user).to receive(:project_shortcut_buttons).and_return(true)
+
+      stub_feature_flags(project_overview_reorg: false)
     end
 
     it 'renders buttons' do
@@ -45,6 +47,10 @@
   end
 
   context 'when rendered in the project overview page and there is no current user' do
+    before do
+      stub_feature_flags(project_overview_reorg: false)
+    end
+
     it 'renders buttons' do
       render(template, is_project_overview: true)
 
diff --git a/spec/views/projects/_home_panel.html.haml_spec.rb b/spec/views/projects/_home_panel.html.haml_spec.rb
index e5081df4c22610a0dc6e66dec3bd2f9ca0576395..a35c87cb4b33c53a81fd57bce0f645f40ea93f46 100644
--- a/spec/views/projects/_home_panel.html.haml_spec.rb
+++ b/spec/views/projects/_home_panel.html.haml_spec.rb
@@ -100,6 +100,8 @@
       allow(view).to receive(:current_user).and_return(user)
       allow(view).to receive(:can?).with(user, :read_project, project).and_return(false)
       allow(project).to receive(:license_anchor_data).and_return(false)
+
+      stub_feature_flags(project_overview_reorg: false)
     end
 
     context 'has no badges' do