diff --git a/app/models/ci/catalog/listing.rb b/app/models/ci/catalog/listing.rb
index e534b7d1a5c589a4fbf23d0a1741f9562b882c63..1485b58b5c6c8d62456e1926c949f30302bcea4f 100644
--- a/app/models/ci/catalog/listing.rb
+++ b/app/models/ci/catalog/listing.rb
@@ -21,8 +21,9 @@ def resources(sort: nil, search: nil, scope: :all)
         when 'latest_released_at_desc' then relation.order_by_latest_released_at_desc
         when 'latest_released_at_asc' then relation.order_by_latest_released_at_asc
         when 'created_at_asc' then relation.order_by_created_at_asc
+        when 'created_at_desc' then relation.order_by_created_at_desc
         else
-          relation.order_by_created_at_desc
+          relation.order_by_star_count(:desc)
         end
       end
 
diff --git a/app/models/ci/catalog/resource.rb b/app/models/ci/catalog/resource.rb
index 73f4356bdbfa094c924cf5ef24c0abfa6a53efbd..61d716e3b7f978b7146069d72cc6ffb95e848f65 100644
--- a/app/models/ci/catalog/resource.rb
+++ b/app/models/ci/catalog/resource.rb
@@ -10,6 +10,7 @@ module Catalog
     class Resource < ::ApplicationRecord
       include PgFullTextSearchable
       include Gitlab::VisibilityLevel
+      include Sortable
 
       self.table_name = 'catalog_resources'
 
@@ -35,6 +36,15 @@ class Resource < ::ApplicationRecord
       scope :order_by_name_asc, -> { reorder(arel_table[:name].asc.nulls_last) }
       scope :order_by_latest_released_at_desc, -> { reorder(arel_table[:latest_released_at].desc.nulls_last) }
       scope :order_by_latest_released_at_asc, -> { reorder(arel_table[:latest_released_at].asc.nulls_last) }
+      scope :order_by_star_count, ->(direction) do
+        build_keyset_order_on_joined_column(
+          scope: joins(:project),
+          attribute_name: 'project_star_count',
+          column: Project.arel_table[:star_count],
+          direction: direction,
+          nullable: :nulls_last
+        )
+      end
 
       delegate :avatar_path, :star_count, :full_path, to: :project
 
diff --git a/spec/models/ci/catalog/listing_spec.rb b/spec/models/ci/catalog/listing_spec.rb
index 356a0dcee67b3c3941b00f9e481afcf0d0ce91ff..07ac6c0f6ad4c1bfc761adf65a322a6b31554a3c 100644
--- a/spec/models/ci/catalog/listing_spec.rb
+++ b/spec/models/ci/catalog/listing_spec.rb
@@ -6,12 +6,21 @@
   let_it_be(:user) { create(:user) }
   let_it_be(:namespace) { create(:group) }
   let_it_be(:public_namespace_project) do
-    create(:project, :public, namespace: namespace, name: 'A public namespace project')
+    create(:project, :public, namespace: namespace, name: 'A public namespace project', star_count: 10)
+  end
+
+  let_it_be(:public_project) do
+    create(:project, :public, name: 'B public test project', star_count: 20)
+  end
+
+  let_it_be(:namespace_project_a) do
+    create(:project, namespace: namespace, name: 'Test namespace project', star_count: 30)
+  end
+
+  let_it_be(:namespace_project_b) do
+    create(:project, namespace: namespace, name: 'X namespace Project', star_count: 40)
   end
 
-  let_it_be(:public_project) { create(:project, :public, name: 'B public test project') }
-  let_it_be(:namespace_project_a) { create(:project, namespace: namespace, name: 'Test namespace project') }
-  let_it_be(:namespace_project_b) { create(:project, namespace: namespace, name: 'X namespace Project') }
   let_it_be(:project_noaccess) { create(:project, namespace: namespace, name: 'Project with no access') }
   let_it_be(:internal_project) { create(:project, :internal, name: 'Internal project') }
 
@@ -94,6 +103,14 @@
         internal_resource.update!(created_at: tomorrow + 1)
       end
 
+      context 'when there is no sort parameter' do
+        let_it_be(:sort) { nil }
+
+        it 'contains catalog resource sorted by star_count descending' do
+          is_expected.to eq([private_namespace_resource, public_resource_b, public_resource_a, internal_resource])
+        end
+      end
+
       context 'when the sort is created_at ascending' do
         let_it_be(:sort) { :created_at_asc }
 
diff --git a/spec/models/ci/catalog/resource_spec.rb b/spec/models/ci/catalog/resource_spec.rb
index 674d6476a610f175aa0e2807f0a9f3e2b03d1272..d20189050b969de9ba8a8e49c1c3c427ad905eef 100644
--- a/spec/models/ci/catalog/resource_spec.rb
+++ b/spec/models/ci/catalog/resource_spec.rb
@@ -5,9 +5,9 @@
 RSpec.describe Ci::Catalog::Resource, feature_category: :pipeline_composition do
   let_it_be(:current_user) { create(:user) }
 
-  let_it_be(:project_a) { create(:project, name: 'A') }
-  let_it_be(:project_b) { create(:project, name: 'B') }
-  let_it_be(:project_c) { create(:project, name: 'C', description: 'B') }
+  let_it_be(:project_a) { create(:project, name: 'A', star_count: 20) }
+  let_it_be(:project_b) { create(:project, name: 'B', star_count: 10) }
+  let_it_be(:project_c) { create(:project, name: 'C', description: 'B', star_count: 30) }
 
   let_it_be_with_reload(:resource_a) do
     create(:ci_catalog_resource, project: project_a, latest_released_at: '2023-02-01T00:00:00Z')
@@ -122,6 +122,22 @@
     end
   end
 
+  describe 'order_by_star_count_desc' do
+    it 'returns catalog resources sorted by project star count in descending order' do
+      ordered_resources = described_class.order_by_star_count(:desc)
+
+      expect(ordered_resources).to eq([resource_c, resource_a, resource_b])
+    end
+  end
+
+  describe 'order_by_star_count_asc' do
+    it 'returns catalog resources sorted by project star count in ascending order' do
+      ordered_resources = described_class.order_by_star_count(:asc)
+
+      expect(ordered_resources).to eq([resource_b, resource_a, resource_c])
+    end
+  end
+
   describe 'authorized catalog resources' do
     let_it_be(:namespace) { create(:group) }
     let_it_be(:other_namespace) { create(:group) }