diff --git a/aleksis/apps/cursus/apps.py b/aleksis/apps/cursus/apps.py
index ba7bf20152de28ca8df9fabe8a80506b643af1d8..2100153526771424e6b04addd6bc55b3baa2d960 100644
--- a/aleksis/apps/cursus/apps.py
+++ b/aleksis/apps/cursus/apps.py
@@ -11,12 +11,3 @@ class DefaultConfig(AppConfig):
     }
     licence = "EUPL-1.2+"
     copyright_info = (([2023], "Jonathan Weth", "dev@jonathanweth.de"),)
-
-    def _maintain_default_data(self):
-        super()._maintain_default_data()
-
-        # Ensure that default group types for school structure exist
-        from .util.group_types import get_school_class_group_type, get_school_grade_group_type
-
-        get_school_grade_group_type()
-        get_school_class_group_type()
diff --git a/aleksis/apps/cursus/frontend/components/SchoolStructure.vue b/aleksis/apps/cursus/frontend/components/SchoolStructure.vue
index 4ebb93ee5cc6aabba652e35b4d594d63eb5c7f7b..37dfe21c881958a6b09e5427c0716648ef814e0a 100644
--- a/aleksis/apps/cursus/frontend/components/SchoolStructure.vue
+++ b/aleksis/apps/cursus/frontend/components/SchoolStructure.vue
@@ -7,31 +7,48 @@ import SchoolTermField from "aleksis.core/components/school_term/SchoolTermField
 
 <template>
   <v-card>
-    <!-- Create grade form -->
+    <!-- Create first level group form -->
     <dialog-object-form
-      v-model="createGradeForm"
-      :fields="createGradeFields"
-      :default-item="createGradeDefaultItem"
+      v-model="createFirstLevelGroupForm"
+      :fields="firstLevelGroupFields"
+      :default-item="firstLevelGroupDefaultItem"
       :is-create="true"
-      create-item-i18n-key="cursus.school_structure.add_grade"
-      :gql-create-mutation="gqlCreateGrades"
-      :get-create-data="transformCreateGradeItem"
-      @cancel="createGradeForm = false"
+      :gql-create-mutation="gqlCreateFirstLevelGroup"
+      :get-create-data="transformFirstLevelGroupItem"
+      @cancel="createFirstLevelGroupForm = false"
       @save="updateSchoolStructure"
-    />
-    <!-- Create class form -->
+    >
+      <template #title>
+        <span class="text-h5">
+          {{
+            $t("cursus.school_structure.add_title", {
+              name: schoolStructure.firstLevelType.name,
+            })
+          }}
+        </span>
+      </template>
+    </dialog-object-form>
+    <!-- Create second level group form -->
     <dialog-object-form
-      v-model="createClassForm"
-      :fields="createClassFields"
-      :default-item="createClassDefaultItem"
+      v-model="createSecondLevelGroupForm"
+      :fields="secondLevelGroupFields"
+      :default-item="secondLevelGroupDefaultItem"
       :is-create="true"
-      create-item-i18n-key="cursus.school_structure.add_class"
-      :gql-create-mutation="gqlCreateClasses"
-      :get-create-data="transformCreateClassItemForGrade"
-      @cancel="createClassForm = false"
+      :gql-create-mutation="gqlCreateSecondLevelGroup"
+      :get-create-data="transformSecondLevelGroupItem"
+      @cancel="createFirstLevelGroupForm = false"
       @save="updateSchoolStructure"
     >
-      <!-- Hide parentGroups field - it is set on grade -->
+      <template #title>
+        <span class="text-h5">
+          {{
+            $t("cursus.school_structure.add_title", {
+              name: schoolStructure.secondLevelType.name,
+            })
+          }}
+        </span>
+      </template>
+      <!-- Hide parentGroups field - it is set on first level group -->
       <!-- eslint-disable-next-line vue/valid-v-slot -->
       <template #parentGroups.field="{ on, attrs }">
         <input type="hidden" v-bind="attrs" v-on="on" />
@@ -52,19 +69,27 @@ import SchoolTermField from "aleksis.core/components/school_term/SchoolTermField
         <v-card-actions>
           <create-button
             v-if="this.$data.currentTerm"
-            i18n-key="cursus.school_structure.add_grade"
-            @click="createGrade"
-          />
+            @click="createFirstLevelGroup"
+          >
+            <v-icon left>$plus</v-icon>
+            {{
+              $t("cursus.school_structure.add", {
+                name: schoolStructure.firstLevelType.name,
+              })
+            }}
+          </create-button>
         </v-card-actions>
       </div>
     </div>
-    <!-- Grades -->
+    <!-- First level groups -->
     <v-container v-if="this.$data.currentTerm">
       <v-row class="overflow-x-auto flex-nowrap slide-n-snap-x-container">
         <!-- responsive 1, 2, 3, 4 col layout -->
         <v-col
-          v-for="grade in grades"
-          :key="grade.id"
+          v-for="firstGroup in schoolStructure
+            ? schoolStructure.firstLevelGroupsByTerm
+            : []"
+          :key="firstGroup.id"
           class="slide-n-snap-contained"
           cols="12"
           sm="6"
@@ -74,27 +99,26 @@ import SchoolTermField from "aleksis.core/components/school_term/SchoolTermField
         >
           <v-card>
             <v-card-title class="justify-end">
-              {{ $t("cursus.school_structure.grade") }}
-              <span class="ml-3 text-h4">{{ grade.shortName }}</span>
+              {{ schoolStructure.firstLevelType.name }}
+              <span class="ml-3 text-h4">{{ firstGroup.shortName }}</span>
             </v-card-title>
             <v-list
               :max-height="$vuetify.breakpoint.height - 333"
               class="overflow-y-auto slide-n-snap-y-container"
             >
-              <!-- class is a "forbidden" name in v-for -->
               <v-list-item
-                v-for="clas in grade.childGroups"
-                :key="clas.id"
+                v-for="secondGroup in firstGroup.childGroups"
+                :key="secondGroup.id"
                 class="slide-n-snap-contained"
               >
                 <v-card class="mx-3 my-2">
                   <div class="d-flex flex-nowrap justify-space-between">
                     <div>
                       <v-card-title class="text-h4">
-                        {{ clas.shortName }}
+                        {{ secondGroup.shortName }}
                       </v-card-title>
                       <v-card-subtitle>
-                        {{ clas.name }}
+                        {{ secondGroup.name }}
                       </v-card-subtitle>
                     </div>
                     <div>
@@ -104,15 +128,15 @@ import SchoolTermField from "aleksis.core/components/school_term/SchoolTermField
                         class="px-2"
                       >
                         <v-chip
-                          v-for="teacher in clas.owners"
+                          v-for="teacher in secondGroup.owners"
                           :key="teacher.id"
                           :to="{
                             name: 'core.personById',
                             params: { id: teacher.id },
                           }"
-                          :outlined="true"
+                          outlined
                         >
-                          {{ teacher.shortName }}
+                          {{ teacher.shortName || teacher.lastName }}
                         </v-chip>
                       </v-chip-group>
                       <v-card-actions>
@@ -120,7 +144,7 @@ import SchoolTermField from "aleksis.core/components/school_term/SchoolTermField
                           i18n-key="cursus.school_structure.timetable"
                           :to="{
                             name: 'lesrooster.timetable_management',
-                            params: { id: clas.id },
+                            params: { id: secondGroup.id },
                           }"
                         />
                       </v-card-actions>
@@ -133,10 +157,16 @@ import SchoolTermField from "aleksis.core/components/school_term/SchoolTermField
               <v-spacer />
               <!-- MAYBE: ADD PLAN COURSES LINK -->
               <create-button
-                i18n-key="cursus.school_structure.add_class"
                 color="secondary"
-                @click="createClass(grade.id)"
-              />
+                @click="createSecondLevelGroup(firstGroup.id)"
+              >
+                <v-icon left>$plus</v-icon>
+                {{
+                  $t("cursus.school_structure.add", {
+                    name: schoolStructure.secondLevelType.name,
+                  })
+                }}
+              </create-button>
             </v-card-actions>
           </v-card>
         </v-col>
@@ -147,38 +177,38 @@ import SchoolTermField from "aleksis.core/components/school_term/SchoolTermField
 
 <script>
 import {
-  gqlSchoolGrades,
-  gqlCreateGrades,
-  gqlCreateClasses,
+  gqlFirstLevelGroups,
+  gqlCreateFirstLevelGroup,
+  gqlCreateSecondLevelGroup,
 } from "./schoolStructure.graphql";
 
 export default {
   name: "SchoolStructure",
   data() {
     return {
-      createGradeForm: false,
-      createGradeFields: [
+      createFirstLevelGroupForm: false,
+      firstLevelGroupFields: [
         {
-          text: this.$t("cursus.school_structure.grade_fields.name"),
+          text: this.$t("cursus.school_structure.fields.name"),
           value: "name",
         },
         {
-          text: this.$t("cursus.school_structure.grade_fields.short_name"),
+          text: this.$t("cursus.school_structure.fields.short_name"),
           value: "shortName",
         },
       ],
-      createGradeDefaultItem: {
+      firstLevelGroupDefaultItem: {
         name: "",
         shortName: "",
       },
-      createClassForm: false,
-      createClassFields: [
+      createSecondLevelGroupForm: false,
+      secondLevelGroupFields: [
         {
-          text: this.$t("cursus.school_structure.class_fields.name"),
+          text: this.$t("cursus.school_structure.fields.name"),
           value: "name",
         },
         {
-          text: this.$t("cursus.school_structure.class_fields.short_name"),
+          text: this.$t("cursus.school_structure.fields.short_name"),
           value: "shortName",
         },
         {
@@ -186,18 +216,18 @@ export default {
           value: "parentGroups",
         },
       ],
-      createClassDefaultItem: {
+      secondLevelGroupDefaultItem: {
         name: "",
         shortName: "",
         parentGroups: [],
       },
-      createClassCurrentGradeID: 0,
+      createSecondLevelGroupFirstLevelGroupId: 0,
       currentTerm: null,
     };
   },
   apollo: {
-    grades: {
-      query: gqlSchoolGrades,
+    schoolStructure: {
+      query: gqlFirstLevelGroups,
       variables() {
         return {
           schoolTerm: this.$data.currentTerm.id,
@@ -209,28 +239,28 @@ export default {
     },
   },
   methods: {
-    createGrade() {
-      this.$data.createGradeForm = true;
+    createFirstLevelGroup() {
+      this.$data.createFirstLevelGroupForm = true;
     },
-    createClass(id) {
-      this.$data.createClassCurrentGradeID = id;
-      this.$data.createClassForm = true;
+    createSecondLevelGroup(id) {
+      this.$data.createSecondLevelGroupFirstLevelGroupId = id;
+      this.$data.createSecondLevelGroupForm = true;
     },
-    transformCreateGradeItem(item) {
+    transformFirstLevelGroupItem(item) {
       return {
         ...item,
         schoolTerm: this.$data.currentTerm.id,
       };
     },
-    transformCreateClassItemForGrade(item) {
+    transformSecondLevelGroupItem(item) {
       return {
         ...item,
         schoolTerm: this.$data.currentTerm.id,
-        parentGroups: this.$data.createClassCurrentGradeID,
+        parentGroups: this.$data.createSecondLevelGroupFirstLevelGroupId,
       };
     },
     updateSchoolStructure() {
-      this.$apollo.queries.grades.refetch();
+      this.$apollo.queries.schoolStructure.refetch();
     },
   },
 };
diff --git a/aleksis/apps/cursus/frontend/components/schoolStructure.graphql b/aleksis/apps/cursus/frontend/components/schoolStructure.graphql
index 269bee126f97789b705a31371b9782d6be1f60ed..4c88e651f7b197d7772af11745c8170b386b1f2a 100644
--- a/aleksis/apps/cursus/frontend/components/schoolStructure.graphql
+++ b/aleksis/apps/cursus/frontend/components/schoolStructure.graphql
@@ -1,23 +1,32 @@
-query gqlSchoolGrades($schoolTerm: ID!) {
-  grades: schoolGradesByTerm(schoolTerm: $schoolTerm) {
-    id
-    name
-    shortName
-    childGroups {
+query gqlFirstLevelGroups($schoolTerm: ID!) {
+  schoolStructure {
+    firstLevelType {
+      name
+    }
+    secondLevelType {
+      name
+    }
+    firstLevelGroupsByTerm(schoolTerm: $schoolTerm) {
       id
       name
       shortName
-      owners {
+      childGroups {
         id
+        name
         shortName
+        owners {
+          id
+          shortName
+          lastName
+        }
       }
     }
   }
 }
 
-mutation gqlCreateGrades($input: [BatchCreateGroupInput]!) {
-  createGrades(input: $input) {
-    grades: groups {
+mutation gqlCreateFirstLevelGroup($input: [BatchCreateGroupInput]!) {
+  createFirstLevelGroups(input: $input) {
+    firstLevelGroups: groups {
       id
       name
       shortName
@@ -28,9 +37,9 @@ mutation gqlCreateGrades($input: [BatchCreateGroupInput]!) {
   }
 }
 
-mutation gqlCreateClasses($input: [BatchCreateGroupInput]!) {
-  createClasses(input: $input) {
-    classes: groups {
+mutation gqlCreateSecondLevelGroup($input: [BatchCreateGroupInput]!) {
+  createSecondLevelGroups(input: $input) {
+    secondLevelGroups: groups {
       id
       name
       shortName
diff --git a/aleksis/apps/cursus/frontend/messages/de.json b/aleksis/apps/cursus/frontend/messages/de.json
index 6e955badb0d0432f100d1a94b0d94b84f982f919..eb98427701e627f717b136a881fb6351de4d9fab 100644
--- a/aleksis/apps/cursus/frontend/messages/de.json
+++ b/aleksis/apps/cursus/frontend/messages/de.json
@@ -30,17 +30,12 @@
     "school_structure": {
       "menu_title": "Schulstruktur",
       "title": "Meine Schulstruktur aus",
-      "grade": "Jahrgang",
-      "add_grade": "Jahrgang hinzufügen",
-      "grade_fields": {
-        "short_name": "Kurzname",
-        "name": "Name"
-      },
-      "add_class": "Klasse hinzufügen",
-      "class_fields": {
+      "fields": {
         "short_name": "Kurzname",
         "name": "Name"
       },
+      "add": "{name} hinzufügen",
+      "add_title": "{name} hinzufügen",
       "timetable": "Stundenplan"
     },
     "errors": {
diff --git a/aleksis/apps/cursus/frontend/messages/en.json b/aleksis/apps/cursus/frontend/messages/en.json
index 9e257d3fc21217a044245a681036c2b3bf7c1582..45081f4f504514045475a7cc735f2423f6723246 100644
--- a/aleksis/apps/cursus/frontend/messages/en.json
+++ b/aleksis/apps/cursus/frontend/messages/en.json
@@ -30,17 +30,12 @@
     "school_structure": {
       "menu_title": "School Structure",
       "title": "My School Structure in",
-      "grade": "Grade",
-      "add_grade": "Add grade",
-      "grade_fields": {
-        "short_name": "Short Name",
-        "name": "Name"
-      },
-      "add_class": "Add class",
-      "class_fields": {
+      "fields": {
         "short_name": "Short Name",
         "name": "Name"
       },
+      "add": "Add {name}",
+      "add_title": "Add {name}",
       "timetable": "Timetable"
     },
     "errors": {
diff --git a/aleksis/apps/cursus/preferences.py b/aleksis/apps/cursus/preferences.py
new file mode 100644
index 0000000000000000000000000000000000000000..b356b428c4de63617447fdaec1ec8118541144da
--- /dev/null
+++ b/aleksis/apps/cursus/preferences.py
@@ -0,0 +1,35 @@
+from django.utils.translation import gettext_lazy as _
+
+from dynamic_preferences.preferences import Section
+from dynamic_preferences.types import ModelChoicePreference
+
+from aleksis.core.models import GroupType
+from aleksis.core.registries import site_preferences_registry
+
+cursus = Section("cursus", verbose_name=_("Course management"))
+
+
+@site_preferences_registry.register
+class SchoolStructureFirstLevelGroupType(ModelChoicePreference):
+    section = cursus
+    name = "school_structure_first_level_group_type"
+    required = False
+    default = None
+    model = GroupType
+    verbose_name = _("School structure: Group type for first level (e. g. grades)")
+    help_text = _(
+        "You have to set this and the second level group type to use the school structure tool."
+    )
+
+
+@site_preferences_registry.register
+class SchoolStructureSecondLevelGroupType(ModelChoicePreference):
+    section = cursus
+    name = "school_structure_second_level_group_type"
+    required = False
+    default = None
+    model = GroupType
+    verbose_name = _("School structure: Group type for second level (e. g. classes)")
+    help_text = _(
+        "You have to set this and the first level group type to use the school structure tool."
+    )
diff --git a/aleksis/apps/cursus/rules.py b/aleksis/apps/cursus/rules.py
index 59443793c21ee7f25da1fc88363c10d4c02d85db..c7f65403466cba3ab6c1b0556f39f3fbeb10b79a 100644
--- a/aleksis/apps/cursus/rules.py
+++ b/aleksis/apps/cursus/rules.py
@@ -5,6 +5,7 @@ from aleksis.core.util.predicates import (
     has_global_perm,
     has_object_perm,
     has_person,
+    is_site_preference_set,
 )
 
 from .models import Course, Subject
@@ -59,7 +60,12 @@ delete_course_predicate = view_course_predicate & (
 )
 add_perm("cursus.delete_course_rule", delete_course_predicate)
 
-manage_school_structure_predicate = has_person & has_global_perm("cursus.manage_school_structure")
+manage_school_structure_predicate = (
+    has_person
+    & is_site_preference_set("cursus", "school_structure_first_level_group_type")
+    & is_site_preference_set("cursus", "school_structure_second_level_group_type")
+    & has_global_perm("cursus.manage_school_structure")
+)
 add_perm("cursus.manage_school_structure_rule", manage_school_structure_predicate)
 
 view_cursus_menu_predicate = (
diff --git a/aleksis/apps/cursus/schema.py b/aleksis/apps/cursus/schema.py
index 6d40775f80bee61d977746f1096e7dc6ebb1c66f..2fb60907d9aa7cbda4de6e9c956c3bc9d8145719 100644
--- a/aleksis/apps/cursus/schema.py
+++ b/aleksis/apps/cursus/schema.py
@@ -10,11 +10,6 @@ from graphene_django_cud.mutations import (
 )
 from guardian.shortcuts import get_objects_for_user
 
-from aleksis.apps.cursus.settings import SCHOOL_CLASS_GROUP_TYPE_NAME, SCHOOL_GRADE_GROUP_TYPE_NAME
-from aleksis.apps.cursus.util.group_types import (
-    get_school_class_group_type,
-    get_school_grade_group_type,
-)
 from aleksis.core.models import Group, Person
 from aleksis.core.schema.base import (
     DjangoFilterMixin,
@@ -24,8 +19,9 @@ from aleksis.core.schema.base import (
     PermissionsTypeMixin,
 )
 from aleksis.core.schema.group import GroupType as GraphQLGroupType
+from aleksis.core.schema.group_type import GroupTypeType
 from aleksis.core.schema.person import PersonType as GraphQLPersonType
-from aleksis.core.util.core_helpers import has_person
+from aleksis.core.util.core_helpers import get_site_preferences, has_person
 
 from .models import Course, Subject
 
@@ -198,7 +194,7 @@ class CourseBatchPatchMutation(PermissionBatchPatchMixin, DjangoBatchPatchMutati
         only_fields = ("id", "name", "subject", "teachers", "groups", "lesson_quota")
 
 
-class CreateSchoolClassMutation(DjangoBatchCreateMutation):
+class CreateSchoolStructureSecondLevelGroupsMutation(DjangoBatchCreateMutation):
     class Meta:
         model = Group
         permissions = ("core.add_group",)
@@ -206,13 +202,15 @@ class CreateSchoolClassMutation(DjangoBatchCreateMutation):
 
     @classmethod
     def before_mutate(cls, root, info, input):  # noqa
-        group_type = get_school_class_group_type()
-        for school_class in input:
-            school_class["group_type"] = group_type.pk
+        group_type = get_site_preferences()["cursus__school_structure_second_level_group_type"]
+        if not group_type:
+            raise PermissionDenied()
+        for group in input:
+            group["group_type"] = group_type.pk
         return input
 
 
-class CreateSchoolGradeMutation(DjangoBatchCreateMutation):
+class CreateSchoolStructureFirstLevelGroupsMutation(DjangoBatchCreateMutation):
     class Meta:
         model = Group
         permissions = ("core.add_group",)
@@ -220,57 +218,84 @@ class CreateSchoolGradeMutation(DjangoBatchCreateMutation):
 
     @classmethod
     def before_mutate(cls, root, info, input):  # noqa
-        group_type = get_school_grade_group_type()
-        for school_grade in input:
-            school_grade["group_type"] = group_type.pk
+        group_type = get_site_preferences()["cursus__school_structure_first_level_group_type"]
+        if not group_type:
+            raise PermissionDenied()
+        for group in input:
+            group["group_type"] = group_type.pk
         return input
 
 
-class Query(graphene.ObjectType):
-    subjects = FilterOrderList(SubjectType)
-    courses = FilterOrderList(CourseType)
-
-    school_classes = FilterOrderList(GraphQLGroupType)
-    school_grades = FilterOrderList(GraphQLGroupType)
-    school_grades_by_term = FilterOrderList(GraphQLGroupType, school_term=graphene.ID())
-
-    teachers = FilterOrderList(TeacherType)
+class SchoolStructureQuery(graphene.ObjectType):
+    first_level_type = graphene.Field(GroupTypeType)
+    second_level_type = graphene.Field(GroupTypeType)
+    first_level_groups = FilterOrderList(GraphQLGroupType)
+    second_level_groups = FilterOrderList(GraphQLGroupType)
+    first_level_groups_by_term = FilterOrderList(GraphQLGroupType, school_term=graphene.ID())
 
-    course_by_id = graphene.Field(CourseType, id=graphene.ID())
-    courses_of_teacher = FilterOrderList(CourseType, teacher=graphene.ID())
+    @staticmethod
+    def resolve_first_level_type(root, info, **kwargs):
+        return get_site_preferences()["cursus__school_structure_first_level_group_type"]
 
-    def resolve_course_by_id(root, info, id):  # noqa
-        course = Course.objects.get(pk=id)
-        if not info.context.user.has_perm("cursus.view_course_rule", course):
-            raise PermissionDenied()
-        return course
+    @staticmethod
+    def resolve_second_level_type(root, info, **kwargs):
+        return get_site_preferences()["cursus__school_structure_second_level_group_type"]
 
     @staticmethod
-    def resolve_school_classes(root, info, **kwargs):
+    def resolve_first_level_groups(root, info, **kwargs):
+        group_type = get_site_preferences()["cursus__school_structure_first_level_group_type"]
+        if not group_type:
+            return []
         return get_objects_for_user(
             info.context.user,
             "core.view_group",
-            Group.objects.filter(group_type__name=SCHOOL_CLASS_GROUP_TYPE_NAME),
+            Group.objects.filter(group_type=group_type),
         )
 
     @staticmethod
-    def resolve_school_grades(root, info, **kwargs):
+    def resolve_second_level_groups(root, info, **kwargs):
+        group_type = get_site_preferences()["cursus__school_structure_second_level_group_type"]
+        if not group_type:
+            return []
         return get_objects_for_user(
             info.context.user,
             "core.view_group",
-            Group.objects.filter(group_type__name=SCHOOL_GRADE_GROUP_TYPE_NAME),
+            Group.objects.filter(group_type=group_type),
         )
 
     @staticmethod
-    def resolve_school_grades_by_term(root, info, school_term):
+    def resolve_first_level_groups_by_term(root, info, school_term):
+        group_type = get_site_preferences()["cursus__school_structure_first_level_group_type"]
+        print(
+            group_type,
+            Group.objects.filter(school_term=school_term).filter(group_type=group_type),
+        )
+        if not group_type:
+            return []
         return get_objects_for_user(
             info.context.user,
             "core.view_group",
-            Group.objects.filter(school_term__id=school_term).filter(
-                group_type__name=SCHOOL_GRADE_GROUP_TYPE_NAME
-            ),
+            Group.objects.filter(school_term=school_term).filter(group_type=group_type),
         )
 
+
+class Query(graphene.ObjectType):
+    subjects = FilterOrderList(SubjectType)
+    courses = FilterOrderList(CourseType)
+
+    school_structure = graphene.Field(SchoolStructureQuery)
+
+    teachers = FilterOrderList(TeacherType)
+
+    course_by_id = graphene.Field(CourseType, id=graphene.ID())
+    courses_of_teacher = FilterOrderList(CourseType, teacher=graphene.ID())
+
+    def resolve_course_by_id(root, info, id):  # noqa
+        course = Course.objects.get(pk=id)
+        if not info.context.user.has_perm("cursus.view_course_rule", course):
+            raise PermissionDenied()
+        return course
+
     @staticmethod
     def resolve_teachers(root, info):
         return get_objects_for_user(
@@ -289,6 +314,10 @@ class Query(graphene.ObjectType):
         # FIXME: Permission checking. But maybe it's done in get_queryset
         return teacher.courses_as_teacher.all()
 
+    @staticmethod
+    def resolve_school_structure(root, info):
+        return True
+
 
 class Mutation(graphene.ObjectType):
     create_subjects = SubjectBatchCreateMutation.Field()
@@ -299,5 +328,5 @@ class Mutation(graphene.ObjectType):
     delete_courses = CourseBatchDeleteMutation.Field()
     update_courses = CourseBatchPatchMutation.Field()
 
-    create_grades = CreateSchoolGradeMutation.Field()
-    create_classes = CreateSchoolClassMutation.Field()
+    create_first_level_groups = CreateSchoolStructureFirstLevelGroupsMutation.Field()
+    create_second_level_groups = CreateSchoolStructureSecondLevelGroupsMutation.Field()
diff --git a/aleksis/apps/cursus/settings.py b/aleksis/apps/cursus/settings.py
deleted file mode 100644
index 1065c8c679515b92214f591ca8c1962a2ff4bfba..0000000000000000000000000000000000000000
--- a/aleksis/apps/cursus/settings.py
+++ /dev/null
@@ -1,2 +0,0 @@
-SCHOOL_GRADE_GROUP_TYPE_NAME = "School grade"
-SCHOOL_CLASS_GROUP_TYPE_NAME = "School class"
diff --git a/aleksis/apps/cursus/util/group_types.py b/aleksis/apps/cursus/util/group_types.py
deleted file mode 100644
index 71f1ebbcc4d4c7613aa678af24b1b3e154d01f24..0000000000000000000000000000000000000000
--- a/aleksis/apps/cursus/util/group_types.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from aleksis.core.models import GroupType
-
-from ..settings import SCHOOL_CLASS_GROUP_TYPE_NAME, SCHOOL_GRADE_GROUP_TYPE_NAME
-
-
-def get_school_grade_group_type():
-    group_type, __ = GroupType.objects.managed_by_app("cursus").get_or_create(
-        name=SCHOOL_GRADE_GROUP_TYPE_NAME, managed_by_app_label="cursus"
-    )
-    return group_type
-
-
-def get_school_class_group_type():
-    group_type, __ = GroupType.objects.managed_by_app("cursus").get_or_create(
-        name=SCHOOL_CLASS_GROUP_TYPE_NAME, managed_by_app_label="cursus"
-    )
-    return group_type
diff --git a/graphql.config.yml b/graphql.config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..385050a8aab4f7224dcf2ac2e06742b6df0ec198
--- /dev/null
+++ b/graphql.config.yml
@@ -0,0 +1 @@
+schema: http://localhost:8000/graphql/