diff --git a/android/gradle.properties b/android/gradle.properties
index cc4e56eef743ffd4a67a64f0b67840717af81ff4..9742e8d9ac872ece07c6ae62a041bc05c2a8fcc6 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.0.30
-app.versionCode=30
+app.versionName=0.0.31
+app.versionCode=31
diff --git a/fastlane/metadata/android/en-US/changelogs/31.txt b/fastlane/metadata/android/en-US/changelogs/31.txt
new file mode 100644
index 0000000000000000000000000000000000000000..30a73655fefce7357a8e7a2b93e61ad5e5595bd0
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/31.txt
@@ -0,0 +1 @@
+Improve swipe navigation.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/31.txt b/fastlane/metadata/android/fr-FR/changelogs/31.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ab5d5e3ad725ba6ed541eba34c218aa934e3ac81
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/31.txt
@@ -0,0 +1 @@
+Amélioration de la navigation par swipe.
diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/bottom_nav_cubit.dart
index d061b97a5c5d706c9e01c9e2ad8197f5e02987d5..8753255ac7acba27b594ea5cfb5b46aafee31625 100644
--- a/lib/cubit/bottom_nav_cubit.dart
+++ b/lib/cubit/bottom_nav_cubit.dart
@@ -3,18 +3,25 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
 class BottomNavCubit extends HydratedCubit<int> {
   BottomNavCubit() : super(0);
 
-  void updateIndex(int index) => emit(index);
+  int pagesCount = 3;
 
-  void movePrevious() => emit((state > 0) ? state - 1 : state);
-  void moveNext() => emit((state < 2) ? state + 1 : state);
+  void updateIndex(int index) {
+    if (isIndexAllowed(index)) {
+      emit(index);
+    } else {
+      goToHomePage();
+    }
+  }
+
+  bool isIndexAllowed(int index) {
+    return (index >= 0) && (index < pagesCount);
+  }
 
-  void getHomePage() => emit(0);
-  void getDiscoveriesPage() => emit(1);
-  void getStatisticsPage() => emit(2);
+  void goToHomePage() => emit(0);
 
   @override
   int? fromJson(Map<String, dynamic> json) {
-    return json['pageIndex'] as int?;
+    return 0;
   }
 
   @override
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index ad00a7b0684aeebd6b7ee724f968f81de8211bec..00d12050b2e2fed3011b139d69079500a3268281 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -1,5 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_swipe/flutter_swipe.dart';
 
 import 'package:scrobbles/cubit/bottom_nav_cubit.dart';
 import 'package:scrobbles/ui/screens/discoveries.dart';
@@ -28,28 +29,31 @@ class _SkeletonScreenState extends State<SkeletonScreen> {
       create: (BuildContext context) => BottomNavCubit(),
       child: BlocBuilder<BottomNavCubit, int>(
         builder: (BuildContext context, int state) {
-          return GestureDetector(
-            onHorizontalDragEnd: (dragDetail) {
-              if (dragDetail.velocity.pixelsPerSecond.dx < 1) {
-                context.read<BottomNavCubit>().moveNext();
-              } else {
-                context.read<BottomNavCubit>().movePrevious();
-              }
-            },
-            child: Scaffold(
-              appBar: StandardAppBar(notifyParent: refresh),
-              extendBodyBehindAppBar: false,
-              body: BlocBuilder<BottomNavCubit, int>(
-                builder: (BuildContext context, int state) {
-                  return AnimatedSwitcher(
-                    duration: const Duration(milliseconds: 300),
-                    child: pageNavigation.elementAt(state),
-                  );
-                },
+          return Scaffold(
+            appBar: StandardAppBar(notifyParent: refresh),
+            extendBodyBehindAppBar: false,
+            body: Swiper(
+              itemCount: BlocProvider.of<BottomNavCubit>(context).pagesCount,
+              itemBuilder: (BuildContext context, int index) {
+                return AnimatedSwitcher(
+                  duration: const Duration(milliseconds: 300),
+                  child: pageNavigation.elementAt(index),
+                );
+              },
+              pagination: SwiperPagination(
+                builder: SwiperCustomPagination(
+                  builder: (BuildContext context, SwiperPluginConfig config) {
+                    return BottomNavBar(swipeController: config.controller);
+                  },
+                ),
               ),
-              bottomNavigationBar: const BottomNavBar(),
-              backgroundColor: Theme.of(context).colorScheme.background,
+              onIndexChanged: (newPageIndex) {
+                BlocProvider.of<BottomNavCubit>(context).updateIndex(newPageIndex);
+              },
+              outer: true,
+              loop: false,
             ),
+            backgroundColor: Theme.of(context).colorScheme.background,
           );
         },
       ),
diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart
index 3d2fb30aef2cad40d0b7170087e45749bbb45d09..daaed377dc3b2c28f8bf1a9cf0d0927396552e81 100644
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ b/lib/ui/widgets/bottom_nav_bar.dart
@@ -1,17 +1,24 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_swipe/flutter_swipe.dart';
 import 'package:ionicons/ionicons.dart';
 
 import 'package:scrobbles/cubit/bottom_nav_cubit.dart';
 
 class BottomNavBar extends StatelessWidget {
-  const BottomNavBar({super.key});
+  const BottomNavBar({super.key, required this.swipeController});
+
+  final SwiperController swipeController;
 
   @override
   Widget build(BuildContext context) {
     return Card(
-      margin: const EdgeInsets.only(top: 1, right: 4, left: 4),
+      margin: const EdgeInsets.only(
+        top: 1,
+        right: 0,
+        left: 0,
+      ),
       elevation: 4,
       shadowColor: Theme.of(context).colorScheme.shadow,
       color: Theme.of(context).colorScheme.surfaceVariant,
@@ -25,7 +32,10 @@ class BottomNavBar extends StatelessWidget {
         builder: (BuildContext context, int state) {
           return BottomNavigationBar(
             currentIndex: state,
-            onTap: (int index) => context.read<BottomNavCubit>().updateIndex(index),
+            onTap: (int index) {
+              context.read<BottomNavCubit>().updateIndex(index);
+              swipeController.move(index);
+            },
             type: BottomNavigationBarType.fixed,
             elevation: 0,
             backgroundColor: Colors.transparent,
diff --git a/pubspec.lock b/pubspec.lock
index 9af792b493a76bf64aaa1fa945893b3be4afc0a1..e194593eb71c678f2003542d4360a296dc8ff551 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -123,6 +123,14 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_swipe:
+    dependency: "direct main"
+    description:
+      name: flutter_swipe
+      sha256: dc6541bac3a0545ce15a3fa15913f6250532062960bf6b0ad4562d02f14a8545
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.1"
   flutter_web_plugins:
     dependency: transitive
     description: flutter
diff --git a/pubspec.yaml b/pubspec.yaml
index ae9030af9e65fad26af9b0f39c18bbbbaa8fb4fe..a76c11d6766afd8ae1153b80103de06fe158e82a 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: Display scrobbles data and charts
 
 publish_to: 'none'
 
-version: 0.0.30+30
+version: 0.0.31+31
 
 environment:
   sdk: '^3.0.0'
@@ -21,6 +21,7 @@ dependencies:
   hydrated_bloc: ^9.0.0
   ionicons: ^0.2.2
   unicons: ^2.1.1
+  flutter_swipe: ^1.0.1
 
 flutter:
   uses-material-design: false