diff --git a/kolibri/plugins/coach/assets/src/composables/useQuizResources.js b/kolibri/plugins/coach/assets/src/composables/useQuizResources.js
index 052ae64add..b243a8ca4e 100644
--- a/kolibri/plugins/coach/assets/src/composables/useQuizResources.js
+++ b/kolibri/plugins/coach/assets/src/composables/useQuizResources.js
@@ -128,11 +128,17 @@ export default function useQuizResources({ topicId } = {}) {
   }
 
   /** @returns {Boolean} Whether the given node should be displayed with a checkbox
-   * @description Returns whether the given node is an exercise or not -- although, could be
-   * extended in the future to permit topic-level selection if desired
+   *  @description Returns true for exercises and for topics that have no topic children and no
+   *  more children to load
    */
   function hasCheckbox(node) {
-    return node.kind === ContentNodeKinds.EXERCISE;
+    return (
+      node.kind === ContentNodeKinds.EXERCISE ||
+      // Has children, no more to load, and no children are topics
+      (node.children &&
+        !node.children.more &&
+        !node.children.results.some(c => c.kind === ContentNodeKinds.TOPIC))
+    );
   }
 
   function setResources(r) {
diff --git a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/ResourceSelection.vue b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/ResourceSelection.vue
index 8ac5bb5af5..d11589743b 100644
--- a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/ResourceSelection.vue
+++ b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/ResourceSelection.vue
@@ -50,6 +50,14 @@
         </div>
       </div>
 
+      <div
+        v-if="showTopicSizeWarning()"
+        class="shadow"
+        :style=" { padding: '1em', marginBottom: '1em', backgroundColor: $themePalette.grey.v_100 }"
+      >
+        {{ cannotSelectSomeTopicWarning$() }}
+      </div>
+
       <ResourceSelectionBreadcrumbs
         v-if="isTopicIdSet"
         :ancestors="topic.ancestors"
@@ -62,18 +70,19 @@
         @clear="clearSearchTerm"
         @searchterm="handleSearchTermChange"
       />
+
       <ContentCardList
         :contentList="contentList"
-        :showSelectAll="true"
+        :showSelectAll="showSelectAll"
         :viewMoreButtonState="viewMoreButtonState"
-        :selectAllChecked="isSelectAllChecked"
+        :selectAllChecked="selectAllChecked"
+        :selectAllIndeterminate="selectAllIndeterminate"
         :contentIsChecked="contentPresentInWorkingResourcePool"
         :contentHasCheckbox="hasCheckbox"
         :contentCardMessage="selectionMetadata"
         :contentCardLink="contentLink"
-        :selectAllIndeterminate="selectAllIndeterminate"
         :loadingMoreState="loadingMore"
-        @changeselectall="toggleTopicInWorkingResources"
+        @changeselectall="handleSelectAll"
         @change_content_card="toggleSelected"
         @moreresults="fetchMoreResources"
       />
@@ -154,6 +163,7 @@
         numberOfSelectedResources$,
         numberOfResources$,
         selectedResourcesInformation$,
+        cannotSelectSomeTopicWarning$,
       } = enhancedQuizManagementStrings;
 
       // TODO let's not use text for this
@@ -178,7 +188,29 @@
        * a list of unique resources to avoid unnecessary duplication
        */
       function addToWorkingResourcePool(resources = []) {
-        workingResourcePool.value = uniqWith([...workingResourcePool.value, ...resources], isEqual);
+        workingResourcePool.value = uniqWith(
+          [
+            ...workingResourcePool.value,
+            ...resources.filter(r => r.kind === ContentNodeKinds.EXERCISE),
+          ],
+          isEqual
+        );
+      }
+
+      /**
+       * @description Returns the list of Exercises which can possibly be selected from the current
+       * contentList taking into consideration the logic for whether a topic can be selected or not.
+       * @returns {QuizExercise[]} - All contents which can be selected
+       */
+      function selectableContentList() {
+        return contentList.value.reduce((newList, content) => {
+          if (content.kind === ContentNodeKinds.TOPIC && hasCheckbox(content)) {
+            newList = [...newList, ...content.children.results];
+          } else {
+            newList.push(content);
+          }
+          return newList;
+        }, []);
       }
 
       /**
@@ -202,6 +234,9 @@
        */
       function contentPresentInWorkingResourcePool(content) {
         const workingResourceIds = workingResourcePool.value.map(wr => wr.id);
+        if (content.kind === ContentNodeKinds.TOPIC) {
+          return content.children.results.every(child => workingResourceIds.includes(child.id));
+        }
         return workingResourceIds.includes(content.id);
       }
 
@@ -226,6 +261,63 @@
         });
       }
 
+      const selectAllChecked = computed(() => {
+        // Returns true if all the resources in the topic are in the working resource pool
+        const workingResourceIds = workingResourcePool.value.map(wr => wr.id);
+        const selectableIds = selectableContentList().map(content => content.id);
+        return selectableIds.every(id => workingResourceIds.includes(id));
+      });
+
+      const selectAllIndeterminate = computed(() => {
+        // Returns true if some, but not all, of the resources in the topic are in the working
+        // resource
+        const workingResourceIds = workingResourcePool.value.map(wr => wr.id);
+        const selectableIds = selectableContentList().map(content => content.id);
+        return !selectAllChecked.value && selectableIds.some(id => workingResourceIds.includes(id));
+      });
+
+      const showSelectAll = computed(() => {
+        return contentList.value.every(content => hasCheckbox(content));
+      });
+
+      function handleSelectAll(isChecked) {
+        if (isChecked) {
+          this.addToWorkingResourcePool(selectableContentList());
+        } else {
+          this.contentList.forEach(content => {
+            var contentToRemove = [];
+            if (content.kind === ContentNodeKinds.TOPIC) {
+              contentToRemove = content.children.results;
+            } else {
+              contentToRemove.push(content);
+            }
+            contentToRemove.forEach(c => {
+              this.removeFromWorkingResourcePool(c);
+            });
+          });
+        }
+      }
+
+      /**
+       * @param {Object} param
+       * @param {ContentNode} param.content
+       * @param {boolean} param.checked
+       * @affects workingResourcePool - Adds or removes the content from the workingResourcePool
+       * When given a topic, it adds or removes all the exercises in the topic from the
+       * workingResourcePool. This assumes that topics which should not be added are not able to
+       * be checked and does not do any additional checks.
+       */
+      function toggleSelected({ content, checked }) {
+        content = content.kind === ContentNodeKinds.TOPIC ? content.children.results : [content];
+        if (checked) {
+          this.addToWorkingResourcePool(content);
+        } else {
+          content.forEach(c => {
+            this.removeFromWorkingResourcePool(c);
+          });
+        }
+      }
+
       const {
         hasCheckbox,
         topic,
@@ -341,6 +433,11 @@
       }
 
       return {
+        selectAllChecked,
+        selectAllIndeterminate,
+        showSelectAll,
+        handleSelectAll,
+        toggleSelected,
         topic,
         topicId,
         contentList,
@@ -353,6 +450,7 @@
         resetWorkingResourcePool,
         contentPresentInWorkingResourcePool,
         //contentList,
+        cannotSelectSomeTopicWarning$,
         sectionSettings$,
         selectFromBookmarks$,
         numberOfSelectedBookmarks$,
@@ -382,20 +480,6 @@
       isTopicIdSet() {
         return this.$route.params.topic_id;
       },
-      isSelectAllChecked() {
-        // Returns true if all the resources in the topic are in the working resource pool
-        const workingResourceIds = this.workingResourcePool.map(wr => wr.id);
-        return this.contentList.every(content => workingResourceIds.includes(content.id));
-      },
-      selectAllIndeterminate() {
-        // Returns true if some, but not all, of the resources in the topic are in the working
-        // resource
-        const workingResourceIds = this.workingResourcePool.map(wr => wr.id);
-        return (
-          !this.isSelectAllChecked &&
-          this.contentList.some(content => workingResourceIds.includes(content.id))
-        );
-      },
 
       getBookmarksLink() {
         // Inject the showBookmarks parameter so that
@@ -423,6 +507,12 @@
       },
     },
     methods: {
+      showTopicSizeWarningCard(content) {
+        return !this.hasCheckbox(content) && content.kind === ContentNodeKinds.TOPIC;
+      },
+      showTopicSizeWarning() {
+        return this.contentList.some(this.showTopicSizeWarningCard);
+      },
       /** @public */
       focusFirstEl() {
         this.$refs.textbox.focus();
@@ -446,22 +536,6 @@
 
         return {}; // or return {} if you prefer an empty object
       },
-      toggleSelected({ content, checked }) {
-        if (checked) {
-          this.addToWorkingResourcePool([content]);
-        } else {
-          this.removeFromWorkingResourcePool(content);
-        }
-      },
-      toggleTopicInWorkingResources(isChecked) {
-        if (isChecked) {
-          this.addToWorkingResourcePool(this.contentList);
-        } else {
-          this.contentList.forEach(content => {
-            this.removeFromWorkingResourcePool(content);
-          });
-        }
-      },
       topicListingLink({ topicId }) {
         return this.$router.getRoute(
           PageNames.QUIZ_SELECT_RESOURCES,
@@ -607,4 +681,9 @@
     margin-top: 2em;
   }
 
+  .shadow {
+    box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14),
+      0 2px 1px -1px rgba(0, 0, 0, 0.12);
+  }
+
 </style>
diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/ContentCardList.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/ContentCardList.vue
index d0dfd643cc..ffc72b8e6c 100644
--- a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/ContentCardList.vue
+++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/ContentCardList.vue
@@ -33,7 +33,11 @@
           :link="contentCardLink(content)"
           :numCoachContents="content.num_coach_contents"
           :isLeaf="content.is_leaf"
-        />
+        >
+          <template #notice>
+            <slot name="notice" :content="content"></slot>
+          </template>
+        </LessonContentCard>
       </li>
     </ul>
 
diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/index.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/index.vue
index c64bf7f18c..e3ed3035d4 100644
--- a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/index.vue
+++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/index.vue
@@ -52,6 +52,7 @@
           :isTopic="isTopic"
         />
       </div>
+      <slot name="notice"></slot>
     </div>
 
   </router-link>
diff --git a/packages/kolibri-common/strings/enhancedQuizManagementStrings.js b/packages/kolibri-common/strings/enhancedQuizManagementStrings.js
index 039a606f14..6cb7297274 100644
--- a/packages/kolibri-common/strings/enhancedQuizManagementStrings.js
+++ b/packages/kolibri-common/strings/enhancedQuizManagementStrings.js
@@ -154,4 +154,8 @@ export const enhancedQuizManagementStrings = createTranslator('EnhancedQuizManag
     message:
       '{count, number, integer} of {total, number, integer} {total, plural, one {resource selected} other {resources selected}}',
   },
+  cannotSelectSomeTopicWarning: {
+    message:
+      'You can only select folders with 12 or less exercises and no subfolders to avoid oversized quizzes.',
+  },
 });