diff --git a/src/api/schedule.py b/src/api/schedule.py
index d0f10416a626a71f442165014d1f5297b82c0a3c..0050b9e7ee3a6aecbed4333948fc514f1710324c 100644
--- a/src/api/schedule.py
+++ b/src/api/schedule.py
@@ -227,7 +227,7 @@ class ScheduleEncoder(json.JSONEncoder):
             'name': obj.name,
             'slug': obj.slug,
             'guid': obj.id,
-            # Future TODO: # 'type': obj., # channel vs. cluster vs. virtual vs. ...?
+            # Future TODO: # 'type': obj., # cluster vs. virtual vs. ...?
             # 'description_en': obj.description_en,
             # 'description_de': obj.description_de,
             # Future TODO  'url': obj.get_absolute_url(),
diff --git a/src/api/serializers.py b/src/api/serializers.py
index aa56d026e3d20cc78fe684addf6512f0281110e9..9911bf1f29505a3e3ae7e278b46c06109ad71827 100644
--- a/src/api/serializers.py
+++ b/src/api/serializers.py
@@ -147,8 +147,7 @@ class AssemblySerializer(HubModelSerializer):
             'slug',
             'id',
             'name',
-            'state_assembly',
-            'state_channel',
+            'state',
             'hierarchy',
             'parent',
             'assembly_location',
@@ -158,7 +157,7 @@ class AssemblySerializer(HubModelSerializer):
             'rooms_url',
             'badges_url',
         ]
-        staff_only_fields = ['state_assembly', 'state_channel', 'hierarchy']
+        staff_only_fields = ['state', 'hierarchy']
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
diff --git a/src/api/tests/badges/create_redeem_token.py b/src/api/tests/badges/create_redeem_token.py
index 28931971e31803126209a4c87296cb27e393da16..894176b17f9f04041db176eb20e17f85f49567d9 100644
--- a/src/api/tests/badges/create_redeem_token.py
+++ b/src/api/tests/badges/create_redeem_token.py
@@ -26,7 +26,7 @@ class CreateRedeemTokenTests(TestCase):
             end=datetime(2020, 12, 30, 23, 45, 00, tzinfo=tz),
         )
         self.conf.save()
-        self.assembly = Assembly(name='TestAssembly', slug='asmbly', conference=self.conf, state_assembly=Assembly.State.PLACED)
+        self.assembly = Assembly(name='TestAssembly', slug='asmbly', conference=self.conf, state=Assembly.State.PLACED)
         self.assembly.save()
 
         self.badge = Badge(
diff --git a/src/api/tests/events.py b/src/api/tests/events.py
index 581e8f958a64f6ad37531bd4dfaf47ee045746b4..4b042acd753a3dbb5674d6550c36cff6f5b4fe50 100644
--- a/src/api/tests/events.py
+++ b/src/api/tests/events.py
@@ -22,7 +22,7 @@ class EventsTestCase(TestCase):
         self.human_cm = ConferenceMember(conference=self.conference1, user=self.human_user)
         self.human_cm.save()
 
-        assembly = Assembly(conference=self.conference1, name='DUMMY', slug='dummy', state_assembly=Assembly.State.ACCEPTED, is_official=True)
+        assembly = Assembly(conference=self.conference1, name='DUMMY', slug='dummy', state=Assembly.State.ACCEPTED, is_official=True)
         assembly.save()
 
         self.event = Event(
diff --git a/src/api/tests/map.py b/src/api/tests/map.py
index 9f6375eecc07b16dbecbf38cb9888c6da18bcb4f..41bf4fe15d9dc949121c452615c12c074e2adeef 100644
--- a/src/api/tests/map.py
+++ b/src/api/tests/map.py
@@ -49,7 +49,7 @@ class MapTest(TestCase):
 
         # set POI on assembly and accept it
         self.assembly.location_point = Point(8.9, 52.9)
-        self.assembly.state_assembly = Assembly.State.ACCEPTED
+        self.assembly.state = Assembly.State.ACCEPTED
         self.assembly.save()
         ConferenceExportCache.objects.all().delete()
 
@@ -60,7 +60,7 @@ class MapTest(TestCase):
         self.assertEqual(0, len(content['features']))
 
         # change state to 'placed', now there should be a POI
-        self.assembly.state_assembly = Assembly.State.PLACED
+        self.assembly.state = Assembly.State.PLACED
         self.assembly.save()
         ConferenceExportCache.objects.all().delete()
         resp = self.client.get(url)
@@ -77,7 +77,7 @@ class MapTest(TestCase):
         self.assertEqual(self.assembly.is_cluster, feature.get('properties', {}).get('cluster'))
 
         # change assembly to 'hidden', POI should still be there
-        self.assembly.state_assembly = Assembly.State.HIDDEN
+        self.assembly.state = Assembly.State.HIDDEN
         self.assembly.save()
         ConferenceExportCache.objects.all().delete()
         resp = self.client.get(url)
diff --git a/src/api/tests/metrics.py b/src/api/tests/metrics.py
index 6f56c24324a186e8e0602d75e8b9cc4712c52afe..e025c86d8ce71be3ab5926571c7dcdbfc504b343 100644
--- a/src/api/tests/metrics.py
+++ b/src/api/tests/metrics.py
@@ -32,7 +32,7 @@ class MetricsTest(TestCase):
         assembly = Assembly(
             name='TestAssembly',
             slug='asmbly',
-            state_assembly=Assembly.State('planned'),
+            state=Assembly.State('planned'),
             conference=conf,
         )
         assembly.save()
diff --git a/src/api/tests/permissions.py b/src/api/tests/permissions.py
index 87c9010ebc969fb1c338200eb04669074048f4e0..9beff08a6a7a574fe152399f9839e489a22b7c23 100644
--- a/src/api/tests/permissions.py
+++ b/src/api/tests/permissions.py
@@ -202,7 +202,7 @@ class AssemblyPermissionTestCase(ConferencePermissionTestCase):
         self.assembly = self.view.assembly = Assembly.objects.create(
             name='TestAssembly',
             slug='asmbly',
-            state_assembly=Assembly.State('planned'),
+            state=Assembly.State('planned'),
             conference=self.conference,
         )
 
@@ -235,7 +235,7 @@ class IsPublicAssemblyReadOnlyTestCase(AssemblyPermissionTestCase):
 
     def test_get_allowed_public(self):
         request = self.factory.get('/')
-        self.assembly.state_assembly = Assembly.PUBLIC_STATES[0]
+        self.assembly.state = Assembly.PUBLIC_STATES[0]
         self.assembly.save()
 
         self.run_permission_test(IsPublicAssemblyReadOnly(), (True, True), request)
diff --git a/src/api/tests/schedule.py b/src/api/tests/schedule.py
index 5d3e5b045a5aab46e5e54c9515c0aae29f0724a8..e902270923ddf30a48dcf9a21f0813f34ed72481 100644
--- a/src/api/tests/schedule.py
+++ b/src/api/tests/schedule.py
@@ -30,7 +30,7 @@ class ScheduleTest(TestCase):
         self.conf.save()
         self.conf.tracks.create(slug='community', name='Community').save()
         self.conf.tracks.create(slug='security', name='Security').save()
-        self.assembly = Assembly(name='TestAssembly', slug='asmbly', conference=self.conf, state_assembly=Assembly.State.PLACED)
+        self.assembly = Assembly(name='TestAssembly', slug='asmbly', conference=self.conf, state=Assembly.State.PLACED)
         self.assembly.save()
         self.room = Room(conference=self.conf, assembly=self.assembly, name='Foo Room', room_type=Room.RoomType.STAGE)
         self.room.save()
@@ -52,7 +52,7 @@ class ScheduleTest(TestCase):
         content_parser(content_str)
 
         # prepare assembly for event-hosting, incl. room
-        self.assembly.state_channel = Assembly.State.ACCEPTED
+        self.assembly.state = Assembly.State.ACCEPTED
         self.assembly.save()
         r = self.assembly.rooms.create(conference=self.conf, name='Zelt', room_type='stage')
 
diff --git a/src/api/tests/workadventure.py b/src/api/tests/workadventure.py
index 7d673869f2aeac785dbd5065946e38eece7f6461..e49648de68d651c05aa96e2a728f03c288b70a80 100644
--- a/src/api/tests/workadventure.py
+++ b/src/api/tests/workadventure.py
@@ -94,9 +94,9 @@ class WorkAdventureMapServiceTestCase(_WorkAdventureTestCase):
         endpoint_data = response.json()
         self.assertEqual(0, len(endpoint_data))
 
-        self.assembly1a.state_assembly = Assembly.State.ACCEPTED
+        self.assembly1a.state = Assembly.State.ACCEPTED
         self.assembly1a.save()
-        self.assembly1b.state_assembly = Assembly.State.PLACED
+        self.assembly1b.state = Assembly.State.PLACED
         self.assembly1b.save()
 
         response = c.get(self.wa_url)
@@ -114,15 +114,15 @@ class WorkAdventureMapServiceTestCase(_WorkAdventureTestCase):
 
     def testPush(self):
         # prepare assembly objects
-        self.assembly1a.state_assembly = Assembly.State.ACCEPTED
-        self.assembly1a.save(update_fields=['state_assembly'])
-        assembly2 = Assembly(conference=self.conference1, slug='dummy2', name='Test Dummy 2', state_assembly=Assembly.State.ACCEPTED)
+        self.assembly1a.state = Assembly.State.ACCEPTED
+        self.assembly1a.save(update_fields=['state'])
+        assembly2 = Assembly(conference=self.conference1, slug='dummy2', name='Test Dummy 2', state=Assembly.State.ACCEPTED)
         assembly2.save()
-        assembly3 = Assembly(conference=self.conference1, slug='dummy3', name='Test Dummy 3', state_assembly=Assembly.State.ACCEPTED)
+        assembly3 = Assembly(conference=self.conference1, slug='dummy3', name='Test Dummy 3', state=Assembly.State.ACCEPTED)
         assembly3.save()
-        assembly4 = Assembly(conference=self.conference1, slug='dummy4', name='Test Dummy 4', state_assembly=Assembly.State.ACCEPTED)
+        assembly4 = Assembly(conference=self.conference1, slug='dummy4', name='Test Dummy 4', state=Assembly.State.ACCEPTED)
         assembly4.save()
-        assembly5 = Assembly(conference=self.conference1, slug='dummy5', name='Test Dummy 5', state_assembly=Assembly.State.ACCEPTED)
+        assembly5 = Assembly(conference=self.conference1, slug='dummy5', name='Test Dummy 5', state=Assembly.State.ACCEPTED)
         assembly5.save()
 
         # prepare room objects
@@ -227,9 +227,9 @@ class WorkAdventureEndpointTestCase:  # TODO: enable again -- _WorkAdventureTest
         response = c.get(url_a)
         self.assertEqual(response.status_code, 404, f'Expected to have WA endpoint return HTTP 404 instead of {response.status_code}.')
 
-        self.assembly1a.state_assembly = Assembly.State.ACCEPTED
+        self.assembly1a.state = Assembly.State.ACCEPTED
         self.assembly1a.save()
-        self.assembly1b.state_assembly = Assembly.State.PLACED
+        self.assembly1b.state = Assembly.State.PLACED
         self.assembly1b.save()
         endpoint_data = []
 
@@ -252,7 +252,7 @@ class WorkAdventureEndpointTestCase:  # TODO: enable again -- _WorkAdventureTest
     def testPush(self):
         # prepare assembly and room
         self.assembly1c.refresh_from_db()
-        self.assembly1c.state_assembly = Assembly.State.ACCEPTED
+        self.assembly1c.state = Assembly.State.ACCEPTED
         self.assembly1c.save()
 
         self.room1c.refresh_from_db()
diff --git a/src/api/views/maps.py b/src/api/views/maps.py
index eba2387d775bb38af9f35b69c43c511dc70a6c03..c238affb721217a00f35d065df5907fd645b40a8 100644
--- a/src/api/views/maps.py
+++ b/src/api/views/maps.py
@@ -71,7 +71,7 @@ class AssembliesExportView(ConferenceSlugMixin, APIView, metaclass=abc.ABCMeta):
 
     def get_queryset(self):
         exportable_states = [*Assembly.PLACED_STATES, Assembly.State.HIDDEN]
-        return Assembly.objects.filter(conference=self.conference, state_assembly__in=exportable_states)
+        return Assembly.objects.filter(conference=self.conference, state__in=exportable_states)
 
     def get_geometry_field(self, obj):
         return getattr(obj, self.geometry_field)
@@ -138,7 +138,7 @@ class C3NavExportView(ConferenceSlugMixin, APIView):
         data = []
 
         exportable_states = [*Assembly.PLACED_STATES, Assembly.State.HIDDEN]
-        qs = self.conference.assemblies.filter(state_assembly__in=exportable_states)
+        qs = self.conference.assemblies.filter(state__in=exportable_states)
         if request.GET.get('all') != '1':
             qs = qs.exclude(location_data__point=None, location_data__boundaries=None)
         for assembly in qs:  # type: Assembly
@@ -153,7 +153,7 @@ class C3NavExportView(ConferenceSlugMixin, APIView):
                     'description': {'de': assembly.description_de, 'en': assembly.description_en},
                     'public_url': hub_absolute('plainui:assembly', assembly_slug=assembly.slug),
                     'parent_id': assembly.parent_id,
-                    'children': assembly.children.filter(state_assembly__in=exportable_states).values_list('slug', flat=True) if assembly.is_cluster else None,
+                    'children': assembly.children.filter(state__in=exportable_states).values_list('slug', flat=True) if assembly.is_cluster else None,
                     'floor': assembly.get_location_floor_index(),
                     'location': loc_data.get('point'),  # assembly.get_location_point_xy(),
                     'polygons': loc_data.get('boundaries'),  # assembly.get_location_boundaries_xy(),
diff --git a/src/api/views/metrics.py b/src/api/views/metrics.py
index f8c3ef2b12d939800f3f494423ad39d945b288e3..7f84d5ab24ce10c828b693d172074a636dd34102 100644
--- a/src/api/views/metrics.py
+++ b/src/api/views/metrics.py
@@ -49,7 +49,6 @@ class MetricsView(TemplateView):
             'hub_conference_members_themes': {'help': 'used themes by members in the conference', 'type': 'gauge', 'values': {}},
             'hub_conference_tickets': {'help': 'registered tickets', 'type': 'counter', 'values': {}},
             'hub_conference_assemblies': {'help': "conference's assemblies", 'type': 'gauge', 'values': {}},
-            'hub_conference_channels': {'help': "conference's channels", 'type': 'gauge', 'values': {}},
             'hub_conference_badges_public': {'help': "conference's badges (public)", 'type': 'gauge', 'values': {}},
             'hub_conference_badges_hidden': {'help': "conference's badges (non-public)", 'type': 'gauge', 'values': {}},
             'hub_conference_badges_accepted': {'help': "conference's badges (accepted/assigned)", 'type': 'gauge', 'values': {}},
@@ -64,10 +63,13 @@ class MetricsView(TemplateView):
             slug = conference.slug
 
             # hub_conference_assemblies
-            self.report_assembly_metrics(metrics, conference, 'assembly', 'assemblies')
-
-            # hub_conference_channels
-            self.report_assembly_metrics(metrics, conference, 'channel', 'channels')
+            asm_count = Assembly.objects.filter(conference=conference).values('state').annotate(count=Count('*'))
+            expected_states = list(Assembly.State.values)
+            for line in asm_count:
+                metrics[f'hub_conference_{'assemblies'}']['values'][f'{{conference="{conference.slug}",state="{line["state"]}"}}'] = line['count']
+                expected_states.remove(line['state'])
+            for missing in expected_states:
+                metrics[f'hub_conference_{'assemblies'}']['values'][f'{{conference="{conference.slug}",state="{missing}"}}'] = 0
 
             # hub_conference_rooms
             room_counts = {room_type: 0 for room_type in Room.RoomType.values}
@@ -143,13 +145,3 @@ class MetricsView(TemplateView):
         context['metrics'] = metrics
 
         return context
-
-    @staticmethod
-    def report_assembly_metrics(metrics, conference: Conference, lookup_key: str, report_key: str):
-        asm_count = Assembly.objects.filter(conference=conference).values(f'state_{lookup_key}').annotate(count=Count('*'))
-        expected_states = list(Assembly.State.values)
-        for line in asm_count:
-            metrics[f'hub_conference_{report_key}']['values'][f'{{conference="{conference.slug}",state="{line["state_" + lookup_key]}"}}'] = line['count']
-            expected_states.remove(line[f'state_{lookup_key}'])
-        for missing in expected_states:
-            metrics[f'hub_conference_{report_key}']['values'][f'{{conference="{conference.slug}",state="{missing}"}}'] = 0
diff --git a/src/api/views/workadventure.py b/src/api/views/workadventure.py
index 3b47e5cb6e43a7e00ab41dd449e546e6ef1a18c0..862b7b9fe10f00c9471f93c17a453c556a5cd703 100644
--- a/src/api/views/workadventure.py
+++ b/src/api/views/workadventure.py
@@ -75,7 +75,7 @@ class MapServiceView(ConferenceSlugMixin, APIView):
     def get(self, request, format=None):  # pylint: disable=redefined-builtin
         wa_rooms = []
         for room in Room.objects.filter(conference=self.conference, room_type=Room.RoomType.WORKADVENTURE).select_related('assembly'):
-            if room.assembly is not None and room.assembly.state_assembly not in Assembly.PUBLIC_STATES:
+            if room.assembly is not None and room.assembly.state not in Assembly.PUBLIC_STATES:
                 continue
             room_data = _export_room_data(room)
             wa_rooms.append(room_data)
diff --git a/src/backoffice/forms/assemblies.py b/src/backoffice/forms/assemblies.py
index f71454133b8a522ac21d14466e8779bdc6858a47..c581d5ea34f9eac33d76075b17b6d4e170a05f39 100644
--- a/src/backoffice/forms/assemblies.py
+++ b/src/backoffice/forms/assemblies.py
@@ -18,20 +18,12 @@ logger = logging.getLogger(__name__)
 class AssemblyCreateForm(forms.ModelForm):
     class Meta:
         model = Assembly
-        fields = ['slug', 'name', 'is_assembly', 'is_channel']
-
-    is_assembly = forms.BooleanField(initial=False, required=False, help_text=_('Assembly__is_assembly__help'), label=_('Assembly__is_assembly'))
-    is_channel = forms.BooleanField(initial=False, required=False, help_text=_('Assembly__is_channel__help'), label=_('Assembly__is_channel'))
+        fields = ['slug', 'name']
 
     def __init__(self, *args, **kwargs):
         self._conference = kwargs.pop('conference')
         super().__init__(*args, **kwargs)
 
-        if not self._conference.support_channels:
-            self.fields['is_assembly'].disabled = True
-            self.fields['is_assembly'].initial = True
-            del self.fields['is_channel']
-
         if self._conference.has_disclaimer('assembly'):
             self.fields['disclaimer'] = forms.BooleanField(
                 initial=False,
@@ -45,10 +37,6 @@ class AssemblyCreateForm(forms.ModelForm):
         if self._conference.has_disclaimer('assembly') and not self.cleaned_data['disclaimer']:
             self.add_error('disclaimer', _('Assembly__disclaimer-needed'))
 
-        if (not self.cleaned_data['is_assembly']) and (not self.cleaned_data['is_channel']):
-            self.add_error('is_assembly', _('Assembly__must_be_assembly_or_channel'))
-            self.add_error('is_channel', _('Assembly__must_be_assembly_or_channel'))
-
         if (slug := self.cleaned_data.get('slug')) and Assembly.objects.filter(conference=self._conference, slug=slug).exists():
             self.add_error('slug', _('Assembly__slug__alreadyexists'))
 
@@ -75,7 +63,7 @@ class AssemblyEditForm(TranslatedFieldsForm):
             'assembly_location': forms.Textarea(attrs={'rows': 4}),
         }
 
-    def __init__(self, *args, staff_access: bool, staff_mode: bool, assembly_staff_access: bool, channel_staff_access: bool, **kwargs):
+    def __init__(self, *args, staff_access: bool, staff_mode: bool, assembly_staff_access: bool, **kwargs):
         super().__init__(*args, **kwargs)
 
         # configure fields' widget customizations
@@ -84,7 +72,7 @@ class AssemblyEditForm(TranslatedFieldsForm):
         # configure fields
         assembly = self.instance
         conference = self.instance.conference
-        if assembly.basedata_readonly and not staff_access:
+        if assembly.base_data_readonly and not staff_access:
             self.fields['name'].disabled = True
             self.fields['slug'].disabled = True
             self.fields['is_physical'].disabled = True
@@ -157,7 +145,7 @@ class AssemblyMemberAddForm(forms.Form):
 class AssemblyMemberEditForm(forms.ModelForm):
     class Meta:
         model = AssemblyMember
-        fields = ['is_representative', 'can_manage_assembly', 'is_content_coordinator', 'is_production_coordinator', 'is_technical_contact', 'show_public']
+        fields = ['is_representative', 'can_manage_assembly', 'is_technical_contact', 'show_public']
 
     def clean(self):
         # call original .clean() which does some checks already
diff --git a/src/backoffice/forms/rooms.py b/src/backoffice/forms/rooms.py
index 8e22909df8476d7079960b652bf4ae5c16b430b1..1d3144ef897bf8808f0c5ff604ad96cc6c8042df 100644
--- a/src/backoffice/forms/rooms.py
+++ b/src/backoffice/forms/rooms.py
@@ -167,7 +167,7 @@ class AssemblyRoomEditForm(TranslatedFieldsForm):
         model = Room
         fields = ['name', 'slug', 'description', 'is_public_fahrplan', 'is_official', 'official_room_order', 'capacity']
 
-    def __init__(self, *args, with_capacity=False, channel_staff=False, **kwargs):
+    def __init__(self, *args, with_capacity: bool = False, schedule_admin: bool = False, **kwargs):
         super().__init__(*args, **kwargs)
         self.fields['slug'].disabled = True
         if self.instance.room_type in Room.BACKEND_ROOMTYPES:
@@ -185,7 +185,7 @@ class AssemblyRoomEditForm(TranslatedFieldsForm):
         if self.instance.room_type in [Room.RoomType.HANGAR]:
             self.fields['name'].disabled = True
 
-        if not channel_staff:
+        if not schedule_admin:
             del self.fields['is_public_fahrplan']
             del self.fields['is_official']
             del self.fields['official_room_order']
@@ -254,7 +254,7 @@ class AssemblyRoomEditHangarForm(TranslatedFieldsForm):
         model = Room
         fields = ['backend_status', 'backend_link']
 
-    def __init__(self, *args, with_capacity=False, channel_staff=False, **kwargs):
+    def __init__(self, *args, with_capacity: bool = False, schedule_admin: bool = False, **kwargs):
         super().__init__(*args, **kwargs)
         self.fields['backend_status'].disabled = True
         self.fields['backend_link'].label = _('Room-hangar_backend_link')
diff --git a/src/backoffice/locale/de/LC_MESSAGES/django.po b/src/backoffice/locale/de/LC_MESSAGES/django.po
index 3d93572540a0febbb1e245126eef7699ad6bcab5..67d29a252841a59680245a0352c4ff67ae3e04bd 100644
--- a/src/backoffice/locale/de/LC_MESSAGES/django.po
+++ b/src/backoffice/locale/de/LC_MESSAGES/django.po
@@ -17,24 +17,9 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-msgid "Assembly__is_assembly__help"
-msgstr "Ankreuzen, wenn ihr eine Assembly seid - egal ob physisch oder virtuell."
-
-msgid "Assembly__is_assembly"
-msgstr "Ich melde eine Assembly an."
-
-msgid "Assembly__is_channel__help"
-msgstr "Ankreuzen, wenn ihr ein Channel bzw. eine Bühne seid - sprich Vortragsprogramm bietet welches über Self-organized Sessions hinausgeht (Faustregel: ihr habt Streaming über das bzw. mit dem VOC). Wenn ihr nicht wisst was gemeint ist seid ihr kein Channel."
-
-msgid "Assembly__is_channel"
-msgstr "Ich melde einen Channel oder eine Bühne an."
-
 msgid "Assembly__disclaimer-needed"
 msgstr "Bitte beachte den Hinweis und bestätige, dass du ihn gelesen und verstanden hast."
 
-msgid "Assembly__must_be_assembly_or_channel"
-msgstr "Assembly und/oder Channel - nur \"keines von beiden\" ergibt keinen Sinn."
-
 msgid "Assembly__slug__alreadyexists"
 msgstr "Dieser Kurzname wird bereits von einer anderen Assembly benutzt."
 
@@ -362,11 +347,7 @@ msgid "no"
 msgstr "Nein"
 
 # use translation from core
-msgid "Assembly__state_assembly"
-msgstr ""
-
-# use translation from core
-msgid "Assembly__state_channel"
+msgid "Assembly__state"
 msgstr ""
 
 msgid "assemblycreate_title"
@@ -402,10 +383,10 @@ msgstr "Webseite"
 msgid "Assembly__hierarchy"
 msgstr "Einordnung"
 
-msgid "Assembly__state_assembly-planned__hint"
+msgid "Assembly__state__planned__hint"
 msgstr "Die Registrierung dieser Assembly ist noch nicht abgeschlossen."
 
-msgid "Assembly__state_assembly-planned__description"
+msgid "Assembly__state__planned__description"
 msgstr "Um die Registrierung dieses Assemblies abzuschließen, füllt bitte die Informationen und  restlichen Daten (z.B. Beschreibung) aus."
 
 msgid "Assembly__registration_details"
@@ -629,12 +610,6 @@ msgstr "Repräsentant"
 msgid "AssemblyMember__can_manage_assembly"
 msgstr "kann Assembly verwalten"
 
-msgid "AssemblyMember__is_content_coordinator"
-msgstr "Content-Koordinator"
-
-msgid "AssemblyMember__is_production_coordinator"
-msgstr "Produktions-Koordinator"
-
 msgid "AssemblyMember__is_technical_contact"
 msgstr "technische Ansprechperson"
 
@@ -1861,9 +1836,6 @@ msgstr "abgelehnt"
 msgid "nav_assemblies_hidden"
 msgstr "versteckt"
 
-msgid "nav_assemblies_not_selected"
-msgstr "keine Teilnahme"
-
 msgid "lists"
 msgstr "Listen"
 
@@ -1964,24 +1936,6 @@ msgstr "Badge %(token)s aktiviert"
 msgid "BadgeToken__deactivated %(token)s"
 msgstr "Badge %(token)s deaktiviert"
 
-msgid "nav_channels_all"
-msgstr "alle"
-
-msgid "nav_channels_accepted"
-msgstr "akzeptiert"
-
-msgid "nav_channels_pending"
-msgstr "wartend"
-
-msgid "nav_channels_planned"
-msgstr "geplant"
-
-msgid "nav_channels_rejected"
-msgstr "abgelehnt"
-
-msgid "nav_channels_hidden"
-msgstr "versteckt"
-
 msgid "nav_conference"
 msgstr "Konferenz"
 
diff --git a/src/backoffice/locale/en/LC_MESSAGES/django.po b/src/backoffice/locale/en/LC_MESSAGES/django.po
index f73c7c4e43c9b85f3a114653ba9e4cc8e289088b..5700860ebf1f36e6e3c3ec4075edcb44ed32fabe 100644
--- a/src/backoffice/locale/en/LC_MESSAGES/django.po
+++ b/src/backoffice/locale/en/LC_MESSAGES/django.po
@@ -17,24 +17,9 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-msgid "Assembly__is_assembly__help"
-msgstr "Tick this if you are an assembly - no matter whether physical or virtual."
-
-msgid "Assembly__is_assembly"
-msgstr "I'm registering an assembly."
-
-msgid "Assembly__is_channel__help"
-msgstr "Tick this if you are a channel or stage, i.e. you are doing events apart from self-organized sessions (rule of thumb: you do streaming via/with the VOC). If you don't know what we're talking about don't tick this box."
-
-msgid "Assembly__is_channel"
-msgstr "I'm registering a channel or stage."
-
 msgid "Assembly__disclaimer-needed"
 msgstr "Please read the disclaimer and acknowledge that you have understood and will adhere to it."
 
-msgid "Assembly__must_be_assembly_or_channel"
-msgstr "Assembly and/or channel - only neither of both doesn't make any sense."
-
 msgid "Assembly__slug__alreadyexists"
 msgstr "This slug is already used by another assembly."
 
@@ -361,11 +346,10 @@ msgstr "Yes"
 msgid "no"
 msgstr "No"
 
-msgid "Assembly__state_assembly"
-msgstr "assembly"
 
-msgid "Assembly__state_channel"
-msgstr "channel"
+# use translation from core
+msgid "Assembly__state"
+msgstr ""
 
 msgid "assemblycreate_title"
 msgstr "Details of the new assembly/channel/stage"
@@ -400,10 +384,10 @@ msgstr "website"
 msgid "Assembly__hierarchy"
 msgstr "hierarchy"
 
-msgid "Assembly__state_assembly-planned__hint"
+msgid "Assembly__state__planned__hint"
 msgstr "This assembly's registration has not been completed."
 
-msgid "Assembly__state_assembly-planned__description"
+msgid "Assembly__state__planned__description"
 msgstr "To complete the registration of this assembly, please fill in the information and  remaining data (e.g. description)."
 
 msgid "Assembly__registration_details"
@@ -627,12 +611,6 @@ msgstr "representative"
 msgid "AssemblyMember__can_manage_assembly"
 msgstr "can manage assembly"
 
-msgid "AssemblyMember__is_content_coordinator"
-msgstr "content coordinator"
-
-msgid "AssemblyMember__is_production_coordinator"
-msgstr "production coordinator"
-
 msgid "AssemblyMember__is_technical_contact"
 msgstr "technical contact"
 
@@ -1865,9 +1843,6 @@ msgstr "rejected"
 msgid "nav_assemblies_hidden"
 msgstr "hidden"
 
-msgid "nav_assemblies_not_selected"
-msgstr "no participation"
-
 msgid "lists"
 msgstr "lists"
 
@@ -1967,24 +1942,6 @@ msgstr "Redeem token '%(token)s' activated."
 msgid "BadgeToken__deactivated %(token)s"
 msgstr "Redeem token '%(token)s' deactivated."
 
-msgid "nav_channels_all"
-msgstr "all"
-
-msgid "nav_channels_accepted"
-msgstr "accepted"
-
-msgid "nav_channels_pending"
-msgstr "pending"
-
-msgid "nav_channels_planned"
-msgstr "planned"
-
-msgid "nav_channels_rejected"
-msgstr "rejected"
-
-msgid "nav_channels_hidden"
-msgstr "hidden"
-
 msgid "nav_conference"
 msgstr "Conference"
 
diff --git a/src/backoffice/templates/backoffice/assembly_basicdata.html b/src/backoffice/templates/backoffice/assembly_basicdata.html
index 4779b582fb8f1285464aff7c5eb3f2328486ba1e..203f33dbc539852e6a767771915adbffa08f88f3 100644
--- a/src/backoffice/templates/backoffice/assembly_basicdata.html
+++ b/src/backoffice/templates/backoffice/assembly_basicdata.html
@@ -40,15 +40,9 @@
     </div>
   </div>
   <div class="col-md-3">
-    <label class="form-label" for="id_state_assembly">{% trans "Assembly__state_assembly" %}</label>
-    <div id="id_state_assembly">{{ form.instance.get_state_assembly_display }}</div>
+    <label class="form-label" for="id_state">{% trans "Assembly__state" %}</label>
+    <div id="id_state">{{ form.instance.get_state_display }}</div>
   </div>
-  {% if conference.support_channels %}
-    <div class="col-md-3">
-      <label class="form-label" for="id_state_channel">{% trans "Assembly__state_channel" %}</label>
-      <div id="id_state_channel">{{ form.instance.get_state_channel_display }}</div>
-    </div>
-  {% endif %}
 </div>
 
 <div class="row">
diff --git a/src/backoffice/templates/backoffice/assembly_detail.html b/src/backoffice/templates/backoffice/assembly_detail.html
index 1f4d046693437c446f94252a762a27b403dc59c0..3e7357cb70da91697b85637c56aca7ac03d139f2 100644
--- a/src/backoffice/templates/backoffice/assembly_detail.html
+++ b/src/backoffice/templates/backoffice/assembly_detail.html
@@ -85,28 +85,21 @@ $(document).ready(() => {
         <div class="card-body text-center">
           <p>{{ assembly.get_assembly_type_display }}</p>
           <p>
-            {% translate "Assembly__state_assembly" %}
+            {% translate "Assembly__state" %}
             <br>
-            <span class="font-weight-bold {% if assembly.is_public %} text-success {% elif assembly.state_assembly == 'rejected' %} text-danger {% endif %}">{{ assembly.get_state_assembly_display }}</span>
+            <span class="font-weight-bold {% if assembly.is_public %} text-success {% elif assembly.state == 'rejected' %} text-danger {% endif %}">{{ assembly.get_state_display }}</span>
           </p>
-          {% if conference.support_channels %}
-            <p>
-              {% translate "Assembly__state_channel" %}
-              <br>
-              <span class="font-weight-bold {% if assembly.is_public %} text-success {% elif assembly.state_channel == 'rejected' %} text-danger {% endif %}">{{ assembly.get_state_channel_display }}</span>
-            </p>
-          {% endif %}
         </div>
       </div>
     </div>
   </div>
 
-  {% if assembly.state_assembly == "planned" %}
+  {% if assembly.state == "planned" %}
     <div class="row mt-3">
       <div class="col-md-12">
         <div class="card">
-          <div class="card-header bg-warning">{% trans "Assembly__state_assembly-planned__hint" %}</div>
-          <div class="card-body">{% blocktrans %}Assembly__state_assembly-planned__description{% endblocktrans %}</div>
+          <div class="card-header bg-warning">{% trans "Assembly__state__planned__hint" %}</div>
+          <div class="card-body">{% blocktrans %}Assembly__state__planned__description{% endblocktrans %}</div>
         </div>
       </div>
     </div>
diff --git a/src/backoffice/templates/backoffice/assembly_list.html b/src/backoffice/templates/backoffice/assembly_list.html
index 00232d8b7de0f351a2895775b6b2e1b2de09ce8e..3824104a00033426ca879adb9b92fd950da6dae8 100644
--- a/src/backoffice/templates/backoffice/assembly_list.html
+++ b/src/backoffice/templates/backoffice/assembly_list.html
@@ -65,10 +65,7 @@
             {% endif %}
             <th>{% trans "Assembly__name" %}</th>
             <th title="{% trans "Assembly__is_official" %}">{% trans "Assembly__is_official__short" %}</th>
-            <th>{% trans "Assembly__state_assembly" %}</th>
-            {% if conference.support_channels %}
-              <th>{% trans "Assembly__state_channel" %}</th>
-            {% endif %}
+            <th>{% trans "Assembly__state" %}</th>
             <th>{% trans "Assembly__last_update_staff" %}</th>
             <th>{% trans "Assembly__last_update_assembly" %}</th>
           </tr>
@@ -86,22 +83,14 @@
                 {% endspaceless %}
               </td>
               <td>{{ assembly.is_official|yesno }}</td>
-              <td class="{% if assembly.is_public_assembly %}text-success{% elif assembly.state_assembly == 'rejected' %}text-danger{% endif %}">
-                {% if assembly.state_assembly != 'none' %}
-                  {{ assembly.get_state_assembly_display }}
+              <td class="{% if assembly.is_public %}text-success{% elif assembly.state == 'rejected' %}text-danger{% endif %}">
+                {% if assembly.state != 'none' %}
+                  {{ assembly.get_state_display }}
                 {% else %}
                   -
                 {% endif %}
               </td>
-              {% if conference.support_channels %}
-                <td class="{% if assembly.is_public_channel %}text-success{% elif assembly.state_channel == 'rejected' %}text-danger{% endif %}">
-                  {% if assembly.state_channel != 'none' %}
-                    {{ assembly.get_state_channel_display }}
-                  {% else %}
-                    -
-                  {% endif %}
-                </td>
-              {% endif %}
+
               <td>
                 <span class="{% if assembly.last_activity_log_staff > assembly.last_activity_log_assembly %}text-success{% endif %}"
                       title="{% trans "Assembly__last_update_staff" %}">{{ assembly.last_activity_log_staff|naturaltime }}</span>
diff --git a/src/backoffice/templates/backoffice/assembly_members.html b/src/backoffice/templates/backoffice/assembly_members.html
index 709497ad1a67ebff7983a1e0347f81c0a728cab1..3b8a197fb8ae8b514dfa2a31f9ad496942ab7a66 100644
--- a/src/backoffice/templates/backoffice/assembly_members.html
+++ b/src/backoffice/templates/backoffice/assembly_members.html
@@ -26,13 +26,7 @@
                   {% if staff_mode %}<th>Mail</th>{% endif %}
                   <th title="{% trans "AssemblyMember__is_representative" %}">R</th>
                   <th title="{% trans "AssemblyMember__can_manage_assembly" %}">M</th>
-                  {% if assembly.is_channel %}
-                    <th title="{% trans "AssemblyMember__is_content_coordinator" %}">C</th>
-                    <th title="{% trans "AssemblyMember__is_production_coordinator" %}">P</th>
-                  {% endif %}
-                  {% if assembly.is_assembly %}
-                    <th title="{% trans "AssemblyMember__is_technical_contact" %}">T</th>
-                  {% endif %}
+                  <th title="{% trans "AssemblyMember__is_technical_contact" %}">T</th>
                   <th title="{% trans "AssemblyMember__show_public" %}">S</th>
                   {% if can_manage %}
                     <th>{% trans "AssemblyMember__actions" %}</th>
@@ -66,31 +60,13 @@
                         -
                       {% endif %}
                     </td>
-                    {% if assembly.is_channel %}
-                      <td>
-                        {% if member.is_content_coordinator %}
-                          C
-                        {% else %}
-                          -
-                        {% endif %}
-                      </td>
-                      <td>
-                        {% if member.is_production_coordinator %}
-                          P
-                        {% else %}
-                          -
-                        {% endif %}
-                      </td>
-                    {% endif %}
-                    {% if assembly.is_assembly %}
-                      <td>
-                        {% if member.is_technical_contact %}
-                          T
-                        {% else %}
-                          -
-                        {% endif %}
-                      </td>
-                    {% endif %}
+                    <td>
+                      {% if member.is_technical_contact %}
+                        T
+                      {% else %}
+                        -
+                      {% endif %}
+                    </td>
                     <td>
                       {% if member.show_public %}
                         S
diff --git a/src/backoffice/templates/backoffice/assemblyteam_assembly_detail.html b/src/backoffice/templates/backoffice/assemblyteam_assembly_detail.html
index cbede58d16260ff0a9269ae24ea52782ea4a36b1..e652b8c69d00b202bd44651d0290c6773a4d6317 100644
--- a/src/backoffice/templates/backoffice/assemblyteam_assembly_detail.html
+++ b/src/backoffice/templates/backoffice/assemblyteam_assembly_detail.html
@@ -86,18 +86,18 @@
       <div class="row mb-3">
         <div class="col-md-8">
           <div class="card">
-            <div class="card-header">{% trans "Assembly__state_assembly" %}</div>
+            <div class="card-header">{% trans "Assembly__state" %}</div>
             <div class="card-body">
               <div class="dropdown text-center">
-                <span class="fs-4 {% if object.is_public_assembly %}text-success{% elif object.state_assembly == 'rejected' %}text-danger{% endif %}">
-                  {{ object.get_state_assembly_display }}
+                <span class="fs-4 {% if object.is_public %}text-success{% elif object.state == 'rejected' %}text-danger{% endif %}">
+                  {{ object.get_state_display }}
                 </span>
                 <btn class="btn btn-sm btn-primary dropdown-toggle" role="button" data-bs-toggle="dropdown">
                 <i class="bi bi-pencil"></i>
                 </btn>
 
                 <ul class="dropdown-menu">
-                  {% if assembly.state_assembly == assembly.State.PLANNED %}
+                  {% if assembly.state == assembly.State.PLANNED %}
                     <li>
                       <a class="dropdown-item text-danger"
                          role="button"
@@ -113,7 +113,7 @@
                       </a>
                     </li>
 
-                  {% elif assembly.state_assembly == assembly.State.REGISTERED %}
+                  {% elif assembly.state == assembly.State.REGISTERED %}
                     <li>
                       <a class="dropdown-item text-success"
                          role="button"
@@ -136,7 +136,7 @@
                       </a>
                     </li>
 
-                  {% elif assembly.state_assembly == assembly.State.REJECTED %}
+                  {% elif assembly.state == assembly.State.REJECTED %}
                     <li>
                       <a class="dropdown-item text-warning"
                          role="button"
@@ -147,7 +147,7 @@
 
                   {% else %}
                     {% if assembly.is_public %}
-                      {% if assembly.state_assembly != 'placed' %}
+                      {% if assembly.state != 'placed' %}
                         <li>
                           <a class="dropdown-item text-secondary"
                              role="button"
@@ -156,7 +156,7 @@
                           </a>
                         </li>
                       {% endif %}
-                      {% if assembly.state_assembly != 'arrived' %}
+                      {% if assembly.state != 'arrived' %}
                         <li>
                           <a class="dropdown-item text-info"
                              role="button"
@@ -165,7 +165,7 @@
                           </a>
                         </li>
                       {% endif %}
-                      {% if assembly.state_assembly != 'confirmed' %}
+                      {% if assembly.state != 'confirmed' %}
                         <li>
                           <a class="dropdown-item text-success"
                              role="button"
diff --git a/src/backoffice/templates/backoffice/assemblyteam_editposition.html b/src/backoffice/templates/backoffice/assemblyteam_editposition.html
index 6770b6ad946914b325d46832c924527a8b6ade04..f05ac91b0645a8d7b4498f1802931ef5b9981dda 100644
--- a/src/backoffice/templates/backoffice/assemblyteam_editposition.html
+++ b/src/backoffice/templates/backoffice/assemblyteam_editposition.html
@@ -23,7 +23,7 @@
             <input type="hidden" name="value" value="{{ new_value }}">
 
             <p>{% trans "Assembly__slug" %}: {{ assembly.slug }}</p>
-            <p>{% trans "Assembly__state_assembly" %}: {{ assembly.get_state_assembly_display }}</p>
+            <p>{% trans "Assembly__state" %}: {{ assembly.get_state_display }}</p>
 
             {% include "core/map.html" with map_config=conference.map_config.backoffice poi_id="poi" areas_id="areas" floor_id="floor" %}
 
diff --git a/src/backoffice/templates/backoffice/assemblyteam_editstate.html b/src/backoffice/templates/backoffice/assemblyteam_editstate.html
index 11d3f279503600963c2a4c4948d680ed78b264f8..79a88978f05754a0a2a5e85da6bd23ace662bee3 100644
--- a/src/backoffice/templates/backoffice/assemblyteam_editstate.html
+++ b/src/backoffice/templates/backoffice/assemblyteam_editstate.html
@@ -24,7 +24,7 @@
 
             <p>{% trans "Assembly__slug" %}: {{ assembly.slug }}</p>
             <p>
-              {% trans "Assembly__state_assembly" %}: <s class="text-danger">{{ assembly.get_state_assembly_display }}</s> <span class="text-success">{{ new_value_translated }}</span>
+              {% trans "Assembly__state" %}: <s class="text-danger">{{ assembly.get_state_display }}</s> <span class="text-success">{{ new_value_translated }}</span>
             </p>
 
             <p>{% trans "assemblyteam_addcomment_field" %}:</p>
diff --git a/src/backoffice/templates/backoffice/index.html b/src/backoffice/templates/backoffice/index.html
index 693606dc0fba264f8774e59ba73410eaf3a5dd79..91ae8119efd69a8e031c1a1c69000f29295be681 100644
--- a/src/backoffice/templates/backoffice/index.html
+++ b/src/backoffice/templates/backoffice/index.html
@@ -26,10 +26,10 @@
                   <a href="{% url 'backoffice:assembly' pk=assembly.id %}">{{ assembly.name }}</a>
                 </td>
                 <td>
-                  {{ assembly.get_state_assembly_display }}
-                  {% if assembly.state_assembly == 'planned' %}
+                  {{ assembly.get_state_display }}
+                  {% if assembly.state == 'planned' %}
                     <span class="text-danger font-weight-bold"
-                          title="{% trans "Assembly__state_assembly-planned__hint" %}">⚠</span>
+                          title="{% trans "Assembly__state__planned__hint" %}">⚠</span>
                   {% endif %}
                 </td>
               </tr>
diff --git a/src/backoffice/templates/backoffice/moderation_assembly-detail.html b/src/backoffice/templates/backoffice/moderation_assembly-detail.html
index 282cec37c9cf1bc6e776e26e81a44693f0315fae..3e24840ed766c168c240db3ad3817dc109306aaf 100644
--- a/src/backoffice/templates/backoffice/moderation_assembly-detail.html
+++ b/src/backoffice/templates/backoffice/moderation_assembly-detail.html
@@ -54,9 +54,9 @@
             <dd class="col-sm-9">
               {{ object.is_official|yesno }}
             </dd>
-            <dt class="col-sm-3">{% trans "Assembly__state_assembly" %}:</dt>
+            <dt class="col-sm-3">{% trans "Assembly__state" %}:</dt>
             <dd class="col-sm-9">
-              {{ object.get_state_assembly_display }}
+              {{ object.get_state_display }}
             </dd>
           </dl>
         </div>
diff --git a/src/backoffice/templates/backoffice/moderation_assembly-item.html b/src/backoffice/templates/backoffice/moderation_assembly-item.html
index b2a933c852dee083c5e850696d732fdbe8fa8826..defe3952107f2d1121ab2a55d72c3c589d845e00 100644
--- a/src/backoffice/templates/backoffice/moderation_assembly-item.html
+++ b/src/backoffice/templates/backoffice/moderation_assembly-item.html
@@ -5,7 +5,7 @@
    class="fw-bold">{{ assembly.slug }}</a>" <small>{{ assembly.name }}</small>
     <br>
 
-    <span class="text-{% if assembly.is_public %}success{% elif assembly.state_assembly != 'hidden' %}danger{% else %}secondary{% endif %}">{{ assembly.get_state_assembly_display }}</span>
+    <span class="text-{% if assembly.is_public %}success{% elif assembly.state != 'hidden' %}danger{% else %}secondary{% endif %}">{{ assembly.get_state_display }}</span>
     <br>
 
     <span class="text-muted">Kontakte:</span>
diff --git a/src/backoffice/templates/backoffice/moderation_assembly-list.html b/src/backoffice/templates/backoffice/moderation_assembly-list.html
index 909e2c49cad869c6f6689e6bc69b642fed11dbb2..428b542b565baee0133e50f83dbf83b035192087 100644
--- a/src/backoffice/templates/backoffice/moderation_assembly-list.html
+++ b/src/backoffice/templates/backoffice/moderation_assembly-list.html
@@ -66,10 +66,7 @@
             <th>{% trans "Assembly__slug" %}</th>
             <th>{% trans "Assembly__name" %}</th>
             <th title="{% trans "Assembly__is_official" %}">{% trans "Assembly__is_official__short" %}</th>
-            <th>{% trans "Assembly__state_assembly" %}</th>
-            {% if conference.support_channels %}
-              <th>{% trans "Assembly__state_channel" %}</th>
-            {% endif %}
+            <th>{% trans "Assembly__state" %}</th>
             <th>{% trans "Assembly__last_update" %}</th>
           </tr>
         </thead>
@@ -94,22 +91,13 @@
                 {% endspaceless %}
               </td>
               <td>{{ assembly.is_official|yesno }}</td>
-              <td class="{% if assembly.is_public_assembly %}text-success{% elif assembly.state_assembly == 'rejected' %}text-danger{% endif %}">
-                {% if assembly.state_assembly != 'none' %}
-                  {{ assembly.get_state_assembly_display }}
+              <td class="{% if assembly.is_public %}text-success{% elif assembly.state == 'rejected' %}text-danger{% endif %}">
+                {% if assembly.state != 'none' %}
+                  {{ assembly.get_state_display }}
                 {% else %}
                   -
                 {% endif %}
               </td>
-              {% if conference.support_channels %}
-                <td class="{% if assembly.is_public_channel %}text-success{% elif assembly.state_channel == 'rejected' %}text-danger{% endif %}">
-                  {% if assembly.state_channel != 'none' %}
-                    {{ assembly.get_state_channel_display }}
-                  {% else %}
-                    -
-                  {% endif %}
-                </td>
-              {% endif %}
               <td>
                 {% if assembly.last_update_assembly > assembly.last_update_staff %}
                   <span title="{% trans "Assembly__last_update_assembly" %}">{{ assembly.last_update_assembly|naturaltime }}</span>
diff --git a/src/backoffice/templates/backoffice/wa-map-list.html b/src/backoffice/templates/backoffice/wa-map-list.html
index 95e2c94eefdbdad812151fcc6376231d2ad66bf9..018fbe834d19ae72b9cc6de7ae0a177dd18440a4 100644
--- a/src/backoffice/templates/backoffice/wa-map-list.html
+++ b/src/backoffice/templates/backoffice/wa-map-list.html
@@ -68,7 +68,7 @@
                 <a href="{% url 'backoffice:workadventure-map-detail' pk=obj.pk %}">{{ obj.name|default:"-?-" }}</a>
               </td>
               <td>
-                <span class="{% if obj.assembly.is_public_assembly %}text-success{% else %}text-danger{% endif %}">Assembly</span>
+                <span class="{% if obj.assembly.is_public %}text-success{% else %}text-danger{% endif %}">Assembly</span>
                 {% include "backoffice/_room_backend_status.html" with object=obj backend_status_display="Backend" %}
                 {% include "backoffice/_room_wa_map_status.html" with object=obj display="Map" %}
               </td>
diff --git a/src/backoffice/tests/assemblies.py b/src/backoffice/tests/assemblies.py
index 0d19efc8a59f032b6c892ba2144319b1fdd100fb..a51bfd9d6c678373d3164233883bd7d5a76dccdd 100644
--- a/src/backoffice/tests/assemblies.py
+++ b/src/backoffice/tests/assemblies.py
@@ -10,9 +10,7 @@ from backoffice.tests import BackOfficeTestCase
 class AssemblyListViewTest(BackOfficeTestCase):
     def setUp(self):
         super().setUp()
-        self.assemblies = [
-            Assembly(slug=a, name=a, is_virtual=True, conference_id=self.conf.id, state_assembly=Assembly.State.ACCEPTED) for a in ('a1', 'a2', 'a3')
-        ]
+        self.assemblies = [Assembly(slug=a, name=a, is_virtual=True, conference_id=self.conf.id, state=Assembly.State.ACCEPTED) for a in ('a1', 'a2', 'a3')]
         for a in self.assemblies:
             a.save()
         self.assembly_links = [AssemblyLink(a=self.assemblies[0], b=self.assemblies[1]), AssemblyLink(a=self.assemblies[0], b=self.assemblies[2])]
@@ -91,7 +89,7 @@ class AssemblyCreateViewTest(BackOfficeTestCase):
 class AssemblyMembersViewTest(BackOfficeTestCase):
     def setUp(self):
         super().setUp()
-        self.assembly = Assembly.objects.create(slug='a1', name='a1', is_physical=True, conference_id=self.conf.id, state_assembly=Assembly.State.ACCEPTED)
+        self.assembly = Assembly.objects.create(slug='a1', name='a1', is_physical=True, conference_id=self.conf.id, state=Assembly.State.ACCEPTED)
         self.users: list[PlatformUser] = [
             PlatformUser.objects.create(
                 username=a,
diff --git a/src/backoffice/urls.py b/src/backoffice/urls.py
index 16180a58bcaf018cff8148c8a7e4a60cfc264338..43cc00aaf9255fab6617727c66e5186ac0477164 100644
--- a/src/backoffice/urls.py
+++ b/src/backoffice/urls.py
@@ -6,7 +6,6 @@ from backoffice.views import (
     assemblyteam,
     auth,
     badges,
-    channelteam,
     events,
     invitations,
     misc,
@@ -64,8 +63,6 @@ urlpatterns = [
     path('wiki/page/<uuid:pk>/delete-revision', wiki.PageRevisionDeleteView.as_view(), name='wiki-page-revision-delete'),
     path('assemblies', assemblyteam.AssembliesView.as_view(), name='assemblies'),
     path('assemblies/list/<str:variant>', assemblyteam.AssembliesListsView.as_view(), name='assemblieslist'),
-    path('channels', channelteam.ChannelsView.as_view(), name='channels'),
-    path('channels/list/<str:variant>', channelteam.ChannelsListView.as_view(), name='channelslist'),
     path('assemblyteam/<uuid:pk>', assemblyteam.AssemblyView.as_view(), name='assemblyteam-detail'),
     path('assemblyteam/<uuid:pk>/state', assemblyteam.AssemblyEditStateView.as_view(), name='assemblyteam-editstate'),
     path('assemblyteam/<uuid:pk>/hierarchy', assemblyteam.AssemblyEditHierarchyView.as_view(), name='assemblyteam-edithierarchy'),
diff --git a/src/backoffice/views/assemblies/assemblies.py b/src/backoffice/views/assemblies/assemblies.py
index 1645784cb04eeb52ff7f0ae6104e4a3ac960a421..12c8cc40e9413ff41c77685b00feb1dacbcba5e3 100644
--- a/src/backoffice/views/assemblies/assemblies.py
+++ b/src/backoffice/views/assemblies/assemblies.py
@@ -87,8 +87,7 @@ class AssemblyCreateView(ConferenceLoginRequiredMixin, CreateView):
 
     def form_valid(self, form):
         form.instance.conference = self.conference
-        form.instance.state_assembly = Assembly.State.PLANNED if form.cleaned_data['is_assembly'] else Assembly.State.NONE
-        form.instance.state_channel = Assembly.State.PLANNED if self.conference.support_channels and form.cleaned_data['is_channel'] else Assembly.State.NONE
+        form.instance.state = Assembly.State.PLANNED
 
         form.instance.ensure_single_type_conference_match()
 
@@ -104,8 +103,7 @@ class AssemblyCreateView(ConferenceLoginRequiredMixin, CreateView):
             kind=ActivityLogEntry.Kind.ENTITY,
             slug=ActivityLogChange(new=form.instance.slug),
             name=ActivityLogChange(new=form.instance.name),
-            state_assembly=ActivityLogChange(new=form.instance.state_assembly),
-            state_channel=ActivityLogChange(new=form.instance.state_channel),
+            state=ActivityLogChange(new=form.instance.state),
         )
 
         # add current user as first member of the new assembly (so that editing is possible)
@@ -150,7 +148,6 @@ class AssemblyUpdateView(AssemblyMixin, UpdateView):
         kwargs['staff_access'] = self.staff_access
         kwargs['staff_mode'] = self.staff_mode
         kwargs['assembly_staff_access'] = self.assembly_staff_access
-        kwargs['channel_staff_access'] = self.channel_staff_access
 
         return kwargs
 
@@ -272,13 +269,10 @@ class AssemblyUpdateView(AssemblyMixin, UpdateView):
         for fld, change in assembly.ensure_single_type_conference_match().items():
             changes[fld] = change
 
-        # auto-advance assembly/channel states from 'planned' to 'registered' on (first) save
-        if assembly.state_assembly == Assembly.State.PLANNED and (assembly.user_can_manage(self.request.user) or not self.staff_mode):
-            assembly.state_assembly = Assembly.State.REGISTERED
-            changes['state_assembly'] = (Assembly.State.PLANNED, Assembly.State.REGISTERED)
-        if assembly.state_channel == Assembly.State.PLANNED and (assembly.user_can_manage(self.request.user) or not self.staff_mode):
-            assembly.state_channel = Assembly.State.REGISTERED
-            changes['state_channel'] = (Assembly.State.PLANNED, Assembly.State.REGISTERED)
+        # auto-advance assembly states from 'planned' to 'registered' on (first) save
+        if assembly.state == Assembly.State.PLANNED and (assembly.user_can_manage(self.request.user) or not self.staff_mode):
+            assembly.state = Assembly.State.REGISTERED
+            changes['state'] = (Assembly.State.PLANNED, Assembly.State.REGISTERED)
 
         # log latest update timestamp
         if self.staff_mode and not assembly.user_can_manage(self.request.user):
diff --git a/src/backoffice/views/assemblies/members.py b/src/backoffice/views/assemblies/members.py
index 57da50f9f198388ab6998addac24e7de0eefb98e..edd2866c2e43003a98651ccfbf672a175146f7a5 100644
--- a/src/backoffice/views/assemblies/members.py
+++ b/src/backoffice/views/assemblies/members.py
@@ -158,17 +158,6 @@ class MembersUpdateView(AssemblyMixin, UpdateView):
     template_name = 'backoffice/assembly_members_edit.html'
     form_class = AssemblyMemberEditForm
 
-    def get_form(self, *args, **kwargs):
-        frm = super().get_form(*args, **kwargs)
-
-        if not self.object.assembly.is_assembly:
-            del frm.fields['is_technical_contact']
-        if not self.object.assembly.is_channel:
-            del frm.fields['is_content_coordinator']
-            del frm.fields['is_production_coordinator']
-
-        return frm
-
     def get_object(self, queryset: QuerySet['AssemblyMember'] | None = None):
         queryset = queryset or self.assembly.members.all()
         try:
diff --git a/src/backoffice/views/assemblies/rooms.py b/src/backoffice/views/assemblies/rooms.py
index 3d704325c025d66eb50c5a7d72e8107929db998a..e6809f7f008395eb4420e4b39cca733386138d34 100644
--- a/src/backoffice/views/assemblies/rooms.py
+++ b/src/backoffice/views/assemblies/rooms.py
@@ -1,4 +1,5 @@
 import logging
+from typing import Any
 
 from django.conf import settings
 from django.contrib import messages
@@ -11,7 +12,7 @@ from django.views.generic import View
 from django.views.generic.edit import CreateView, FormView, UpdateView
 
 from core.integrations import BigBlueButton, Hangar, IntegrationError, WorkAdventure
-from core.models.conference import ConferenceExportCache
+from core.models.conference import ConferenceExportCache, ConferenceMember
 from core.models.events import Event
 from core.models.rooms import Room, RoomLink
 
@@ -91,10 +92,12 @@ class AssemblyRoomUpdateView(AssemblyMixin, UpdateView):
         assert room.assembly == self.assembly
         return room
 
-    def get_form_kwargs(self):
-        kwargs = super().get_form_kwargs()
-        kwargs['channel_staff'] = self.channel_staff_access
-        return kwargs
+    def get_form_kwargs(self) -> dict[str, Any]:
+        member = ConferenceMember.get_member(user=self.request.user, conference=self.conference)
+        return {
+            **super().get_form_kwargs(),
+            'schedule_admin': member.has_perms('core.scheduleadmin', require_staff=True),
+        }
 
     def get_form(self, *args, **kwargs):
         if self.object.room_type == Room.RoomType.WORKADVENTURE:
@@ -105,8 +108,7 @@ class AssemblyRoomUpdateView(AssemblyMixin, UpdateView):
             # keeping the form readonly. To make it writeable, do `return EditAssemblyRoomHangarForm(**self.get_form_kwargs())``
             return AssemblyRoomEditHangarForm(instance=self.object)
 
-        form = super().get_form(*args, **kwargs)
-        return form
+        return super().get_form(*args, **kwargs)
 
     def form_valid(self, form):
         res = super().form_valid(form)
diff --git a/src/backoffice/views/assemblyteam.py b/src/backoffice/views/assemblyteam.py
index 3e519b5fcd839d8b88df7706359506440c54507a..6cfa8ab7eff843770e983ce6d42dd18a6ae4f74f 100644
--- a/src/backoffice/views/assemblyteam.py
+++ b/src/backoffice/views/assemblyteam.py
@@ -37,16 +37,15 @@ class AssemblyTeamMixin(ConferenceLoginRequiredMixin):
     base_view_name = 'backoffice:assemblies'
     list_view_name = 'backoffice:assemblieslist'
     sidebar_caption = _('nav_assemblies')
-    status_field = 'state_assembly'
+    status_field = 'state'
 
     MODES = {
-        'all': (('XMode', Q(state_assembly__exact=Assembly.State.HIDDEN)), _('nav_assemblies_all')),
-        'accepted': (('QMode', Q(state_assembly__in=Assembly.PUBLIC_STATES)), _('nav_assemblies_accepted')),
-        'pending': (('QMode', Q(state_assembly__in=[Assembly.State.REGISTERED])), _('nav_assemblies_pending')),
-        'planned': (('QMode', Q(state_assembly__in=[Assembly.State.PLANNED])), _('nav_assemblies_planned')),
-        'rejected': (('QMode', Q(state_assembly__in=[Assembly.State.REJECTED])), _('nav_assemblies_rejected')),
-        'hidden': (('QMode', Q(state_assembly__in=[Assembly.State.HIDDEN])), _('nav_assemblies_hidden')),
-        'not_selected': (('QMode', Q(state_assembly__in=[Assembly.State.NONE])), _('nav_assemblies_not_selected')),
+        'all': (('XMode', Q(state__exact=Assembly.State.HIDDEN)), _('nav_assemblies_all')),
+        'accepted': (('QMode', Q(state__in=Assembly.PUBLIC_STATES)), _('nav_assemblies_accepted')),
+        'pending': (('QMode', Q(state__in=[Assembly.State.REGISTERED])), _('nav_assemblies_pending')),
+        'planned': (('QMode', Q(state__in=[Assembly.State.PLANNED])), _('nav_assemblies_planned')),
+        'rejected': (('QMode', Q(state__in=[Assembly.State.REJECTED])), _('nav_assemblies_rejected')),
+        'hidden': (('QMode', Q(state__in=[Assembly.State.HIDDEN])), _('nav_assemblies_hidden')),
     }
 
     def get_context_data(self, **kwargs):
@@ -129,16 +128,6 @@ class AssembliesListMixin(AssemblyTeamMixin, FilteredListView):
         mode = (self.request.POST if self.request.method == 'POST' else self.request.GET).get('mode', self.default_assemblies_mode)
         query_filters = {}
 
-        if mode == 'not_selected':
-            pass
-        elif self.active_page == 'assemblies':
-            query_filters['!state_assembly'] = Assembly.State.NONE
-        elif self.active_page == 'channels':
-            query_filters['!state_channel'] = Assembly.State.NONE
-        else:
-            logging.warning('AssembliesListMixin: unexpected active_page="%s"', self.active_page)
-            return Assembly.objects.none()
-
         if mode in self.MODES:
             query_filters[self.MODES[mode][0][0]] = self.MODES[mode][0][1]
         else:
@@ -463,16 +452,16 @@ class AssemblyEditStateView(SingleAssemblyTeamMixin, View):
 
         comment = request.POST.get('comment', '').strip()
 
-        old_value = assembly.state_assembly
-        assembly.state_assembly = value
-        assembly.save(update_fields=['state_assembly'])
+        old_value = assembly.state
+        assembly.state = value
+        assembly.save(update_fields=['state'])
         assembly.log_activity(
             user=self.request.user,
             kind=ActivityLogEntry.Kind.STAFF,
             comment=comment if comment else None,
-            state_assembly=ActivityLogChange(
+            state=ActivityLogChange(
                 old=old_value,
-                new=assembly.state_assembly,
+                new=assembly.state,
             ),
         )
 
@@ -587,7 +576,7 @@ class AssemblyEditPlacementView(SingleAssemblyTeamMixin, View):
         comment = request.POST.get('comment', '').strip()
 
         old_values = {
-            'state_assembly': assembly.state_assembly,
+            'state': assembly.state,
             'location_point': assembly.get_location_point_xy(),
             'location_boundaries': assembly.get_location_boundaries_xy(),
             'location_floor': assembly.get_location_floor_index(),
@@ -637,23 +626,23 @@ class AssemblyEditPlacementView(SingleAssemblyTeamMixin, View):
         if action == 'publish':
             # if assembly.location_point is not None or assembly.location_boundaries is not None:
             if assembly.location_data.get('point') or assembly.location_data.get('boundaries'):
-                assembly.state_assembly = Assembly.State.PLACED
-                changes['state_assembly'] = assembly.state_assembly
+                assembly.state = Assembly.State.PLACED
+                changes['state'] = assembly.state
             else:
                 messages.warning(request, gettext('assemblyedit_position_missingonpublish'))
                 return redirect('backoffice:assemblyteam-editposition', pk=assembly.pk)
 
         elif action == 'recall':
             if assembly.is_placed:
-                assembly.state_assembly = Assembly.State.ACCEPTED
-                changes['state_assembly'] = assembly.state_assembly
+                assembly.state = Assembly.State.ACCEPTED
+                changes['state'] = assembly.state
             else:
                 messages.warning(request, gettext('assemblyedit_position_wasnotpublished'))
 
         elif action != 'save':
             messages.warning(request, gettext('assemblyedit_position_unknownaction'))
 
-        assembly.save(update_fields=['state_assembly', 'location_point', 'location_boundaries', 'location_floor', 'location_data'])
+        assembly.save(update_fields=['state', 'location_point', 'location_boundaries', 'location_floor', 'location_data'])
 
         # log the action
         messages.success(request, gettext('assemblyedit_changedposition'))
@@ -675,14 +664,14 @@ class AssemblyEditPlacementView(SingleAssemblyTeamMixin, View):
             **{k: ActivityLogChange(old=old_values[k], new=v) for k, v in changes.items() if old_values[k] != v},
         )
 
-        if assembly.state_assembly != old_values['state_assembly']:
+        if assembly.state != old_values['state']:
             messages.success(request, gettext('assemblyedit_changedstate'))
             logger.info(
                 'Assembly "%(assembly_slug)s" (%(assembly_pk)s): changed state to "%(state)s" upon request by <%(user)s>.',
                 {
                     'assembly_slug': assembly.slug,
                     'assembly_pk': assembly.pk,
-                    'state': assembly.state_assembly,
+                    'state': assembly.state,
                     'user': self.request.user.username,
                 },
             )
diff --git a/src/backoffice/views/channelteam.py b/src/backoffice/views/channelteam.py
deleted file mode 100644
index e8c259fdd23cc9c41e1ace79b024c0fdf5a045bf..0000000000000000000000000000000000000000
--- a/src/backoffice/views/channelteam.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from django.db.models import Q
-from django.utils.translation import gettext_lazy as _
-
-from core.models.assemblies import Assembly
-
-from .assemblyteam import AssembliesListsView, AssembliesView
-
-
-class ChannelsMixin:
-    """sets options that configure the Assemblies views to work in Channels mode"""
-
-    MODES = {
-        'all': (Q(), _('nav_channels_all')),
-        'accepted': (Q(state_channel__in=Assembly.PUBLIC_STATES), _('nav_channels_accepted')),
-        'pending': (Q(state_channel__in=[Assembly.State.REGISTERED]), _('nav_channels_pending')),
-        'planned': (Q(state_channel__in=[Assembly.State.PLANNED]), _('nav_channels_planned')),
-        'rejected': (Q(state_channel__in=[Assembly.State.REJECTED]), _('nav_channels_rejected')),
-        'hidden': (Q(state_channel__in=[Assembly.State.HIDDEN]), _('nav_channels_hidden')),
-    }
-    permission_required = ['core.channel_team']
-    active_page = 'channels'
-    base_view_name = 'backoffice:channels'
-    list_view_name = 'backoffice:channelslist'
-    sidebar_caption = _('nav_channels')
-    status_field = 'state_channel'
-
-
-class ChannelsView(ChannelsMixin, AssembliesView):
-    pass
-
-
-class ChannelsListView(ChannelsMixin, AssembliesListsView):
-    pass
diff --git a/src/backoffice/views/mixins.py b/src/backoffice/views/mixins.py
index c29a4c610e8f40ea899220f3b8f2767dc4b36379..42fa2548aaa36121098fc4b6e06dc56f2bd4552f 100644
--- a/src/backoffice/views/mixins.py
+++ b/src/backoffice/views/mixins.py
@@ -60,14 +60,6 @@ class ConferenceRequiredMixinBase:
     def is_assembly_team(self):
         return self.conferencemember.user.is_authenticated and self.conferencemember.has_perms('core.assembly_team', require_staff=True)
 
-    @property
-    def is_channel_team(self):
-        return (
-            self.conference.support_channels
-            and self.conferencemember.user.is_authenticated
-            and self.conferencemember.has_perms('core.channel_team', require_staff=True)
-        )
-
     def dispatch(self, request, *args, **kwargs):
         if self.require_conference and self.conference is None:
             return redirect('backoffice:conferences')
@@ -96,7 +88,6 @@ class ConferenceRequiredMixinBase:
                 {
                     'has_sos': self.conferencemember is not None,
                     'has_assemblies': self.is_assembly_team,
-                    'has_channel': self.is_channel_team,
                     'has_pages': self.conferencemember.has_perms('core.static_pages', require_staff=True),
                     'has_map': self.conferencemember.has_perms('core.map_edit', require_staff=True),
                     'has_assembly_registration_admin': self.conferencemember.has_perms('core.assembly_registration_admin', require_staff=True),
@@ -111,7 +102,6 @@ class ConferenceRequiredMixinBase:
             context.update(
                 {
                     'has_assemblies': False,
-                    'has_channel': False,
                     'has_pages': False,
                     'has_map': False,
                     'has_assembly_registration_admin': False,
@@ -171,10 +161,8 @@ class AssemblyMixinBase:
         self._can_manage = None
         # if _staff_access is set, extra staff fields can be modified (internal comment, is_official)
         self._staff_access = False
-        # if _assembly_staff_access is set, the field state_assembly can be modified
+        # if _assembly_staff_access is set, the field state can be modified
         self._assembly_staff_access = False
-        # if _channels_staff_access is set, the field state_channel can be modified
-        self._channels_staff_access = False
 
         # configures the staff warning
         self._staff_mode = False
@@ -188,24 +176,10 @@ class AssemblyMixinBase:
         # check if it's the assembly team
         if self.conferencemember.has_perms('core.assembly_team', 'core.change_assembly', require_staff=True):
             self._assembly_staff_access = True
-            self._staff_access = self._staff_access or assembly.state_assembly != Assembly.State.NONE
-            self._staff_mode = True
-
-        # check if it's the channel team
-        if self.conferencemember.has_perms('core.channel_team', 'core.change_assembly', require_staff=True):
-            self._channels_staff_access = True
-            self._staff_access = self._staff_access or assembly.state_channel != Assembly.State.NONE
+            self._staff_access = self._staff_access
             self._staff_mode = True
-
-        # check if the current user is associated as a contact
-        if assembly.has_user(self.request.user):
-            # don't set self._staff_mode = False here as this would prevent assembly team members to edit their own assemblies
-
-            if not self._staff_access and assembly.state_assembly in [Assembly.State.NONE] and assembly.state_channel in [Assembly.State.NONE]:
-                raise Assembly.DoesNotExist
-
         # neither owner/manager nor assembly team? go away
-        elif not self._assembly_staff_access and not self._channels_staff_access:
+        if not assembly.has_user(self.request.user) and not self._assembly_staff_access:
             raise PermissionDenied
 
         self._assembly = assembly
@@ -235,10 +209,6 @@ class AssemblyMixinBase:
     def assembly_staff_access(self):
         return self._assembly_staff_access
 
-    @property
-    def channel_staff_access(self):
-        return self._channels_staff_access
-
     @property
     def staff_mode(self):
         return self._staff_mode
diff --git a/src/backoffice/views/moderation/assemblies.py b/src/backoffice/views/moderation/assemblies.py
index c9322f8afc2ddbf5df91b98a2629501f417f6d06..b7840b6fa3ba2f8050cb5aa0ae736636b3dece96 100644
--- a/src/backoffice/views/moderation/assemblies.py
+++ b/src/backoffice/views/moderation/assemblies.py
@@ -15,7 +15,7 @@ class ModerationAssemblyListView(ModerationAdminMixin, ListView):
     template_name = 'backoffice/moderation_assembly-list.html'
 
     def get_queryset(self):
-        qs = self.conference.assemblies.exclude(state_assembly=Assembly.State.NONE).order_by('slug')
+        qs = self.conference.assemblies.all().order_by('slug')
         return qs
 
 
@@ -23,7 +23,8 @@ class ModerationAssemblyDetailView(ModerationAdminMixin, DetailView):
     template_name = 'backoffice/moderation_assembly-detail.html'
 
     def get_queryset(self):
-        qs = self.conference.assemblies.exclude(state_assembly=Assembly.State.NONE)
+        # TODO: Check if this is the correct queryset
+        qs = self.conference.assemblies.all()
         return qs
 
     def post(self, request, *args, **kwargs):
@@ -32,14 +33,11 @@ class ModerationAssemblyDetailView(ModerationAdminMixin, DetailView):
 
         if action == 'hide':
             changes = {}
-            if (prev_state_assembly := assembly.state_assembly) != Assembly.State.NONE:
-                assembly.state_assembly = Assembly.State.HIDDEN
-                changes['state_assembly'] = ActivityLogChange(old=prev_state_assembly, new=Assembly.State.HIDDEN)
-            if (prev_state_channel := assembly.state_channel) != Assembly.State.NONE:
-                assembly.state_channel = Assembly.State.HIDDEN
-                changes['state_channel'] = ActivityLogChange(old=prev_state_channel, new=Assembly.State.HIDDEN)
-
-            assembly.save(update_fields=['state_assembly', 'state_channel'])
+            previous_state = assembly.state
+            assembly.state = Assembly.State.HIDDEN
+            changes['state'] = ActivityLogChange(old=previous_state, new=Assembly.State.HIDDEN)
+
+            assembly.save(update_fields=['state'])
 
             # add log entries
             assembly.log_activity(
diff --git a/src/core/admin.py b/src/core/admin.py
index bf17eb836cacce598e207f7beba249f72ac08a87..fdf60ba0407d7521172184c291c80ead7929edc3 100644
--- a/src/core/admin.py
+++ b/src/core/admin.py
@@ -360,9 +360,9 @@ class ActivityLogEntryInline(GenericTabularInline):
 
 
 class AssemblyAdmin(GISModelAdmin):
-    list_display = ['conference', 'parent', 'slug', 'name', 'state_assembly', 'state_channel', 'is_official']
+    list_display = ['conference', 'parent', 'slug', 'name', 'state', 'is_official']
     list_display_links = ['slug', 'name']
-    list_filter = ['conference', 'parent', 'state_assembly', 'state_channel', 'is_official']
+    list_filter = ['conference', 'parent', 'state', 'is_official']
     readonly_fields = ['id', 'conference']
     search_fields = ['slug', 'name', 'description']
     inlines = [TagsInline, BadgeInline, AssemblyLinkInline, AssemblyMemberInline, ActivityLogEntryInline]
@@ -371,7 +371,7 @@ class AssemblyAdmin(GISModelAdmin):
         (
             'Organisation',
             {
-                'fields': ['id', 'conference', 'state_assembly', 'state_channel', 'hierarchy', 'parent', 'is_official'],
+                'fields': ['id', 'conference', 'state', 'hierarchy', 'parent', 'is_official'],
             },
         ),
         (
@@ -411,7 +411,7 @@ class AssemblyAdmin(GISModelAdmin):
                 (
                     'Organisation',
                     {
-                        'fields': ['id', 'conference', 'state_assembly', 'state_channel', 'hierarchy', 'is_official'],
+                        'fields': ['id', 'conference', 'state', 'hierarchy', 'is_official'],
                     },
                 ),
                 (
diff --git a/src/core/fixtures/anhalter.json b/src/core/fixtures/anhalter.json
index c34a24297f28900fbc29aa553f1fadfcb80a2a09..a6573e617872fe394618ea87c419b0ccfd592e4e 100644
--- a/src/core/fixtures/anhalter.json
+++ b/src/core/fixtures/anhalter.json
@@ -105,7 +105,7 @@
       "name": "Heart of Gold",
       "parent": null,
       "slug": "heart_of_gold",
-      "state_assembly": "confirmed",
+      "state": "confirmed",
       "assembly_link": null,
       "assembly_location": "",
       "is_physical": true,
@@ -121,7 +121,7 @@
       "description": "Wir haben da einen Computer gebaut. Und Planeten.",
       "parent": null,
       "slug": "main",
-      "state_assembly": "accepted",
+      "state": "accepted",
       "assembly_link": null,
       "assembly_location": "",
       "is_physical": true,
@@ -136,7 +136,7 @@
       "name": "Streaming",
       "parent": null,
       "slug": "media",
-      "state_assembly": "accepted",
+      "state": "accepted",
       "assembly_link": "https://streaming.media.ccc.de/",
       "assembly_location": "",
       "is_virtual": true,
@@ -151,7 +151,7 @@
       "name": "BigBlueButton",
       "parent": null,
       "slug": "bbb",
-      "state_assembly": "accepted",
+      "state": "accepted",
       "assembly_link": null,
       "assembly_location": "",
       "is_virtual": true,
diff --git a/src/core/integrations/workadventure.py b/src/core/integrations/workadventure.py
index 461339ba1cb49c33ffc3e49b3b3913ec1920be6b..ac709e0a4cc22192449485aa9438672847aa181f 100644
--- a/src/core/integrations/workadventure.py
+++ b/src/core/integrations/workadventure.py
@@ -79,7 +79,7 @@ class WorkAdventureIntegration:
         maps = {}
         for room in Room.objects.filter(conference=conference, room_type=Room.RoomType.WORKADVENTURE, blocked=False).select_related('assembly'):
             # skip non-public assemblies
-            if room.assembly is not None and room.assembly.state_assembly not in Assembly.PUBLIC_STATES:
+            if room.assembly is not None and room.assembly.state not in Assembly.PUBLIC_STATES:
                 continue
 
             # skip instances without a non-zero/-empty 'publishedSince' entry
diff --git a/src/core/locale/de/LC_MESSAGES/django.po b/src/core/locale/de/LC_MESSAGES/django.po
index 688dfe079bea5801a2835f4d419f2b64f42aa3ba..2e1ce50803fbbb6b2029cf3b554afa6c31b8bf5d 100644
--- a/src/core/locale/de/LC_MESSAGES/django.po
+++ b/src/core/locale/de/LC_MESSAGES/django.po
@@ -239,9 +239,6 @@ msgstr "gesichtet"
 msgid "Assemblies"
 msgstr ""
 
-msgid "Assembly__state-none"
-msgstr "(keine Teilnahme)"
-
 msgid "Assembly__state-planned"
 msgstr "geplant"
 
@@ -318,18 +315,12 @@ msgstr "zusätzliche JSON-Daten von der Registrierung"
 msgid "Assembly__registration_data"
 msgstr "Registrierungs-Daten"
 
-msgid "Assembly__state_assembly"
+msgid "Assembly__state"
 msgstr "Assembly Status"
 
-msgid "Assembly__state_assembly__help"
+msgid "Assembly__state__help"
 msgstr "Status der Assembly (wird vom Assembly-Team gesetzt)"
 
-msgid "Assembly__state_channel"
-msgstr "Status (Channel)"
-
-msgid "Assembly__state_channel__help"
-msgstr "Status des Channels (wird von der Aufnahmeleitung/VOC gesetzt)"
-
 msgid "Assembly__hierarchy__help"
 msgstr "Art der Lokalität/Assemblies: normal vs. Gruppierung (Habitat)"
 
@@ -649,9 +640,6 @@ msgstr "Assembly-Team: alle Assemblies verwaltbar, auch noch nicht fertig angele
 msgid "ConferenceMember__permission-assembly_registration_admin"
 msgstr "Registrierungs-Admin: Verwalten der Registrierungsinformationen für Assemblies"
 
-msgid "ConferenceMember__permission-channel_team"
-msgstr "Channel-Team: alle Assemblies verwaltbar, auch noch nicht fertig angelegte und abgelehnte sind sichtbar"
-
 msgid "ConferenceMember__permission-static_pages"
 msgstr "Statische Seiten: Verwaltung von Info-Seiten"
 
@@ -805,12 +793,6 @@ msgstr "erlaube Assemblies an entfernten Standorten (ergänzt Orts-Angabe)"
 msgid "Conference__support_assembly_remote"
 msgstr "entf. Assemblies"
 
-msgid "Conference__support_channels__help"
-msgstr "Unterstützung für Channel/Bühnen (analog zu Assemblies)"
-
-msgid "Conference__support_channels"
-msgstr "Channels"
-
 msgid "Conference__mail_footer__help"
 msgstr "Text, welcher am Ende einer Nachricht angehängt wird (z.B. in E-Mails)"
 
@@ -2357,9 +2339,6 @@ msgstr "URL"
 msgid "Voucher__target-assembly"
 msgstr "Assembly"
 
-msgid "Voucher__target-channel"
-msgstr "Channel"
-
 msgid "Voucher__target-user"
 msgstr "Nutzer"
 
diff --git a/src/core/locale/en/LC_MESSAGES/django.po b/src/core/locale/en/LC_MESSAGES/django.po
index ea7d8e254c5858b570ea1801da22fc34eaa61c0b..6d31f5173b9c198a8253e30b5b8043f0a8d26600 100644
--- a/src/core/locale/en/LC_MESSAGES/django.po
+++ b/src/core/locale/en/LC_MESSAGES/django.po
@@ -239,9 +239,6 @@ msgstr "patrolled"
 msgid "Assemblies"
 msgstr ""
 
-msgid "Assembly__state-none"
-msgstr "(no participation)"
-
 msgid "Assembly__state-planned"
 msgstr "planned"
 
@@ -318,18 +315,12 @@ msgstr "additional JSON data from registration"
 msgid "Assembly__registration_data"
 msgstr "registration data"
 
-msgid "Assembly__state_assembly"
+msgid "Assembly__state"
 msgstr "Assembly state"
 
-msgid "Assembly__state_assembly__help"
+msgid "Assembly__state__help"
 msgstr "state of this assembly (set by the assemblies team)"
 
-msgid "Assembly__state_channel"
-msgstr "state (channel)"
-
-msgid "Assembly__state_channel__help"
-msgstr "state of this channel (set by the Aufnahmeleitung)"
-
 msgid "Assembly__hierarchy__help"
 msgstr "hierarchical type of this assembly - regular vs. grouped/habitat"
 
@@ -649,9 +640,6 @@ msgstr "assemblies team: manage all assemblies, see also incomplete and rejected
 msgid "ConferenceMember__permission-assembly_registration_admin"
 msgstr "Registration-Admin: Manage registration information for assemblies"
 
-msgid "ConferenceMember__permission-channel_team"
-msgstr "channel team: manage all assemblies, see also incomplete and rejected registrations"
-
 msgid "ConferenceMember__permission-static_pages"
 msgstr "static pages: manage information pages"
 
@@ -805,12 +793,6 @@ msgstr "support assemblies at remote physical locations (adds location field)"
 msgid "Conference__support_assembly_remote"
 msgstr "remote assemblies"
 
-msgid "Conference__support_channels__help"
-msgstr "support channels/stages management (analog to assemblies)"
-
-msgid "Conference__support_channels"
-msgstr "channels"
-
 msgid "Conference__mail_footer__help"
 msgstr "text which is appended to messages sent via this conference (e.g. in emails)"
 
@@ -2355,9 +2337,6 @@ msgstr "URL"
 msgid "Voucher__target-assembly"
 msgstr "assembly"
 
-msgid "Voucher__target-channel"
-msgstr "channel"
-
 msgid "Voucher__target-user"
 msgstr "user"
 
diff --git a/src/core/management/commands/create_conference.py b/src/core/management/commands/create_conference.py
index 174a05df1bd49379149dddf95f81dbd51481d249..da4a02a89daa1a214560d7a1214f41ef21f9ea36 100644
--- a/src/core/management/commands/create_conference.py
+++ b/src/core/management/commands/create_conference.py
@@ -107,8 +107,7 @@ def seed_conference(conf: Conference, console: Console, year: int = 0):
         slug='sos',
         name='Self Organized Sessions',
         is_official=True,
-        state_assembly=Assembly.State.HIDDEN,
-        state_channel=Assembly.State.NONE,
+        state=Assembly.State.HIDDEN,
     )
 
     # create navigation (top level)
diff --git a/src/core/management/commands/sanitize_database.py b/src/core/management/commands/sanitize_database.py
index c9b268407ff695a13739b9ab62fd0229d5e35c5f..0c5006b095b3d401c6cdf9d00bd864d7c6b95717 100644
--- a/src/core/management/commands/sanitize_database.py
+++ b/src/core/management/commands/sanitize_database.py
@@ -48,7 +48,7 @@ class Command(BaseCommand):
         print_delete_stat(AssemblyMember.objects.all().delete())
 
         print('Assembly(non-public/non-accepted)')
-        non_public_assemblies = Assembly.objects.exclude(state_assembly__in=Assembly.PUBLIC_STATES).exclude(state_channel__in=Assembly.PUBLIC_STATES)
+        non_public_assemblies = Assembly.objects.exclude(state__in=Assembly.PUBLIC_STATES)
         print('  events: ', end='', flush=True)
         print_delete_stat(Event.objects.filter(assembly__in=non_public_assemblies).delete())
         print('  assemblies: ', end='', flush=True)
diff --git a/src/core/migrations/0161_remove_channels.py b/src/core/migrations/0161_remove_channels.py
new file mode 100644
index 0000000000000000000000000000000000000000..85dc34110fcc96731e08dc9e495cac2609b18de1
--- /dev/null
+++ b/src/core/migrations/0161_remove_channels.py
@@ -0,0 +1,84 @@
+# Generated by Django 5.1.2 on 2024-11-28 19:31
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("core", "0160_usercommunicationchannel_caption_and_more"),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name="conferencemember",
+            options={
+                "permissions": [
+                    (
+                        "conference_admin",
+                        "ConferenceMember__permission-confernece_admin",
+                    ),
+                    ("assembly_team", "ConferenceMember__permission-assembly_team"),
+                    (
+                        "assembly_registration_admin",
+                        "ConferenceMember__permission-assembly_registration_admin",
+                    ),
+                    ("static_pages", "ConferenceMember__permission-static_pages"),
+                    ("map_edit", "ConferenceMember__permission-map_edit"),
+                    ("moderation", "Orga: Moderation"),
+                    ("voucher_admin", "ConferenceMember__permission-voucher_admin"),
+                    ("scheduleadmin", "ConferenceMember__permission-scheduleadmin"),
+                    (
+                        "workadventure_admin",
+                        "ConferenceMember__permission-workadventure_admin",
+                    ),
+                ]
+            },
+        ),
+        migrations.RenameField(
+            model_name="assembly",
+            old_name="state_assembly",
+            new_name="state",
+        ),
+        migrations.RemoveField(
+            model_name="assembly",
+            name="state_channel",
+        ),
+        migrations.RemoveField(
+            model_name="conference",
+            name="support_channels",
+        ),
+        migrations.AlterField(
+            model_name="voucher",
+            name="target",
+            field=models.CharField(
+                choices=[
+                    ("assembly", "Voucher__target-assembly"),
+                    ("user", "Voucher__target-user"),
+                ],
+                help_text="Voucher__target__help",
+                max_length=20,
+                verbose_name="Voucher__target",
+            ),
+        ),
+        migrations.AlterField(
+            model_name="assembly",
+            name="state",
+            field=models.CharField(
+                choices=[
+                    ("planned", "Assembly__state-planned"),
+                    ("registered", "Assembly__state-registered"),
+                    ("hidden", "Assembly__state-hidden"),
+                    ("accepted", "Assembly__state-accepted"),
+                    ("rejected", "Assembly__state-rejected"),
+                    ("placed", "Assembly__state-placed"),
+                    ("arrived", "Assembly__state-arrived_self"),
+                    ("confirmed", "Assembly__state-arrived_confirmed"),
+                ],
+                default="planned",
+                help_text="Assembly__state__help",
+                max_length=20,
+                verbose_name="Assembly__state",
+            ),
+        ),
+    ]
diff --git a/src/core/models/assemblies.py b/src/core/models/assemblies.py
index 5627235495a173fd6478caeb685d7fc533f43f89..36c01d31669464a460dce2f3ed9864ff326108e8 100644
--- a/src/core/models/assemblies.py
+++ b/src/core/models/assemblies.py
@@ -70,22 +70,13 @@ class AssemblyManager(ConferenceManagerMixin['Assembly']):
     assembly_filter = 'self'
 
     def apply_public_filter(self, queryset: 'QuerySet[Assembly]', member: ConferenceMember | None = None) -> 'QuerySet[Assembly]':
-        return queryset.filter(Q(state_assembly__in=self.model.PUBLIC_STATES) | Q(state_channel__in=self.model.PUBLIC_STATES))
+        return queryset.filter(Q(state__in=self.model.PUBLIC_STATES))
 
     def associated_to_user(self, user: PlatformUser, conference: Conference) -> 'QuerySet[Assembly]':
         # guests cannot manage anything
         if user is None or not user.is_authenticated:
             return Assembly.objects.none()
-        return (
-            self.associated_with_user(conference, user=user)
-            .filter(members__member=user)
-            .exclude(
-                Q(
-                    state_assembly__in=[Assembly.State.NONE, Assembly.State.HIDDEN],
-                    state_channel__in=[Assembly.State.NONE, Assembly.State.HIDDEN],
-                )
-            )
-        )
+        return self.associated_with_user(conference, user=user).filter(members__member=user).exclude(Q(state__in=[Assembly.State.HIDDEN]))
 
 
 def get_banner_file_name(instance: 'Assembly', filename: str):
@@ -108,7 +99,6 @@ class Assembly(TaggedItemMixin, ActivityLogMixin, RulesModel):
         }
 
     class State(models.TextChoices):
-        NONE = 'none', _('Assembly__state-none')
         PLANNED = 'planned', _('Assembly__state-planned')
         REGISTERED = 'registered', _('Assembly__state-registered')
         HIDDEN = 'hidden', _('Assembly__state-hidden')
@@ -171,13 +161,9 @@ class Assembly(TaggedItemMixin, ActivityLogMixin, RulesModel):
 
     registration_data = models.JSONField(blank=True, null=True, help_text=_('Assembly__registration_data__help'), verbose_name=_('Assembly__registration_data'))
 
-    state_assembly = models.CharField(
-        max_length=20, default=State.NONE, choices=State.choices, verbose_name=_('Assembly__state_assembly'), help_text=_('Assembly__state_assembly__help')
-    )
-    state_channel = models.CharField(
-        max_length=20, default=State.NONE, choices=State.choices, verbose_name=_('Assembly__state_channel'), help_text=_('Assembly__state_channel__help')
+    state = models.CharField(
+        max_length=20, default=State.PLANNED, choices=State.choices, verbose_name=_('Assembly__state'), help_text=_('Assembly__state__help')
     )
-
     hierarchy = models.CharField(
         max_length=20, default=Hierarchy.REGULAR, choices=Hierarchy.choices, help_text=_('Assembly__hierarchy__help'), verbose_name=_('Assembly__hierarchy')
     )
@@ -338,7 +324,7 @@ class Assembly(TaggedItemMixin, ActivityLogMixin, RulesModel):
         set_physical = self.conference.support_assembly_physical and self.is_physical
         set_virtual = self.conference.support_assembly_virtual and self.is_virtual
         set_remote = self.conference.support_assembly_remote and self.is_remote
-        if self.state_assembly in self.PUBLIC_STATES and not (set_physical or set_virtual or set_remote):
+        if self.state in self.PUBLIC_STATES and not (set_physical or set_virtual or set_remote):
             x = _('Assembly__need_type')
             if self.conference.support_assembly_physical:
                 errors['is_physical'] = x
@@ -375,29 +361,13 @@ class Assembly(TaggedItemMixin, ActivityLogMixin, RulesModel):
 
         return mark_safe(escaped)
 
-    @property
-    def is_assembly(self):
-        return self.state_assembly != self.State.NONE
-
-    @property
-    def is_channel(self):
-        return self.state_channel != self.State.NONE
-
     @cached_property
     def is_public(self):
-        return self.state_assembly in self.PUBLIC_STATES or self.state_channel in self.PUBLIC_STATES
+        return self.state in self.PUBLIC_STATES
 
     @cached_property
     def is_placed(self):
-        return self.state_assembly in self.PLACED_STATES or self.state_channel in self.PLACED_STATES
-
-    @cached_property
-    def is_public_assembly(self):
-        return self.state_assembly in self.PUBLIC_STATES
-
-    @cached_property
-    def is_public_channel(self):
-        return self.state_channel in self.PUBLIC_STATES
+        return self.state in self.PLACED_STATES
 
     @cached_property
     def is_cluster(self):
@@ -413,7 +383,7 @@ class Assembly(TaggedItemMixin, ActivityLogMixin, RulesModel):
 
     @property
     def public_children(self):
-        return Assembly.objects.filter(parent=self).filter(state_assembly__in=Assembly.PUBLIC_STATES).order_by('name')
+        return Assembly.objects.filter(parent=self).filter(state__in=Assembly.PUBLIC_STATES).order_by('name')
 
     @property
     def linked_assemblies(self):
@@ -422,9 +392,8 @@ class Assembly(TaggedItemMixin, ActivityLogMixin, RulesModel):
         return [x.b for x in qs.select_related('b')]
 
     @property
-    def basedata_readonly(self):
-        return self.state_assembly not in [Assembly.State.NONE, Assembly.State.PLANNED, Assembly.State.REGISTERED] or self.state_channel not in [
-            Assembly.State.NONE,
+    def base_data_readonly(self):
+        return self.state not in [
             Assembly.State.PLANNED,
             Assembly.State.REGISTERED,
         ]
@@ -467,7 +436,7 @@ class Assembly(TaggedItemMixin, ActivityLogMixin, RulesModel):
         if not user.is_authenticated:
             return False
 
-        if staff_can_manage and user.has_conference_staff_permission(self.conference, 'core.assembly_team', 'core.channel_team'):
+        if staff_can_manage and user.has_conference_staff_permission(self.conference, 'core.assembly_team'):
             return True
 
         return self.members.filter(member=user, can_manage_assembly=True).exists()
diff --git a/src/core/models/base_managers.py b/src/core/models/base_managers.py
index 6681330b37a12e28d53e27f42738495cafd7924e..ea5cbb8038172ba98b2624bd897491e17ba4de22 100644
--- a/src/core/models/base_managers.py
+++ b/src/core/models/base_managers.py
@@ -79,7 +79,7 @@ class ConferenceManagerMixin(models.Manager, Generic[_ModelType]):
 
         allowed_members = AssemblyMember.objects.filter(member=member.user)
         allowed_members = allowed_members.filter(can_manage_assembly=True) if only_manageable else allowed_members
-        queryset = queryset.filter(**{f'{prefix}members__in': allowed_members}).exclude(**{f'{prefix}state_assembly__in': [Assembly.State.HIDDEN]})
+        queryset = queryset.filter(**{f'{prefix}members__in': allowed_members}).exclude(**{f'{prefix}state__in': [Assembly.State.HIDDEN]})
         return queryset
 
     def apply_self_organized_rights_filter(
diff --git a/src/core/models/conference.py b/src/core/models/conference.py
index 9bf0caa5f9f7921a9358f0a5da5a7ee93a1cb578..6fefed32d9d44c67e13e20ceadba0219476275a8 100644
--- a/src/core/models/conference.py
+++ b/src/core/models/conference.py
@@ -84,8 +84,6 @@ class ConferenceMember(models.Model):
             # See all assemblies, not only the accepted ones.
             ('assembly_registration_admin', _('ConferenceMember__permission-assembly_registration_admin')),
             # See all assemblies, not only the accepted ones.
-            ('channel_team', _('ConferenceMember__permission-channel_team')),
-            # Channelteam, Assemblyteam for Channel-Type Assemblies (Assemblies that provide their own content)
             ('static_pages', _('ConferenceMember__permission-static_pages')),
             # Access to static pages, can be further limited by configuring static_page_groups.
             ('map_edit', _('ConferenceMember__permission-map_edit')),
@@ -347,12 +345,6 @@ class Conference(models.Model):
         verbose_name=_('Conference__support_assembly_remote'),
     )
 
-    support_channels = models.BooleanField(
-        default=False,
-        help_text=_('Conference__support_channels__help'),
-        verbose_name=_('Conference__support_channels'),
-    )
-
     mail_footer = models.TextField(
         blank=True,
         null=True,
diff --git a/src/core/models/events.py b/src/core/models/events.py
index ff707ee50d40204a7992c0a116a3d6e8d118ea01..2a6de1497858c605de4e0762f6e6c6af30d3f416 100644
--- a/src/core/models/events.py
+++ b/src/core/models/events.py
@@ -73,10 +73,7 @@ class EventManager(ConferenceManagerMixin['Event']):
     assembly_filter = 'assembly'
 
     def apply_public_filter(self, queryset: 'QuerySet[Event]', member: ConferenceMember | None = None) -> 'QuerySet[Event]':
-        return queryset.filter(
-            (Q(assembly__state_assembly__in=Assembly.PUBLIC_STATES) | Q(assembly__state_channel__in=Assembly.PUBLIC_STATES) | Q(kind=Event.Kind.SELF_ORGANIZED))
-            & Q(is_public=True)
-        )
+        return queryset.filter((Q(assembly__state__in=Assembly.PUBLIC_STATES) | Q(kind=Event.Kind.SELF_ORGANIZED)) & Q(is_public=True))
 
     def apply_assembly_rights_filter(self, queryset: QuerySet['Event'], member: ConferenceMember, *, only_manageable: bool | None) -> QuerySet['Event']:
         return super().apply_assembly_rights_filter(queryset, member, only_manageable=only_manageable)
diff --git a/src/core/models/rooms.py b/src/core/models/rooms.py
index e471f98450e89cca2f7339e1f38b5dc28a0d6e06..e318242ebff80502f33ab4bc6f987825a01312b4 100644
--- a/src/core/models/rooms.py
+++ b/src/core/models/rooms.py
@@ -44,9 +44,7 @@ class RoomManager(ConferenceManagerMixin['Room']):
     assembly_filter = 'assembly'
 
     def apply_public_filter(self, queryset: 'QuerySet[Room]', member: ConferenceMember | None = None) -> 'QuerySet[Room]':
-        return queryset.filter(blocked=False).filter(
-            Q(assembly__state_assembly__in=Assembly.PUBLIC_STATES) | Q(assembly__state_channel__in=Assembly.PUBLIC_STATES)
-        )
+        return queryset.filter(blocked=False).filter(Q(assembly__state__in=Assembly.PUBLIC_STATES))
 
     def assignable_in_timeframe(self, conference: Conference, start: datetime, end: datetime, assembly: Assembly | None = None, is_sos: bool = False):
         """
diff --git a/src/core/models/voucher.py b/src/core/models/voucher.py
index 6f5d007cb65b58cfd81bfadb817eb527400fdea9..9ab716248803b651b9ffd0f520e7fffdd75221ce 100644
--- a/src/core/models/voucher.py
+++ b/src/core/models/voucher.py
@@ -30,14 +30,7 @@ class VoucherManager(models.Manager):
         qs = self.get_queryset().filter(conference=assembly.conference, enabled=True)
 
         # filter on the correct target type
-        if assembly.is_assembly and assembly.is_channel:
-            qs = qs.filter(target__in=Voucher.ASSEMBLY_TARGETS)
-        elif assembly.is_assembly:
-            qs = qs.filter(target=Voucher.Target.ASSEMBLY)
-        elif assembly.is_channel:
-            qs = qs.filter(target=Voucher.Target.CHANNEL)
-        else:
-            return qs.none()
+        qs = qs.filter(target=Voucher.Target.ASSEMBLY)
 
         # select vouchers which shall always be shown or ones assigned to the assembly
         associated_voucher_ids = VoucherEntry.objects.filter(assigned_assembly=assembly).distinct('voucher_id').values_list('voucher_id', flat=True)
@@ -76,9 +69,6 @@ class Voucher(models.Model):
         ASSEMBLY = 'assembly', _('Voucher__target-assembly')
         """This voucher is for assemblies."""
 
-        CHANNEL = 'channel', _('Voucher__target-channel')
-        """This voucher is for channels."""
-
         USER = 'user', _('Voucher__target-user')
         """This voucher is for an user."""
 
@@ -115,8 +105,6 @@ class Voucher(models.Model):
     objects = VoucherManager()
     logger = logging.getLogger(__name__)
 
-    ASSEMBLY_TARGETS = [Target.ASSEMBLY, Target.CHANNEL]
-
     def __str__(self):
         return self.name
 
@@ -150,13 +138,13 @@ class Voucher(models.Model):
 
     def do_auto_assignment(self, assemblies: list[Assembly]) -> int:
         if self.target not in self.ASSEMBLY_TARGETS:
-            raise NotImplementedError('Auto-Assignment of non assemblies/channels not implemented yet.')
+            raise NotImplementedError('Auto-Assignment of non assemblies not implemented yet.')
 
         # nothing to do if we're not enabled or set to manual assignment
         if (not self.enabled) or self.assignment == self.Assignment.MANUAL:
             return 0
 
-        # work on all conference assemblies (and channels) if no list is provided
+        # work on all conference assemblies if no list is provided
         if assemblies is None:
             if self.assignment == self.Assignment.ON_PUBLIC:
                 assemblies = self.conference.assemblies.conference_accessible(self.conference)
@@ -175,11 +163,9 @@ class Voucher(models.Model):
         # iterate over all missing assignments
         total = 0
         for assembly in missing_assignments:
-            # skip non-public assembly/channel if auto-assignment is for public ones only
+            # skip non-public assembly if auto-assignment is for public ones only
             if self.assignment == self.Assignment.ON_PUBLIC:
-                if (self.target == self.Target.ASSEMBLY and not assembly.is_public_assembly) or (
-                    self.target == self.Target.CHANNEL and not assembly.is_public_channel
-                ):
+                if self.target == self.Target.ASSEMBLY and not assembly.is_public:
                     continue
 
             # abort (but warn) if no more available entries are available
@@ -257,20 +243,13 @@ class VoucherEntry(models.Model):
         if self.assigned is not None or self.assigned_assembly is not None or self.assigned_user is not None:
             raise ValidationError(_('VoucherEntry__already_assigned'))
 
-        if self.voucher.target in Voucher.ASSEMBLY_TARGETS:
+        if self.voucher.target == Voucher.Target.ASSEMBLY:
             if not isinstance(target, Assembly):
-                raise ValueError("VoucherEntry's target must be an assembly or channel.")
+                raise ValueError("VoucherEntry's target must be an assembly.")
 
             if target.conference_id != self.voucher.conference_id:
                 raise ValueError('Voucher and assembly must be in the same conference!')
 
-            if self.voucher.target == Voucher.Target.ASSEMBLY:
-                if not target.is_assembly:
-                    raise ValueError("VoucherEntry's target must be an assembly.")
-            if self.voucher.target == Voucher.Target.CHANNEL:
-                if not target.is_channel:
-                    raise ValueError("VoucherEntry's target must be a channel.")
-
             self.assigned = timezone.now()
             self.assigned_assembly = target
             self.assigned_user = None
diff --git a/src/core/models/workadventure.py b/src/core/models/workadventure.py
index 75f93037f8054af4e3f383ac20e94692de755dca..24c1ccdc1db70135c9c13096944f2d92358cb640 100644
--- a/src/core/models/workadventure.py
+++ b/src/core/models/workadventure.py
@@ -112,9 +112,7 @@ class WorkadventureSession(models.Model):
             user_tags.add('admin')
         if is_angel:
             user_tags.add('angel')
-        for slug in (
-            Assembly.objects.associated_to_user(self.user, self.conference).filter(state_assembly__in=Assembly.PUBLIC_STATES).values_list('slug', flat=True)
-        ):
+        for slug in Assembly.objects.associated_to_user(self.user, self.conference).filter(state__in=Assembly.PUBLIC_STATES).values_list('slug', flat=True):
             user_tags.add('assembly_' + slug)
 
         result = {
diff --git a/src/core/tests/rooms.py b/src/core/tests/rooms.py
index 87c2fa9a3d431d7a5a4d092e63b607e2e3b0bbe5..cfb7994b404b69920c7ffb6b703873b42c51f7be 100644
--- a/src/core/tests/rooms.py
+++ b/src/core/tests/rooms.py
@@ -13,13 +13,13 @@ class RoomTests(TestCase):
         self.conference = Conference(slug='foo', name='Foo Conference', start=now() - timedelta(days=1), end=now() + timedelta(days=1))
         self.conference.save()
 
-        self.assembly1 = Assembly(conference=self.conference, slug='fnord', name='Fnord Assembly', state_assembly=Assembly.State.ACCEPTED, is_official=True)
+        self.assembly1 = Assembly(conference=self.conference, slug='fnord', name='Fnord Assembly', state=Assembly.State.ACCEPTED, is_official=True)
         self.assembly1.save()
-        self.assembly2 = Assembly(conference=self.conference, slug='banana', name='Obstgarten', state_assembly=Assembly.State.ARRIVED_CONFIRMED)
+        self.assembly2 = Assembly(conference=self.conference, slug='banana', name='Obstgarten', state=Assembly.State.ARRIVED_CONFIRMED)
         self.assembly2.save()
-        self.assembly3 = Assembly(conference=self.conference, slug='third', name='3. Rad', state_assembly=Assembly.State.ACCEPTED)
+        self.assembly3 = Assembly(conference=self.conference, slug='third', name='3. Rad', state=Assembly.State.ACCEPTED)
         self.assembly3.save()
-        self.assembly4 = Assembly(conference=self.conference, slug='gone', name='never shown', state_assembly=Assembly.State.HIDDEN)
+        self.assembly4 = Assembly(conference=self.conference, slug='gone', name='never shown', state=Assembly.State.HIDDEN)
         self.assembly4.save()
 
         self.room1a = Room(conference=self.conference, assembly=self.assembly1, room_type=Room.RoomType.LECTURE_HALL, name='1a')
diff --git a/src/core/tests/schedules.py b/src/core/tests/schedules.py
index 12698c3ec2e45add361084ff0c2c692a308830f2..c548b54b2337dbd80b67fc7cd868ab4ae2643407 100644
--- a/src/core/tests/schedules.py
+++ b/src/core/tests/schedules.py
@@ -213,7 +213,7 @@ class ScheduleTests(TestCase):
             conference=self.conference,
             name='CCC',
             is_official=True,
-            state_assembly=Assembly.State.ACCEPTED,
+            state=Assembly.State.ACCEPTED,
         )
         r2 = a2.rooms.create(
             conference=self.conference,
@@ -333,7 +333,7 @@ class ScheduleTests(TestCase):
             end=datetime(2023, 12, 31, 15, 00, 0, tzinfo=timezone.utc),
         )
         self.conference.save()
-        self.assembly = Assembly(name='CCC', slug='ccc', conference=self.conference, state_assembly=Assembly.State.PLACED)
+        self.assembly = Assembly(name='CCC', slug='ccc', conference=self.conference, state=Assembly.State.PLACED)
         self.assembly.save()
 
         src = ScheduleSource.objects.create(
diff --git a/src/core/tests/vouchers.py b/src/core/tests/vouchers.py
index c598820be882e28a639d015078dbf4df71c5ac00..ebd18f2451123851c713e6b15ba84a6120ff0d7b 100644
--- a/src/core/tests/vouchers.py
+++ b/src/core/tests/vouchers.py
@@ -33,7 +33,7 @@ class VoucherTests(TestCase):
         self.guest.save()
 
         self.assembly = Assembly(conference=self.conference, slug='fnord', name='Fnord Assembly')
-        self.assembly.state_assembly = Assembly.State.ACCEPTED
+        self.assembly.state = Assembly.State.ACCEPTED
         self.assembly.save()
 
     def testBasics(self):
@@ -148,13 +148,13 @@ class VoucherTests(TestCase):
         self.assertEqual(entry.target, self.assembly)
 
         # setup a second assembly which is not 'public' yet
-        a2 = self.conference.assemblies.create(slug='second', name='test2', state_assembly=Assembly.State.REGISTERED)
+        a2 = self.conference.assemblies.create(slug='second', name='test2', state=Assembly.State.REGISTERED)
 
         # try auto-assignment again, should have no effect (assignment=ON_PUBLIC, only one public assembly which is already assigned)
         self.assertEqual(0, self.doAutoAssignment())
 
         # set assembly public, should trigger a warning as we don't have a free entry available
-        a2.state_assembly = Assembly.State.ACCEPTED
+        a2.state = Assembly.State.ACCEPTED
         a2.save()
         self.assertEqual(0, self.doAutoAssignment(expected_warnings=1))
 
diff --git a/src/core/tests/workadventure.py b/src/core/tests/workadventure.py
index fd6eb43b4088a113c4d28487532d5a3ca02d95e7..6d6b8ab9339433c27856d6c9ddad4d922ab0b93d 100644
--- a/src/core/tests/workadventure.py
+++ b/src/core/tests/workadventure.py
@@ -9,7 +9,7 @@ class WorkadventureSessionTests(TestCase):
     def setUp(self):
         self.conference = Conference(slug='test', name='Test Conference')
         self.conference.save()
-        self.assembly = self.conference.assemblies.create(slug='fnord', state_assembly=Assembly.State.ACCEPTED)
+        self.assembly = self.conference.assemblies.create(slug='fnord', state=Assembly.State.ACCEPTED)
         self.room = self.assembly.rooms.create(conference=self.conference, room_type=Room.RoomType.WORKADVENTURE, slug='fnord')
         self.user = PlatformUser(username='bernd')
         self.user.save()
diff --git a/src/plainui/tests/test_views.py b/src/plainui/tests/test_views.py
index e9002f0c704db719229956d1659aa6d71ed7b151..f7d5ad206afbb7c11eb44d08cbabc495e4a1748e 100644
--- a/src/plainui/tests/test_views.py
+++ b/src/plainui/tests/test_views.py
@@ -216,7 +216,7 @@ class ViewsTestBase(TestCase):
 class ViewsTest(ViewsTestBase):
     @override_locale('en')
     def test_EventView(self):
-        assembly = Assembly(conference=self.conf, name='DUMMY', slug='dummy', state_assembly=Assembly.State.ACCEPTED, is_official=True)
+        assembly = Assembly(conference=self.conf, name='DUMMY', slug='dummy', state=Assembly.State.ACCEPTED, is_official=True)
         assembly.save()
 
         tag = ConferenceTag(conference=self.conf, slug='test_tag', is_public=True, value_type='simple')
@@ -260,9 +260,9 @@ class ViewsTest(ViewsTestBase):
 
     @override_locale('en')
     def test_TagView(self):
-        assembly1 = Assembly(conference=self.conf, slug='d', name='DUMMY', state_assembly=Assembly.State.ACCEPTED)
+        assembly1 = Assembly(conference=self.conf, slug='d', name='DUMMY', state=Assembly.State.ACCEPTED)
         assembly1.save()
-        assembly2 = Assembly(conference=self.conf, slug='2', name='2nd', state_assembly=Assembly.State.ACCEPTED)
+        assembly2 = Assembly(conference=self.conf, slug='2', name='2nd', state=Assembly.State.ACCEPTED)
         assembly2.save()
 
         tag = ConferenceTag(conference=self.conf, slug='test_tag', is_public=True, value_type='simple')
@@ -305,7 +305,7 @@ class ViewsTest(ViewsTestBase):
         speaker2.save()
         member1 = PlatformUser(username='member1')
         member1.save()
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
         AssemblyMember(member=speaker1, is_representative=True, can_manage_assembly=True, show_public=True, assembly=assembly).save()
         AssemblyMember(member=speaker2, is_representative=True, can_manage_assembly=True, show_public=False, assembly=assembly).save()
@@ -375,7 +375,7 @@ class ViewsTest(ViewsTestBase):
         resp = self.client.get(reverse('plainui:assembly', kwargs={'assembly_slug': assembly.slug}))
         self.assertTrue(resp.context_data['is_favorite'])
 
-        sos_assembly = Assembly(conference=self.conf, slug='sos_assembly', name='SOS Assembly', state_assembly=Assembly.State.PLACED)
+        sos_assembly = Assembly(conference=self.conf, slug='sos_assembly', name='SOS Assembly', state=Assembly.State.PLACED)
         sos_assembly.save()
 
         # redirects to the sos page when accessing the sos assembly as the existence of the assembly page caused some confusion
@@ -386,7 +386,7 @@ class ViewsTest(ViewsTestBase):
 
     @override_locale('en')
     def test_AssembliesView(self):
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
 
         self.assertNeedsLogin(reverse('plainui:assemblies'))
@@ -396,7 +396,7 @@ class ViewsTest(ViewsTestBase):
 
     @override_locale('en')
     def test_AssembliesAllView(self):
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
 
         self.assertNeedsLogin(reverse('plainui:assemblies_all'))
@@ -406,7 +406,7 @@ class ViewsTest(ViewsTestBase):
 
     @override_locale('en')
     def test_AssembliesEventsView(self):
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
         room = Room(conference=self.conf, assembly=assembly, name='Some Room')
         room.save()
@@ -1175,7 +1175,7 @@ class ViewsTest(ViewsTestBase):
 
     @override_locale('en')
     def test_SearchView_post(self):
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='asdf', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='asdf', state=Assembly.State.PLACED)
         assembly.save()
         event = Event(
             conference=self.conf,
@@ -1213,7 +1213,7 @@ class ViewsTest(ViewsTestBase):
 
     @override_locale('en')
     def test_ProfileView_get(self):
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
         event = Event(
             conference=self.conf,
@@ -1268,7 +1268,7 @@ class ViewsTest(ViewsTestBase):
     @override_locale('en')
     @patch('modeltranslation.settings.AVAILABLE_LANGUAGES', ['en', 'de'])
     def test_ProfileView_post(self):
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
         event = Event(
             conference=self.conf,
@@ -1691,9 +1691,9 @@ class ViewsTest(ViewsTestBase):
 
     @override_locale('en')
     def test_ModifyFavoritesView_post(self):
-        assembly1 = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly1 = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly1.save()
-        assembly2 = Assembly(conference=self.conf, slug='assembly2', name='Assembly2', state_assembly=Assembly.State.PLACED)
+        assembly2 = Assembly(conference=self.conf, slug='assembly2', name='Assembly2', state=Assembly.State.PLACED)
         assembly2.save()
         event1 = Event(
             conference=self.conf,
@@ -2006,7 +2006,7 @@ class ViewsTest(ViewsTestBase):
         self.user.timezone = 'UTC'
         self.user.save()
 
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
         room = Room(conference=self.conf, assembly=assembly, name='Some Room', is_public_fahrplan=True)
         room.save()
@@ -2101,7 +2101,7 @@ class ViewsTest(ViewsTestBase):
         self.conf.end = datetime(2020, 1, 3, 0, 0, 0, tzinfo=UTC)
         self.conf.save()
 
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
         room = Room(conference=self.conf, assembly=assembly, name='Some Room', is_public_fahrplan=True)
         room.save()
@@ -2157,7 +2157,7 @@ class ViewsTest(ViewsTestBase):
         self.conf.end = now + timedelta(days=3)
         self.conf.save()
 
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
         room = Room(conference=self.conf, assembly=assembly, name='Room1')
         room.save()
@@ -2176,7 +2176,7 @@ class ViewsTest(ViewsTestBase):
         self.conf.end = now + timedelta(days=3)
         self.conf.save()
 
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
         room = Room(conference=self.conf, assembly=assembly, name='Room1')
         room.save()
@@ -2195,7 +2195,7 @@ class ViewsTest(ViewsTestBase):
         self.conf.end = now + timedelta(days=3)
         self.conf.save()
 
-        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state_assembly=Assembly.State.PLACED)
+        assembly = Assembly(conference=self.conf, slug='assembly1', name='Assembly1', state=Assembly.State.PLACED)
         assembly.save()
         room = Room(conference=self.conf, assembly=assembly, name='Some Room')
         room.save()
@@ -2252,82 +2252,6 @@ class ViewsTest(ViewsTestBase):
         self.assertEqual(resp.context_data['conf'], self.conf)
         self.assertEqual(resp.context_data['hide_header'], True)
 
-    @freeze_time(datetime(2020, 1, 1, 1, 0, 0, tzinfo=UTC))
-    @override_locale('en')
-    def test_ChannelEventsView(self):
-        assembly = Assembly(conference=self.conf, slug='official', name='Official Assembly', state_assembly=Assembly.State.PLACED, is_official=True)
-        assembly.save()
-        room1 = Room(conference=self.conf, assembly=assembly, name='Stream1', is_official=True)
-        room1.save()
-        room_link1 = RoomLink(room=room1, link_type=RoomLink.LinkType.MEDIA_CCC_DE, link='some.where')
-        room_link1.save()
-        room2 = Room(conference=self.conf, assembly=assembly, name='Stream2', is_official=True)
-        room2.save()
-        room_link2 = RoomLink(room=room2, link_type=RoomLink.LinkType.MEDIA_CCC_DE, link='else.where')
-        room_link2.save()
-
-        event = Event(
-            conference=self.conf,
-            assembly=assembly,
-            room=room1,
-            slug='Event1_1',
-            name='Event1_1',
-            is_public=True,
-            kind=Event.Kind.ASSEMBLY,
-            schedule_start=datetime(2020, 1, 1, 0, 45, 0, tzinfo=UTC),
-            schedule_duration=timedelta(minutes=45),
-            additional_data={'persons': [{'public_name': 'Gottfried Fluffke'}, {'public_name': 'Ferdinand Federviech'}]},
-        )
-        event.save()
-        event2 = Event(
-            conference=self.conf,
-            assembly=assembly,
-            room=room1,
-            slug='Event1_2',
-            name='Event1_2',
-            is_public=True,
-            schedule_start=datetime(2020, 1, 1, 1, 50, 1, tzinfo=UTC),
-            schedule_duration=timedelta(minutes=45),
-        )
-        event2.save()
-        event_upcoming = Event(
-            conference=self.conf,
-            assembly=assembly,
-            room=room2,
-            slug='Event2_1',
-            name='Event2_1',
-            is_public=True,
-            schedule_start=datetime(2020, 1, 1, 1, 50, 1, tzinfo=UTC),
-            schedule_duration=timedelta(minutes=45),
-        )
-        event_upcoming.save()
-
-        EventParticipant(is_public=True, participant=self.user, event=event2, role=EventParticipant.Role.SPEAKER).save()
-
-        self.assertNeedsLogin(reverse('plainui:channel_events'))
-        resp = self.client.get(reverse('plainui:channel_events'))
-        self.assertEqual(resp.context_data['conf'], self.conf)
-        self.assertEqual(
-            resp.context_data['rooms_active'],
-            [
-                {
-                    'room': room1,
-                    'current_event': event,
-                    'next_event': event2,
-                }
-            ],
-        )
-        self.assertEqual(
-            resp.context_data['rooms_inactive'],
-            [
-                {
-                    'room': room2,
-                    'current_event': None,
-                    'next_event': event_upcoming,
-                }
-            ],
-        )
-
     @override_locale('en')
     def test_WorldView(self):
         self.assertNeedsLogin(reverse('plainui:world'), check_user=True)
@@ -2347,7 +2271,7 @@ class ViewsTest(ViewsTestBase):
     @override_settings(WORKADVENTURE_LOBBY_ROOM_SLUG='lobby')
     @override_locale('en')
     def test_WorkadventureEnter(self):
-        assembly = Assembly(conference=self.conf, slug='official', name='Official Assembly', state_assembly=Assembly.State.PLACED, is_official=True)
+        assembly = Assembly(conference=self.conf, slug='official', name='Official Assembly', state=Assembly.State.PLACED, is_official=True)
         assembly.save()
         lobby_room = Room(conference=self.conf, assembly=assembly, slug='lobby', room_type=Room.RoomType.WORKADVENTURE)
         lobby_room.save()
diff --git a/src/plainui/urls.py b/src/plainui/urls.py
index 3eb67cd268872b70aac4ddfdaf0462a89a024d39..b6811fed2358b42bad410ac265de0cbe6296040d 100644
--- a/src/plainui/urls.py
+++ b/src/plainui/urls.py
@@ -51,7 +51,6 @@ urlpatterns = [
     path('board/<int:pk>', views.BoardEntryView.as_view(), name='board_entry'),
     path('board/<int:pk>/edit', views.BoardEntryEditView.as_view(), name='board_entry_edit'),
     path('board/<int:pk>/delete', views.BoardEntryDeleteView.as_view(), name='board_entry_delete'),
-    path('channels', views.ChannelEventsView.as_view(), name='channel_events'),
     path('fahrplan', views.FahrplanView.as_view(), name='fahrplan'),
     path('modify_favorites', views.ModifyFavoritesView.as_view(), name='modify_favorites'),
     path('modify_theme', views.ModifyThemeView.as_view(), name='modify_theme'),
diff --git a/src/plainui/views/events.py b/src/plainui/views/events.py
index f6e7fc3c7377f4bc2b3eb84dd8f7ed78d0273e8d..7af6f15812eb867c4cb82277c801937f3af0b5db 100644
--- a/src/plainui/views/events.py
+++ b/src/plainui/views/events.py
@@ -1,6 +1,5 @@
 __all__ = (
     'AssembliesEventsView',
-    'ChannelEventsView',
     'EventView',
     'SosJoin',
     'SosList',
@@ -9,7 +8,6 @@ __all__ = (
 
 from django.contrib import messages
 from django.contrib.contenttypes.models import ContentType
-from django.db.models import F, Prefetch
 from django.http import Http404, HttpResponseRedirect
 from django.shortcuts import get_object_or_404, redirect
 from django.urls import reverse
@@ -20,14 +18,11 @@ from core import integrations
 from core.models import (
     Event,
     EventAttachment,
-    EventParticipant,
-    Room,
-    RoomLink,
     TagItem,
 )
 from core.views.list_views import FilteredListView
 
-from plainui.views.utils import ConferenceRequiredMixin, event_filter, organize_events_for_calendar, session_get_favorite_events
+from plainui.views.utils import ConferenceRequiredMixin, event_filter, session_get_favorite_events
 
 
 class AssembliesEventsView(ConferenceRequiredMixin, TemplateView):
@@ -100,77 +95,6 @@ class UpcomingView(ConferenceRequiredMixin, TemplateView):
         )
 
 
-class ChannelEventsView(ConferenceRequiredMixin, TemplateView):
-    template_name = 'plainui/channel_events.html.j2'
-
-    def get_context_data(self, **kwargs):
-        context = super().get_context_data(**kwargs)
-        context['conf'] = self.conf
-        now = self.now
-
-        rooms = []  # type: list[Room]
-        room_ids = []  # type: list[UUID]
-        room_qs = Room.objects.conference_accessible(self.conf).filter(is_official=True, links__link_type=RoomLink.LinkType.MEDIA_CCC_DE)
-        for room in room_qs.order_by('official_room_order', 'name'):
-            rooms.append(room)
-            room_ids.append(room.pk)
-
-        current_events_qs = (
-            Event.objects.conference_accessible(self.conf)
-            .filter(room_id__in=room_ids, schedule_start__lte=now, schedule_end__gte=now)
-            .order_by('room_id', 'schedule_start')
-            .distinct('room_id')
-        )
-        speakers = EventParticipant.objects.filter(is_public=True, role=EventParticipant.Role.SPEAKER).order_by('participant__display_name')
-        speakers = speakers.annotate(speaker_name=F('participant__display_name'))
-        current_events_qs = current_events_qs.prefetch_related(Prefetch('participants', queryset=speakers, to_attr='speakers'))
-
-        current_events = {}  # type: dict[UUID, Event]
-        for event in current_events_qs:
-            current_events[event.room_id] = event
-
-        next_events_qs = (
-            Event.objects.conference_accessible(self.conf)
-            .filter(room_id__in=room_ids, schedule_start__gt=now, schedule_end__isnull=False)
-            .order_by('room_id', 'schedule_start')
-            .distinct('room_id')
-        )
-        speakers = EventParticipant.objects.filter(is_public=True, role=EventParticipant.Role.SPEAKER).order_by('participant__username')
-        speakers = speakers.annotate(speaker_name=F('participant__username'))
-        next_events_qs = next_events_qs.prefetch_related(Prefetch('participants', queryset=speakers, to_attr='speakers'))
-
-        next_events = {}  # type: dict[UUID, Event]
-        for event in next_events_qs:
-            next_events[event.room_id] = event
-
-        rooms_active = []
-        rooms_inactive = []
-        for room in rooms:
-            current_event = current_events.get(room.pk)
-            next_event = next_events.get(room.pk)
-            room_data = {
-                'room': room,
-                'current_event': current_event,
-                'next_event': next_event,
-            }
-            if current_event:
-                rooms_active.append(room_data)
-            else:
-                rooms_inactive.append(room_data)
-
-        context['rooms_active'] = rooms_active
-        context['rooms_inactive'] = rooms_inactive
-
-        context['my_favorite_events'] = session_get_favorite_events(self.request.session, self.request.user)
-
-        events = event_filter(self.request.user, self.conf, public_fahrplan=True)
-        context['events'] = organize_events_for_calendar(self.conf, events)
-
-        context['report_info'] = {'enabled': True}
-
-        return context
-
-
 class SosList(ConferenceRequiredMixin, FilteredListView):
     model = Event
     template_name = 'plainui/sos.html.j2'