diff --git a/ee/app/assets/javascripts/iterations/components/iterations.vue b/ee/app/assets/javascripts/iterations/components/iterations.vue
index 892b8fbb451c5a1e2449c062b09c441d27fbf881..a98d22e607fab1d66a321617e0a0c0d3537e30b3 100644
--- a/ee/app/assets/javascripts/iterations/components/iterations.vue
+++ b/ee/app/assets/javascripts/iterations/components/iterations.vue
@@ -17,7 +17,7 @@ export default {
     GlTabs,
   },
   props: {
-    groupPath: {
+    fullPath: {
       type: String,
       required: true,
     },
@@ -33,7 +33,7 @@ export default {
     },
   },
   apollo: {
-    group: {
+    namespace: {
       query: GroupIterationQuery,
       variables() {
         return this.queryVariables;
@@ -51,7 +51,7 @@ export default {
   },
   data() {
     return {
-      group: {
+      namespace: {
         iterations: [],
         pageInfo: {
           hasNextPage: true,
@@ -68,7 +68,7 @@ export default {
   computed: {
     queryVariables() {
       const vars = {
-        fullPath: this.groupPath,
+        fullPath: this.fullPath,
         state: this.state,
       };
 
@@ -83,10 +83,10 @@ export default {
       return vars;
     },
     iterations() {
-      return this.group.iterations;
+      return this.namespace.iterations;
     },
     loading() {
-      return this.$apollo.queries.group.loading;
+      return this.$apollo.queries.namespace.loading;
     },
     state() {
       switch (this.tabIndex) {
@@ -100,15 +100,15 @@ export default {
       }
     },
     prevPage() {
-      return Number(this.group.pageInfo.hasPreviousPage);
+      return Number(this.namespace.pageInfo.hasPreviousPage);
     },
     nextPage() {
-      return Number(this.group.pageInfo.hasNextPage);
+      return Number(this.namespace.pageInfo.hasNextPage);
     },
   },
   methods: {
     handlePageChange(page) {
-      const { startCursor, endCursor } = this.group.pageInfo;
+      const { startCursor, endCursor } = this.namespace.pageInfo;
 
       if (page > this.pagination.currentPage) {
         this.pagination = {
diff --git a/ee/app/assets/javascripts/iterations/index.js b/ee/app/assets/javascripts/iterations/index.js
index a6211f082c1be664a141db63e641ffeb9e2d3f05..b0bb365a1da668cbcb8eb215f50e31485d9219f7 100644
--- a/ee/app/assets/javascripts/iterations/index.js
+++ b/ee/app/assets/javascripts/iterations/index.js
@@ -21,7 +21,7 @@ export function initIterationsList() {
     render(createElement) {
       return createElement(Iterations, {
         props: {
-          groupPath: el.dataset.groupFullPath,
+          fullPath: el.dataset.fullPath,
           canAdmin: parseBoolean(el.dataset.canAdmin),
           newIterationPath: el.dataset.newIterationPath,
         },
diff --git a/ee/app/assets/javascripts/pages/projects/iterations/index.js b/ee/app/assets/javascripts/pages/projects/iterations/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..07f607e37fed125b58b90990c97e496d84633a97
--- /dev/null
+++ b/ee/app/assets/javascripts/pages/projects/iterations/index.js
@@ -0,0 +1,3 @@
+import { initIterationsList } from 'ee/iterations';
+
+document.addEventListener('DOMContentLoaded', initIterationsList);
diff --git a/ee/app/views/groups/iterations/index.html.haml b/ee/app/views/groups/iterations/index.html.haml
index 87b395b030372ff11555335497713bc610f00665..c1fb6195c7a119f3c94ab6da310d8b57e4da98f1 100644
--- a/ee/app/views/groups/iterations/index.html.haml
+++ b/ee/app/views/groups/iterations/index.html.haml
@@ -1,4 +1,4 @@
 - page_title _("Iterations")
 
 - if Feature.enabled?(:group_iterations, @group, default_enabled: true)
-  .js-iterations-list{ data: { group_full_path: @group.full_path, can_admin: can?(current_user, :create_iteration, @group).to_s, new_iteration_path: new_group_iteration_path(@group) } }
+  .js-iterations-list{ data: { full_path: @group.full_path, can_admin: can?(current_user, :create_iteration, @group).to_s, new_iteration_path: new_group_iteration_path(@group) } }
diff --git a/ee/app/views/layouts/nav/sidebar/_project_iterations_link.html.haml b/ee/app/views/layouts/nav/sidebar/_project_iterations_link.html.haml
index 34396a056c9f385f2b8952d525c97ac870c7a059..f388bd1d77606f6c6fe8fa093d3c2dc31ac184b2 100644
--- a/ee/app/views/layouts/nav/sidebar/_project_iterations_link.html.haml
+++ b/ee/app/views/layouts/nav/sidebar/_project_iterations_link.html.haml
@@ -1,4 +1,4 @@
-- return unless Feature.enabled?(:project_iterations, @project.group, default_enabled: false)
+- return unless Feature.enabled?(:project_iterations, @project.group)
 - return unless @project.feature_available?(:iterations)
 - return unless can?(current_user, :read_iteration, @project)
 
diff --git a/ee/app/views/projects/iterations/index.html.haml b/ee/app/views/projects/iterations/index.html.haml
index e706be9ac9039513af26efee3bd2ba9cb07a988f..e8a5a6ced555187978446a56b2abc7cfbbb45337 100644
--- a/ee/app/views/projects/iterations/index.html.haml
+++ b/ee/app/views/projects/iterations/index.html.haml
@@ -1 +1,4 @@
 - page_title _("Iterations")
+
+- if Feature.enabled?(:project_iterations, @project.group)
+  .js-iterations-list{ data: { full_path: @project.group.full_path } }
diff --git a/ee/spec/features/projects/iterations/iterations_list_spec.rb b/ee/spec/features/projects/iterations/iterations_list_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..48ac66a23e36ccb0b40536c3f4ad8ec7a892f9ab
--- /dev/null
+++ b/ee/spec/features/projects/iterations/iterations_list_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Iterations list', :js do
+  let(:now) { Time.now }
+  let_it_be(:group) { create(:group) }
+  let_it_be(:project) { create(:project, :public, group: group) }
+  let_it_be(:user) { create(:user) }
+  let!(:started_iteration) { create(:iteration, :skip_future_date_validation, group: group, start_date: now - 1.day, due_date: now) }
+  let!(:upcoming_iteration) { create(:iteration, group: group, start_date: now + 1.day, due_date: now + 2.days) }
+  let!(:closed_iteration) { create(:closed_iteration, :skip_future_date_validation, group: group, start_date: now - 3.days, due_date: now - 2.days) }
+
+  context 'as guest' do
+    before do
+      visit project_iterations_path(project)
+    end
+
+    it 'shows iterations on each tab' do
+      expect(page).to have_link(started_iteration.title)
+      expect(page).to have_link(upcoming_iteration.title)
+      expect(page).not_to have_link(closed_iteration.title)
+
+      click_link('Closed')
+
+      expect(page).to have_link(closed_iteration.title)
+      expect(page).not_to have_link(started_iteration.title)
+      expect(page).not_to have_link(upcoming_iteration.title)
+
+      click_link('All')
+
+      expect(page).to have_link(started_iteration.title)
+      expect(page).to have_link(upcoming_iteration.title)
+      expect(page).to have_link(closed_iteration.title)
+    end
+  end
+
+  context 'as authorized user' do
+    before do
+      project.add_developer(user)
+      sign_in(user)
+      visit project_iterations_path(project)
+    end
+
+    it 'does not show "New iteration" button' do
+      expect(page).not_to have_link('New iteration')
+    end
+  end
+end
diff --git a/ee/spec/frontend/iterations/components/iterations_spec.js b/ee/spec/frontend/iterations/components/iterations_spec.js
index dda0f0a766037acd4222b433829e944d24bec6ff..889e8dabe2a3aaf77fca12672f74d94bda1db184 100644
--- a/ee/spec/frontend/iterations/components/iterations_spec.js
+++ b/ee/spec/frontend/iterations/components/iterations_spec.js
@@ -6,7 +6,7 @@ import { GlAlert, GlLoadingIcon, GlPagination, GlTab, GlTabs } from '@gitlab/ui'
 describe('Iterations tabs', () => {
   let wrapper;
   const defaultProps = {
-    groupPath: 'gitlab-org',
+    fullPath: 'gitlab-org',
   };
 
   const mountComponent = ({ props = defaultProps, loading = false } = {}) => {
@@ -14,7 +14,7 @@ describe('Iterations tabs', () => {
       propsData: props,
       mocks: {
         $apollo: {
-          queries: { group: { loading } },
+          queries: { namespace: { loading } },
         },
       },
       stubs: {
@@ -74,7 +74,7 @@ describe('Iterations tabs', () => {
         loading: false,
       });
       wrapper.setData({
-        group: {
+        namespace: {
           pageInfo: {
             hasNextPage: true,
             hasPreviousPage: false,
@@ -102,7 +102,7 @@ describe('Iterations tabs', () => {
       expect(wrapper.vm.queryVariables).toEqual({
         beforeCursor: 'first-item',
         lastPageSize: 20,
-        fullPath: defaultProps.groupPath,
+        fullPath: defaultProps.fullPath,
         state: 'opened',
       });
     });
@@ -113,7 +113,7 @@ describe('Iterations tabs', () => {
       expect(wrapper.vm.queryVariables).toEqual({
         afterCursor: 'last-item',
         firstPageSize: 20,
-        fullPath: defaultProps.groupPath,
+        fullPath: defaultProps.fullPath,
         state: 'opened',
       });
     });