diff --git a/api/funkwhale_api/music/filters.py b/api/funkwhale_api/music/filters.py
index 79b2d2c63872f2816316b2e711cb20037f0f630a..d69dd13a3d3b095cabbc5730b78a970c35c88adf 100644
--- a/api/funkwhale_api/music/filters.py
+++ b/api/funkwhale_api/music/filters.py
@@ -218,3 +218,12 @@ class AlbumFilter(
     def filter_playable(self, queryset, name, value):
         actor = utils.get_actor_from_request(self.request)
         return queryset.playable_by(actor, value)
+
+
+class LibraryFilter(filters.FilterSet):
+    q = fields.SearchFilter(search_fields=["name"],)
+    scope = common_filters.ActorScopeFilter(actor_field="actor", distinct=True)
+
+    class Meta:
+        model = models.Library
+        fields = ["privacy_level", "q", "scope"]
diff --git a/api/funkwhale_api/music/management/commands/import_files.py b/api/funkwhale_api/music/management/commands/import_files.py
index fab980510d77b045df80df803d0fa40642a520ac..ddc598d06fcf5dfa50ac1508c90e563c59cf6a0e 100644
--- a/api/funkwhale_api/music/management/commands/import_files.py
+++ b/api/funkwhale_api/music/management/commands/import_files.py
@@ -27,7 +27,8 @@ def crawl_dir(dir, extensions, recursive=True, ignored=[]):
     if os.path.isfile(dir):
         yield dir
         return
-    with os.scandir(dir) as scanner:
+    try:
+        scanner = os.scandir(dir)
         for entry in scanner:
             if entry.is_file():
                 for e in extensions:
@@ -38,6 +39,9 @@ def crawl_dir(dir, extensions, recursive=True, ignored=[]):
                 yield from crawl_dir(
                     entry, extensions, recursive=recursive, ignored=ignored
                 )
+    finally:
+        if hasattr(scanner, "close"):
+            scanner.close()
 
 
 def batch(iterable, n=1):
diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py
index 93635c11b55be1b10e996ad62f281e43f41e6c2f..6c9f7e41c4754b8c2a40819ab02529965e6583bb 100644
--- a/api/funkwhale_api/music/views.py
+++ b/api/funkwhale_api/music/views.py
@@ -273,6 +273,7 @@ class LibraryViewSet(
         oauth_permissions.ScopePermission,
         common_permissions.OwnerPermission,
     ]
+    filterset_class = filters.LibraryFilter
     required_scope = "libraries"
     anonymous_policy = "setting"
     owner_field = "actor.user"
@@ -282,8 +283,12 @@ class LibraryViewSet(
         qs = super().get_queryset()
         # allow retrieving a single library by uuid if request.user isn't
         # the owner. Any other get should be from the owner only
-        if self.action != "retrieve":
+        if self.action not in ["retrieve", "list"]:
             qs = qs.filter(actor=self.request.user.actor)
+        if self.action == "list":
+            actor = utils.get_actor_from_request(self.request)
+            qs = qs.viewable_by(actor)
+
         return qs
 
     def perform_create(self, serializer):
diff --git a/api/tests/files/nested/valid.ogg b/api/tests/files/nested/valid.ogg
new file mode 100644
index 0000000000000000000000000000000000000000..e1643848a07a548e55d53726d4e4fe168a8ab2cd
Binary files /dev/null and b/api/tests/files/nested/valid.ogg differ
diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py
index 4f2b6226919739626ddb4d6d4baa2afec7727248..5e3c9c953be2d44a55a01d7d4a0c1d757f10f047 100644
--- a/api/tests/music/test_views.py
+++ b/api/tests/music/test_views.py
@@ -631,10 +631,10 @@ def test_user_can_create_library(factories, logged_in_api_client):
 def test_user_can_list_their_library(factories, logged_in_api_client):
     actor = logged_in_api_client.user.create_actor()
     library = factories["music.Library"](actor=actor)
-    factories["music.Library"]()
+    factories["music.Library"](privacy_level="everyone")
 
     url = reverse("api:v1:libraries-list")
-    response = logged_in_api_client.get(url)
+    response = logged_in_api_client.get(url, {"scope": "me"})
 
     assert response.status_code == 200
     assert response.data["count"] == 1
@@ -651,6 +651,19 @@ def test_user_can_retrieve_another_user_library(factories, logged_in_api_client)
     assert response.data["uuid"] == str(library.uuid)
 
 
+def test_user_can_list_public_libraries(factories, api_client, preferences):
+    preferences["common__api_authentication_required"] = False
+    library = factories["music.Library"](privacy_level="everyone")
+    factories["music.Library"](privacy_level="me")
+
+    url = reverse("api:v1:libraries-list")
+    response = api_client.get(url)
+
+    assert response.status_code == 200
+    assert response.data["count"] == 1
+    assert response.data["results"][0]["uuid"] == str(library.uuid)
+
+
 def test_library_list_excludes_channel_library(factories, logged_in_api_client):
     actor = logged_in_api_client.user.create_actor()
     factories["audio.Channel"](attributed_to=actor)
diff --git a/api/tests/test_import_audio_file.py b/api/tests/test_import_audio_file.py
index 04c06a8f462fbdd7db3dfe4e31139f7edc5585c6..7ee1028c8fd7e331208474a7a871bd41931e1bb4 100644
--- a/api/tests/test_import_audio_file.py
+++ b/api/tests/test_import_audio_file.py
@@ -352,3 +352,17 @@ def test_handle_modified_update_existing_path_if_found_and_attributed_to(
         event=event, stdout=stdout, library=library, in_place=True,
     )
     update_track_metadata.assert_not_called()
+
+
+def test_import_files(factories, capsys):
+    # smoke test to ensure the command run properly
+    library = factories["music.Library"](actor__local=True)
+    call_command(
+        "import_files", str(library.uuid), DATA_DIR, interactive=False, recursive=True
+    )
+    captured = capsys.readouterr()
+
+    imported = library.uploads.filter(import_status="finished").count()
+    assert imported > 0
+    assert "Successfully imported {} new tracks".format(imported) in captured.out
+    assert "For details, please refer to import reference" in captured.out
diff --git a/changes/changelog.d/1048.bugfix b/changes/changelog.d/1048.bugfix
new file mode 100644
index 0000000000000000000000000000000000000000..0f1973444147ffad54d32a715f7fa5d9a07dda28
--- /dev/null
+++ b/changes/changelog.d/1048.bugfix
@@ -0,0 +1 @@
+Fixed recursive CLI importing crashing under Python 3.5 (#1148, #1147)
diff --git a/changes/changelog.d/1113.enhancement b/changes/changelog.d/1113.enhancement
new file mode 100644
index 0000000000000000000000000000000000000000..979b33056dfd728c2b2ca9c1298962cfa25d7b2a
--- /dev/null
+++ b/changes/changelog.d/1113.enhancement
@@ -0,0 +1 @@
+Added new channels widget on pod landing page (#1113)
diff --git a/changes/changelog.d/1117.bugfix b/changes/changelog.d/1117.bugfix
new file mode 100644
index 0000000000000000000000000000000000000000..b2236ee70ae1d1186322e5f57d1d50a9d74d70d4
--- /dev/null
+++ b/changes/changelog.d/1117.bugfix
@@ -0,0 +1 @@
+Fixed a wording issue on artist channel page (#1117)
diff --git a/changes/changelog.d/1151.enhancement b/changes/changelog.d/1151.enhancement
new file mode 100644
index 0000000000000000000000000000000000000000..c9b867a30208c3669a9d4b93571add7fc588e04b
--- /dev/null
+++ b/changes/changelog.d/1151.enhancement
@@ -0,0 +1 @@
+Updated the /api/v1/libraries endpoint to support listing public libraries from other users/pods (#1151)
diff --git a/changes/notes.rst b/changes/notes.rst
index ee03756587bdb21f04c4abe9f5311a5df5143928..8d84dc02621ce2db8bd1b62ea5dac3300e0a510a 100644
--- a/changes/notes.rst
+++ b/changes/notes.rst
@@ -18,3 +18,16 @@ Because of this change, existing thumbnails will not load, and you will need to:
 2. run ``python manage.py fw media generate-thumbnails`` to regenerate thumbnails with the enhanced quality
 
 If you don't want to regenerate thumbnails, you can keep the old ones by adding ``THUMBNAIL_JPEG_RESIZE_QUALITY=70`` to your .env file.
+
+Small API breaking change in ``/api/v1/libraries``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To allow easier crawling of public libraries on a pod,we had to make a slight breaking change
+to the behaviour of ``GET /api/v1/libraries``.
+
+Before, it returned only libraries owned by the current user.
+
+Now, it returns all the accessible libraries (including ones from other users and pods).
+
+If you are consuming the API via a third-party client and need to retrieve your libraries,
+use the ``scope`` parameter, like this: ``GET /api/v1/libraries?scope=me``
diff --git a/front/src/components/Home.vue b/front/src/components/Home.vue
index 2d010bb5e26e110ae27a2ace6fa79e6e8a117fea..a872022f1c468ed0ac33c8cd0dc9cded7baeed04 100644
--- a/front/src/components/Home.vue
+++ b/front/src/components/Home.vue
@@ -173,6 +173,12 @@
           <div class="ui hidden divider"></div>
         </router-link>
       </album-widget>
+      <div class="ui hidden section divider"></div>
+      <h3 class="ui header" >
+        <translate translate-context="*/*/*">New channels</translate>
+      </h3>
+      <channels-widget :show-modification-date="true" :limit="10" :filters="{ordering: '-creation_date', external: 'false'}"></channels-widget>
+
     </section>
   </main>
 </template>
@@ -183,6 +189,7 @@ import _ from '@/lodash'
 import {mapState} from 'vuex'
 import showdown from 'showdown'
 import AlbumWidget from "@/components/audio/album/Widget"
+import ChannelsWidget from "@/components/audio/ChannelsWidget"
 import LoginForm from "@/components/auth/LoginForm"
 import SignupForm from "@/components/auth/SignupForm"
 import {humanSize } from '@/filters'
@@ -190,6 +197,7 @@ import {humanSize } from '@/filters'
 export default {
   components: {
     AlbumWidget,
+    ChannelsWidget,
     LoginForm,
     SignupForm,
   },
diff --git a/front/src/views/channels/DetailBase.vue b/front/src/views/channels/DetailBase.vue
index 0aaa735be7de807a64fd646ba065866d38266839..f838b0e8395e9b8af8060f7159a4a026e6ba53e8 100644
--- a/front/src/views/channels/DetailBase.vue
+++ b/front/src/views/channels/DetailBase.vue
@@ -18,11 +18,14 @@
                 <template v-if="totalTracks > 0">
                   <div class="ui hidden very small divider"></div>
                   <translate translate-context="Content/Channel/Paragraph"
+                    key="1"
+                    v-if="object.artist.content_category === 'podcast'"
                     translate-plural="%{ count } episodes"
                     :translate-n="totalTracks"
                     :translate-params="{count: totalTracks}">
                     %{ count } episode
                   </translate>
+                  <translate key="2" v-else translate-context="*/*/*" :translate-params="{count: totalTracks}" :translate-n="totalTracks" translate-plural="%{ count } tracks">%{ count } track</translate>
                 </template>
                 <template v-if="object.attributed_to.full_username === $store.state.auth.fullUsername || $store.getters['channels/isSubscribed'](object.uuid)">
                   ยท <translate translate-context="Content/Channel/Paragraph" translate-plural="%{ count } subscribers" :translate-n="object.subscriptions_count" :translate-params="{count: object.subscriptions_count}">%{ count } subscriber</translate>
diff --git a/front/src/views/content/libraries/Home.vue b/front/src/views/content/libraries/Home.vue
index aeb61e9b2dddd555193e7a22269d2b583d1460c1..9a491bf54743ae2646b8de970baa2f09c52bb2c2 100644
--- a/front/src/views/content/libraries/Home.vue
+++ b/front/src/views/content/libraries/Home.vue
@@ -53,7 +53,7 @@ export default {
     fetch() {
       this.isLoading = true
       let self = this
-      axios.get("libraries/").then(response => {
+      axios.get("libraries/", {params: {scope: 'me'}}).then(response => {
         self.isLoading = false
         self.libraries = response.data.results
         if (self.libraries.length === 0) {