diff --git a/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue b/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue
index 42f8cea872709450e04b97a415354ac536b759b8..355b4f71d99cb891f5bc69898ecb65de93015ccd 100644
--- a/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue
+++ b/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue
@@ -8,6 +8,7 @@ import { CI_RESOURCE_DETAILS_PAGE_NAME } from '../../router/constants';
 
 export default {
   i18n: {
+    components: s__('CiCatalog|Components:'),
     unreleased: s__('CiCatalog|Unreleased'),
     releasedMessage: s__('CiCatalog|Released %{timeAgo} by %{author}'),
   },
@@ -34,8 +35,12 @@ export default {
     authorProfileUrl() {
       return this.latestVersion.author.webUrl;
     },
-    resourceId() {
-      return cleanLeadingSeparator(this.resource.webPath);
+    componentNames() {
+      const components = this.resource.latestVersion?.components?.nodes;
+      return components?.map((component) => component.name).join(', ') || null;
+    },
+    detailsPageHref() {
+      return decodeURIComponent(this.detailsPageResolved.href);
     },
     detailsPageResolved() {
       return this.$router.resolve({
@@ -43,32 +48,35 @@ export default {
         params: { id: this.resourceId },
       });
     },
-    detailsPageHref() {
-      return decodeURIComponent(this.detailsPageResolved.href);
-    },
     entityId() {
       return getIdFromGraphQLId(this.resource.id);
     },
-    starCount() {
-      return this.resource?.starCount || 0;
+    formattedDate() {
+      return formatDate(this.latestVersion?.releasedAt);
     },
-    starCountText() {
-      return n__('Star', 'Stars', this.starCount);
+    hasComponents() {
+      return Boolean(this.componentNames);
     },
     hasReleasedVersion() {
       return Boolean(this.latestVersion?.releasedAt);
     },
-    formattedDate() {
-      return formatDate(this.latestVersion?.releasedAt);
-    },
     latestVersion() {
       return this.resource?.latestVersion || {};
     },
+    name() {
+      return this.latestVersion?.name || this.$options.i18n.unreleased;
+    },
     releasedAt() {
       return getTimeago().format(this.latestVersion?.releasedAt);
     },
-    name() {
-      return this.latestVersion?.name || this.$options.i18n.unreleased;
+    resourceId() {
+      return cleanLeadingSeparator(this.resource.webPath);
+    },
+    starCount() {
+      return this.resource?.starCount || 0;
+    },
+    starCountText() {
+      return n__('Star', 'Stars', this.starCount);
     },
     webPath() {
       return cleanLeadingSeparator(this.resource?.webPath);
@@ -152,6 +160,14 @@ export default {
           </span>
         </div>
       </div>
+      <div
+        v-if="hasComponents"
+        data-testid="ci-resource-component-names"
+        class="gl-font-sm gl-mt-1"
+      >
+        <span class="gl-font-weight-bold"> &#8226; {{ $options.i18n.components }} </span>
+        <span class="gl-text-gray-900">{{ componentNames }}</span>
+      </div>
     </div>
   </li>
 </template>
diff --git a/app/assets/javascripts/ci/catalog/graphql/fragments/catalog_resource.fragment.graphql b/app/assets/javascripts/ci/catalog/graphql/fragments/catalog_resource.fragment.graphql
index 316308e96d7ea2174f06d40686542db4b97584b7..252bd6a574391b1dcd0f4ed821dedb559cbc15c3 100644
--- a/app/assets/javascripts/ci/catalog/graphql/fragments/catalog_resource.fragment.graphql
+++ b/app/assets/javascripts/ci/catalog/graphql/fragments/catalog_resource.fragment.graphql
@@ -7,6 +7,12 @@ fragment CatalogResourceFields on CiCatalogResource {
   starCount
   latestVersion {
     id
+    components {
+      nodes {
+        id
+        name
+      }
+    }
     name
     path
     releasedAt
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d5d92d162084f75718339a361e8518a53b629b40..65515894d7036d4e5584b86ad305f4d37970ef87 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -10484,6 +10484,9 @@ msgstr ""
 msgid "CiCatalog|Components"
 msgstr ""
 
+msgid "CiCatalog|Components:"
+msgstr ""
+
 msgid "CiCatalog|Create a pipeline component repository and make reusing pipeline configurations faster and easier."
 msgstr ""
 
diff --git a/spec/frontend/ci/catalog/components/list/ci_resources_list_item_spec.js b/spec/frontend/ci/catalog/components/list/ci_resources_list_item_spec.js
index 15add3f307ff8ec1ed93817250dfbb78c7d67a62..67d12b88b6aa716ea4ac3b3a33c6bf609c0342ab 100644
--- a/spec/frontend/ci/catalog/components/list/ci_resources_list_item_spec.js
+++ b/spec/frontend/ci/catalog/components/list/ci_resources_list_item_spec.js
@@ -18,6 +18,20 @@ describe('CiResourcesListItem', () => {
 
   const router = createRouter();
   const resource = catalogSinglePageResponse.data.ciCatalogResources.nodes[0];
+  const componentList = {
+    components: {
+      nodes: [
+        {
+          id: 'gid://gitlab/Ci::Catalog::Resources::Component/2',
+          name: 'test-component',
+        },
+        {
+          id: 'gid://gitlab/Ci::Catalog::Resources::Component/1',
+          name: 'component_two',
+        },
+      ],
+    },
+  };
   const release = {
     author: { name: 'author', webUrl: '/user/1' },
     releasedAt: Date.now(),
@@ -42,6 +56,7 @@ describe('CiResourcesListItem', () => {
 
   const findAvatar = () => wrapper.findComponent(GlAvatar);
   const findBadge = () => wrapper.findComponent(GlBadge);
+  const findComponentNames = () => wrapper.findByTestId('ci-resource-component-names');
   const findResourceName = () => wrapper.findByTestId('ci-resource-link');
   const findResourceDescription = () => wrapper.findByText(defaultProps.resource.description);
   const findUserLink = () => wrapper.findByTestId('user-link');
@@ -82,6 +97,35 @@ describe('CiResourcesListItem', () => {
     });
   });
 
+  describe('components', () => {
+    describe('when there are no components', () => {
+      beforeEach(() => {
+        createComponent({ props: { resource: { ...resource, latestVersion: null } } });
+      });
+
+      it('does not render the component names', () => {
+        expect(findComponentNames().exists()).toBe(false);
+      });
+    });
+
+    describe('when there are components', () => {
+      beforeEach(() => {
+        createComponent({
+          props: { resource: { ...resource, latestVersion: { ...componentList, ...release } } },
+        });
+      });
+
+      it('renders the component name template', () => {
+        expect(findComponentNames().exists()).toBe(true);
+      });
+
+      it('renders the correct component names', () => {
+        expect(findComponentNames().text()).toContain(componentList.components.nodes[0].name);
+        expect(findComponentNames().text()).toContain(componentList.components.nodes[1].name);
+      });
+    });
+  });
+
   describe('release time', () => {
     describe('when there is no release data', () => {
       beforeEach(() => {
diff --git a/spec/frontend/ci/catalog/mock.js b/spec/frontend/ci/catalog/mock.js
index c92564359901fa380f808e100e9d907cf025a923..2aac033b529f31eed027deae888d5de493587420 100644
--- a/spec/frontend/ci/catalog/mock.js
+++ b/spec/frontend/ci/catalog/mock.js
@@ -1,3 +1,49 @@
+const componentsDetailsMockData = {
+  __typename: 'CiComponentConnection',
+  nodes: [
+    {
+      id: 'gid://gitlab/Ci::Component/1',
+      name: 'Ruby gal',
+      description: 'This is a pretty amazing component that does EVERYTHING ruby.',
+      includePath: 'gitlab.com/gitlab-org/ruby-gal@~latest',
+      inputs: [{ name: 'version', default: '1.0.0', required: true }],
+    },
+    {
+      id: 'gid://gitlab/Ci::Component/2',
+      name: 'Javascript madness',
+      description: 'Adds some spice to your life.',
+      includePath: 'gitlab.com/gitlab-org/javascript-madness@~latest',
+      inputs: [
+        { name: 'isFun', default: 'true', required: true },
+        { name: 'RandomNumber', default: '10', required: false },
+      ],
+    },
+    {
+      id: 'gid://gitlab/Ci::Component/3',
+      name: 'Go go go',
+      description: 'When you write Go, you gotta go go go.',
+      includePath: 'gitlab.com/gitlab-org/go-go-go@~latest',
+      inputs: [{ name: 'version', default: '1.0.0', required: true }],
+    },
+  ],
+};
+
+const componentsListMockData = {
+  nodes: [
+    {
+      id: 'gid://gitlab/Ci::Catalog::Resources::Component/2',
+      name: 'test-component',
+      __typename: 'CiCatalogResourceComponent',
+    },
+    {
+      id: 'gid://gitlab/Ci::Catalog::Resources::Component/1',
+      name: 'component_two',
+      __typename: 'CiCatalogResourceComponent',
+    },
+  ],
+  __typename: 'CiCatalogResourceComponentConnection',
+};
+
 export const emptyCatalogResponseBody = {
   data: {
     ciCatalogResources: {
@@ -268,7 +314,13 @@ export const catalogSinglePageResponse = {
           name: 'Project-45 Name',
           description: 'A simple component',
           starCount: 0,
-          latestVersion: null,
+          latestVersion: {
+            id: 'gid://gitlab/Ci::Catalog::Resources::Version/2',
+            components: {
+              ...componentsListMockData,
+            },
+            __typename: 'CiCatalogResourceVersion',
+          },
           webPath: '/frontend-fixtures/project-45',
           __typename: 'CiCatalogResource',
         },
@@ -310,6 +362,7 @@ export const catalogSharedDataMock = {
       latestVersion: {
         __typename: 'Release',
         id: '3',
+        components: componentsListMockData,
         name: '1.0.0',
         path: 'path/to/release',
         releasedAt: Date.now(),
@@ -378,6 +431,9 @@ const generateResourcesNodes = (count = 20, startId = 0) => {
       latestVersion: {
         __typename: 'Release',
         id: '3',
+        components: {
+          ...componentsListMockData,
+        },
         name: '1.0.0',
         path: 'path/to/release',
         releasedAt: Date.now(),
@@ -392,36 +448,6 @@ const generateResourcesNodes = (count = 20, startId = 0) => {
 
 export const mockCatalogResourceItem = generateResourcesNodes(1)[0];
 
-const componentsMockData = {
-  __typename: 'CiComponentConnection',
-  nodes: [
-    {
-      id: 'gid://gitlab/Ci::Component/1',
-      name: 'Ruby gal',
-      description: 'This is a pretty amazing component that does EVERYTHING ruby.',
-      includePath: 'gitlab.com/gitlab-org/ruby-gal@~latest',
-      inputs: [{ name: 'version', default: '1.0.0', required: true }],
-    },
-    {
-      id: 'gid://gitlab/Ci::Component/2',
-      name: 'Javascript madness',
-      description: 'Adds some spice to your life.',
-      includePath: 'gitlab.com/gitlab-org/javascript-madness@~latest',
-      inputs: [
-        { name: 'isFun', default: 'true', required: true },
-        { name: 'RandomNumber', default: '10', required: false },
-      ],
-    },
-    {
-      id: 'gid://gitlab/Ci::Component/3',
-      name: 'Go go go',
-      description: 'When you write Go, you gotta go go go.',
-      includePath: 'gitlab.com/gitlab-org/go-go-go@~latest',
-      inputs: [{ name: 'version', default: '1.0.0', required: true }],
-    },
-  ],
-};
-
 export const mockComponents = {
   data: {
     ciCatalogResource: {
@@ -431,7 +457,7 @@ export const mockComponents = {
       latestVersion: {
         id: 'gid://gitlab/Version/1',
         components: {
-          ...componentsMockData,
+          ...componentsDetailsMockData,
         },
       },
     },