diff --git a/api/funkwhale_api/audio/filters.py b/api/funkwhale_api/audio/filters.py
index 3a8da5ca7f66e07e8dbd3552a8a7822f7758cb22..6b1a9e8d94c28da47682600ed908b1df5f514ac4 100644
--- a/api/funkwhale_api/audio/filters.py
+++ b/api/funkwhale_api/audio/filters.py
@@ -4,6 +4,7 @@ import django_filters
 
 from funkwhale_api.common import fields
 from funkwhale_api.common import filters as common_filters
+from funkwhale_api.federation import actors
 from funkwhale_api.moderation import filters as moderation_filters
 
 from . import models
@@ -28,6 +29,7 @@ class ChannelFilter(moderation_filters.HiddenContentFilterSet):
     subscribed = django_filters.BooleanFilter(
         field_name="_", method="filter_subscribed"
     )
+    external = django_filters.BooleanFilter(field_name="_", method="filter_external")
     ordering = django_filters.OrderingFilter(
         # tuple-mapping retains order
         fields=(
@@ -38,7 +40,7 @@ class ChannelFilter(moderation_filters.HiddenContentFilterSet):
 
     class Meta:
         model = models.Channel
-        fields = ["q", "scope", "tag", "subscribed", "ordering"]
+        fields = ["q", "scope", "tag", "subscribed", "ordering", "external"]
         hidden_content_fields_mapping = moderation_filters.USER_FILTER_CONFIG["CHANNEL"]
 
     def filter_subscribed(self, queryset, name, value):
@@ -56,6 +58,18 @@ class ChannelFilter(moderation_filters.HiddenContentFilterSet):
         else:
             return queryset.exclude(query)
 
+    def filter_external(self, queryset, name, value):
+        query = Q(
+            attributed_to=actors.get_service_actor(),
+            actor__preferred_username__startswith="rssfeed-",
+        )
+        if value is True:
+            queryset = queryset.filter(query)
+        if value is False:
+            queryset = queryset.exclude(query)
+
+        return queryset
+
 
 class IncludeChannelsFilterSet(django_filters.FilterSet):
     """
diff --git a/api/funkwhale_api/audio/serializers.py b/api/funkwhale_api/audio/serializers.py
index 6b9227dedc2d027248ca028e16af3233a9284609..c31cdb69da4cf80964b88953d6a24f2a4db46af2 100644
--- a/api/funkwhale_api/audio/serializers.py
+++ b/api/funkwhale_api/audio/serializers.py
@@ -200,11 +200,9 @@ class ChannelUpdateSerializer(serializers.Serializer):
         obj.save(update_fields=["metadata"])
 
         if "description" in validated_data:
-            description_obj = common_utils.attach_content(
+            common_utils.attach_content(
                 obj.artist, "description", validated_data["description"]
             )
-            if description_obj:
-                actor_update_fields.append(("summary", description_obj.rendered))
 
         if "name" in validated_data:
             actor_update_fields.append(("name", validated_data["name"]))
diff --git a/api/funkwhale_api/common/middleware.py b/api/funkwhale_api/common/middleware.py
index 201cd2ec84b29c433c62ec10553fa3f8c3487be0..7f82ae20c3168029564794f9b08f8a5347238d43 100644
--- a/api/funkwhale_api/common/middleware.py
+++ b/api/funkwhale_api/common/middleware.py
@@ -204,7 +204,8 @@ def get_api_response(request, url):
     except urls.exceptions.Resolver404:
         return http.HttpResponseNotFound()
     response = match.func(request, *match.args, **match.kwargs)
-    response.render()
+    if hasattr(response, "render"):
+        response.render()
     return response
 
 
diff --git a/api/tests/audio/test_filters.py b/api/tests/audio/test_filters.py
index c0cb9caa4cf2ab3a151d8926440a01a03e2e8f04..d7a0a79800e6559f9272e0d0f42027d6a719e8ad 100644
--- a/api/tests/audio/test_filters.py
+++ b/api/tests/audio/test_filters.py
@@ -1,3 +1,5 @@
+import pytest
+
 from funkwhale_api.audio import filters
 from funkwhale_api.audio import models
 
@@ -30,3 +32,17 @@ def test_channel_filter_subscribed_false(factories, mocker, queryset_equal_list)
     )
 
     assert filterset.qs == [other_channel]
+
+
+@pytest.mark.parametrize("external, expected_index", [("true", 0), ("false", 1)])
+def test_channel_filter_external(
+    external, expected_index, factories, mocker, queryset_equal_list
+):
+    user = factories["users.User"](with_actor=True)
+    channels = [factories["audio.Channel"](external=True), factories["audio.Channel"]()]
+    qs = models.Channel.objects.all()
+    filterset = filters.ChannelFilter(
+        {"external": external}, request=mocker.Mock(user=user), queryset=qs
+    )
+
+    assert filterset.qs == [channels[expected_index]]
diff --git a/api/tests/audio/test_serializers.py b/api/tests/audio/test_serializers.py
index 3c29bdf458a0700dd8fa7c70042f143b23fe3cc8..0eecba8d9e8a871a37e01acedf8273fae7e23ebe 100644
--- a/api/tests/audio/test_serializers.py
+++ b/api/tests/audio/test_serializers.py
@@ -184,9 +184,6 @@ def test_channel_serializer_update(factories, mocker):
         sorted(channel.artist.tagged_items.values_list("tag__name", flat=True))
         == data["tags"]
     )
-    assert channel.actor.summary == common_utils.render_html(
-        data["description"]["text"], "text/markdown"
-    )
     assert channel.artist.description.text == data["description"]["text"]
     assert channel.artist.description.content_type == "text/markdown"
     assert channel.actor.name == data["name"]
diff --git a/front/src/components/Sidebar.vue b/front/src/components/Sidebar.vue
index 9203674334a492bf7f56be116591c55a68481809..ea8dc16d84b2509eea99f5f11dfe3801d9a9fc33 100644
--- a/front/src/components/Sidebar.vue
+++ b/front/src/components/Sidebar.vue
@@ -352,7 +352,7 @@ $sidebar-color: #2D2F33;
 
 .sidebar {
   background: $sidebar-color;
-  z-index: auto;
+  z-index: 1;
   @include media(">desktop") {
     display: flex;
     flex-direction: column;
diff --git a/front/src/components/audio/ChannelEntries.vue b/front/src/components/audio/ChannelEntries.vue
index af3f2794310de761ae895019bc5af70164fa73b8..23f70cbed61817983494974fb782dedbe00b905e 100644
--- a/front/src/components/audio/ChannelEntries.vue
+++ b/front/src/components/audio/ChannelEntries.vue
@@ -13,12 +13,11 @@
       </button>
     </template>
     <template v-if="!isLoading && objects.length === 0">
-      <div class="ui placeholder segment">
-        <div class="ui icon header">
-          <i class="music icon"></i>
-          No results matching your query
-        </div>
-      </div>
+      <empty-state @refresh="fetchData('tracks/')" :refresh="true">
+        <p>
+          <translate translate-context="Content/Channels/*">You may need to subscribe to this channel to see its content.</translate>
+        </p>
+      </empty-state>
     </template>
   </div>
 </template>
diff --git a/front/src/components/audio/ChannelSeries.vue b/front/src/components/audio/ChannelSeries.vue
index 5f9fa99d961e0745fa1784c5f092df4153c940cf..69e73598724fcb3cf032887c932816440fea83b2 100644
--- a/front/src/components/audio/ChannelSeries.vue
+++ b/front/src/components/audio/ChannelSeries.vue
@@ -18,12 +18,11 @@
       </button>
     </template>
     <template v-if="!isLoading && objects.length === 0">
-      <div class="ui placeholder segment">
-        <div class="ui icon header">
-          <i class="compact disc icon"></i>
-          No results matching your query
-        </div>
-      </div>
+      <empty-state @refresh="fetchData('albums/')" :refresh="true">
+        <p>
+          <translate translate-context="Content/Channels/*">You may need to subscribe to this channel to see its contents.</translate>
+        </p>
+      </empty-state>
     </template>
   </div>
 </template>
diff --git a/front/src/components/library/Home.vue b/front/src/components/library/Home.vue
index 15f505f842609a8885fa79a8b4a420ee2580572b..20df9429ad82d48681d03e1a84dae52a3cbe6ae2 100644
--- a/front/src/components/library/Home.vue
+++ b/front/src/components/library/Home.vue
@@ -30,7 +30,7 @@
         <h3 class="ui header" >
           <translate translate-context="*/*/*">New channels</translate>
         </h3>
-        <channels-widget :show-modification-date="true" :limit="12" :filters="{ordering: '-creation_date'}"></channels-widget>
+        <channels-widget :show-modification-date="true" :limit="12" :filters="{ordering: '-creation_date', external: 'false'}"></channels-widget>
       </template>
 
 
diff --git a/front/src/views/auth/ProfileBase.vue b/front/src/views/auth/ProfileBase.vue
index ac828288b95c74299296f4944bbd011de5ae3a69..80ec6ad7d0ddece99aa2d174382d3391a6dbf5ee 100644
--- a/front/src/views/auth/ProfileBase.vue
+++ b/front/src/views/auth/ProfileBase.vue
@@ -6,7 +6,7 @@
     <div class="ui head vertical stripe segment container">
       <div class="ui stackable grid" v-if="object">
         <div class="ui five wide column">
-          <div class="ui pointing dropdown icon small basic right floated button" ref="dropdown" v-dropdown="{direction: 'downward'}" style="position: absolute; right: 1em; top: 1em; z-index: 5">
+          <div class="ui pointing dropdown icon small basic right floated button" ref="dropdown" v-dropdown="{direction: 'downward'}" style="position: absolute; right: 1em; top: 1em;">
             <i class="ellipsis vertical icon"></i>
             <div class="menu">
               <div
diff --git a/front/src/views/library/DetailBase.vue b/front/src/views/library/DetailBase.vue
index 48ebd062980e7b1b2cbe74404859c7ff09d063d4..ffbd66f047c4ca98c415e5b7db83b2bc598576d9 100644
--- a/front/src/views/library/DetailBase.vue
+++ b/front/src/views/library/DetailBase.vue
@@ -4,7 +4,7 @@
       <div v-if="isLoading" class="ui centered active inline loader"></div>
       <div class="ui stackable grid" v-else-if="object">
         <div class="ui five wide column">
-          <div class="ui pointing dropdown icon small basic right floated button" ref="dropdown" v-dropdown="{direction: 'downward'}" style="position: absolute; right: 1em; top: 1em; z-index: 5">
+          <div class="ui pointing dropdown icon small basic right floated button" ref="dropdown" v-dropdown="{direction: 'downward'}" style="position: absolute; right: 1em; top: 1em;">
             <i class="ellipsis vertical icon"></i>
             <div class="menu">
               <div