diff --git a/CHANGELOG.md b/CHANGELOG.md
index ca4d549091e161fdd2b9441431d973c3f780a6e6..6ecfe23c8e7c01a1edf38ada32400e5c237cf5a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.6.0
+
+-   Add application navigation widgets
+
 ## 0.5.0
 
 -   Add activity parameters widgets
diff --git a/lib/flutter_toolbox.dart b/lib/flutter_toolbox.dart
index f4b591f1bb0019f27b912c7ec1db7709f8f2bf96..4676362268fbaa539130a5de668c94b77862fea7 100644
--- a/lib/flutter_toolbox.dart
+++ b/lib/flutter_toolbox.dart
@@ -33,6 +33,21 @@ export 'parameters/settings/settings_activity_cubit.dart'
     show ActivitySettingsCubit, ActivitySettingsState;
 export 'parameters/models/settings/settings_activity.dart' show ActivitySettings;
 
+export 'nav/application_navigation_definition.dart'
+    show
+        ScreenItem,
+        ActivityPageItem,
+        ApplicationNavigation,
+        AppBarConfiguration,
+        AppBarButton;
+export 'nav/cubit/nav_cubit_screens.dart' show NavCubitScreen;
+export 'nav/cubit/nav_cubit_pages.dart' show NavCubitPage;
+export 'nav/ui/screens/about.dart' show ScreenAbout;
+export 'nav/ui/screens/activity.dart' show ScreenActivity;
+export 'nav/ui/screens/settings.dart' show ScreenSettings;
+export 'nav/ui/bottom_nav_bar.dart' show BottomNavBar;
+export 'nav/ui/global_app_bar.dart' show GlobalAppBar;
+
 // dependencies
 
 export 'package:easy_localization/easy_localization.dart'
diff --git a/lib/nav/application_navigation_definition.dart b/lib/nav/application_navigation_definition.dart
new file mode 100644
index 0000000000000000000000000000000000000000..5e5809e69b950606468eeb35072df81f3925b301
--- /dev/null
+++ b/lib/nav/application_navigation_definition.dart
@@ -0,0 +1,130 @@
+import 'package:flutter/material.dart';
+
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+/// A screen item,
+///
+/// Normalized screens are: "activity", "settings" and "about".
+///
+/// These are set in [ApplicationNavigation] with
+/// - [ApplicationNavigation.screenActivity]
+/// - [ApplicationNavigation.screenSettings]
+/// - [ApplicationNavigation.screenAbout]
+///
+class ScreenItem {
+  final String code;
+  final Icon icon;
+  final Widget Function({required ApplicationConfigDefinition appConfig}) screen;
+
+  const ScreenItem({
+    required this.code,
+    required this.icon,
+    required this.screen,
+  });
+}
+
+/// A page in [ScreenItem] given in [ApplicationNavigation.screenActivity]
+///
+/// These are set in [ApplicationNavigation] with
+/// [ApplicationNavigation.activityPages].
+///
+class ActivityPageItem {
+  final String code;
+  final Icon? icon;
+  final Widget Function({required ApplicationConfigDefinition appConfig}) builder;
+
+  const ActivityPageItem({
+    required this.code,
+    this.icon,
+    required this.builder,
+  });
+
+  factory ActivityPageItem.empty() {
+    return ActivityPageItem(
+      code: '',
+      builder: ({required ApplicationConfigDefinition appConfig}) => Text(''),
+    );
+  }
+}
+
+/// Custom AppBar configuration
+///
+class AppBarConfiguration {
+  final bool? hideApplicationTitle;
+  final bool? pushQuitActivityButtonLeft;
+  final bool? hideQuitActivityButton;
+  final List<AppBarButton> Function(BuildContext context)? topBarButtonsBuilder;
+
+  const AppBarConfiguration({
+    this.hideApplicationTitle = false,
+    this.pushQuitActivityButtonLeft = false,
+    this.hideQuitActivityButton = false,
+    this.topBarButtonsBuilder,
+  });
+}
+
+/// Custom AppBar button (will generate a widget [IconButton])
+///
+class AppBarButton {
+  final Icon icon;
+  final Function(BuildContext context)? onPressed;
+  final Function(BuildContext context)? onLongPress;
+
+  const AppBarButton({
+    required this.icon,
+    this.onPressed,
+    this.onLongPress,
+  });
+}
+
+/// Navigation configuration for application
+///
+class ApplicationNavigation {
+  final ScreenItem screenActivity;
+  final ScreenItem screenSettings;
+  final ScreenItem screenAbout;
+  final AppBarConfiguration? appBarConfiguration;
+  final Map<int, ActivityPageItem> activityPages;
+  final bool displayBottomNavBar;
+
+  const ApplicationNavigation({
+    required this.screenActivity,
+    required this.screenSettings,
+    required this.screenAbout,
+    this.appBarConfiguration,
+    required this.activityPages,
+    this.displayBottomNavBar = false,
+  });
+
+  static const indexActivity = 0;
+  static const indexSettings = 1;
+  static const indexAbout = 2;
+
+  ScreenItem getScreen(int screenIndex) {
+    switch (screenIndex) {
+      case indexActivity:
+        return screenActivity;
+      case indexSettings:
+        return screenSettings;
+      case indexAbout:
+        return screenAbout;
+      default:
+        return screenActivity;
+    }
+  }
+
+  ScreenItem getActivityScreen() {
+    return screenActivity;
+  }
+
+  Widget getScreenWidget({
+    required ApplicationConfigDefinition appConfig,
+    required int screenIndex,
+  }) {
+    return getScreen(screenIndex).screen(appConfig: appConfig);
+  }
+
+  bool isActivityPageIndexAllowed(int pageIndex) {
+    return activityPages.keys.contains(pageIndex);
+  }
+}
diff --git a/lib/nav/cubit/nav_cubit_pages.dart b/lib/nav/cubit/nav_cubit_pages.dart
new file mode 100644
index 0000000000000000000000000000000000000000..cf38b7664cbf734a67af19d94c051e686cffcb54
--- /dev/null
+++ b/lib/nav/cubit/nav_cubit_pages.dart
@@ -0,0 +1,27 @@
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+class NavCubitPage extends HydratedCubit<int> {
+  NavCubitPage({
+    required this.appConfig,
+  }) : super(0);
+
+  final ApplicationConfigDefinition appConfig;
+
+  void updateIndex(int index) {
+    if (appConfig.navigation.isActivityPageIndexAllowed(index)) {
+      emit(index);
+    } else {
+      emit(0);
+    }
+  }
+
+  @override
+  int fromJson(Map<String, dynamic> json) {
+    return 0;
+  }
+
+  @override
+  Map<String, dynamic>? toJson(int state) {
+    return <String, int>{'index': state};
+  }
+}
diff --git a/lib/nav/cubit/nav_cubit_screens.dart b/lib/nav/cubit/nav_cubit_screens.dart
new file mode 100644
index 0000000000000000000000000000000000000000..1b15747eb54a49dff2d38f33a55d3cf805182928
--- /dev/null
+++ b/lib/nav/cubit/nav_cubit_screens.dart
@@ -0,0 +1,27 @@
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+class NavCubitScreen extends HydratedCubit<int> {
+  NavCubitScreen() : super(0);
+
+  void goToScreenActivity() {
+    emit(0);
+  }
+
+  void goToScreenSettings() {
+    emit(1);
+  }
+
+  void goToScreenAbout() {
+    emit(2);
+  }
+
+  @override
+  int fromJson(Map<String, dynamic> json) {
+    return 0;
+  }
+
+  @override
+  Map<String, dynamic>? toJson(int state) {
+    return <String, int>{'index': state};
+  }
+}
diff --git a/lib/nav/ui/bottom_nav_bar.dart b/lib/nav/ui/bottom_nav_bar.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3dc549a829d48976c3b2219e39e23b9be824f12b
--- /dev/null
+++ b/lib/nav/ui/bottom_nav_bar.dart
@@ -0,0 +1,48 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+class BottomNavBar extends StatelessWidget {
+  const BottomNavBar({
+    super.key,
+    required this.appConfig,
+  });
+
+  final ApplicationConfigDefinition appConfig;
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      margin: const EdgeInsets.only(top: 1, right: 4, left: 4),
+      elevation: 4,
+      shadowColor: Theme.of(context).colorScheme.shadow,
+      color: Theme.of(context).colorScheme.surfaceContainerHighest,
+      shape: const RoundedRectangleBorder(
+        borderRadius: BorderRadius.only(
+          topLeft: Radius.circular(16),
+          topRight: Radius.circular(16),
+        ),
+      ),
+      child: BlocBuilder<NavCubitPage, int>(builder: (BuildContext context, int state) {
+        final List<BottomNavigationBarItem> items = [];
+
+        appConfig.navigation.activityPages.forEach((int pageIndex, ActivityPageItem item) {
+          items.add(BottomNavigationBarItem(
+            icon: item.icon ?? Icon(null),
+            label: tr(item.code),
+          ));
+        });
+
+        return BottomNavigationBar(
+          currentIndex: state,
+          onTap: (int index) => BlocProvider.of<NavCubitPage>(context).updateIndex(index),
+          type: BottomNavigationBarType.fixed,
+          elevation: 0,
+          backgroundColor: Colors.transparent,
+          selectedItemColor: Theme.of(context).colorScheme.primary,
+          unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
+          items: items,
+        );
+      }),
+    );
+  }
+}
diff --git a/lib/nav/ui/global_app_bar.dart b/lib/nav/ui/global_app_bar.dart
new file mode 100644
index 0000000000000000000000000000000000000000..86d42a47f95dd6aed83c05837dc2d7bea998a3fe
--- /dev/null
+++ b/lib/nav/ui/global_app_bar.dart
@@ -0,0 +1,98 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
+  const GlobalAppBar({
+    super.key,
+    required this.appConfig,
+    required this.pageIndex,
+    required this.isActivityRunning,
+  });
+
+  final ApplicationConfigDefinition appConfig;
+  final int pageIndex;
+  final bool isActivityRunning;
+
+  @override
+  Widget build(BuildContext context) {
+    final bool displayQuitActivityButton =
+        !(appConfig.navigation.appBarConfiguration?.hideQuitActivityButton ?? false);
+
+    final bool pushQuitActivityButtonLeft =
+        (appConfig.navigation.appBarConfiguration?.pushQuitActivityButtonLeft == true);
+
+    final bool showApplicationTitle =
+        !(appConfig.navigation.appBarConfiguration?.hideApplicationTitle ?? false);
+
+    final List<AppBarButton> Function(BuildContext context) builder =
+        appConfig.navigation.appBarConfiguration?.topBarButtonsBuilder ??
+            // Default top bar buttons
+            (BuildContext context) {
+              if (isActivityRunning) {
+                return <AppBarButton>[];
+              }
+
+              return <AppBarButton>[
+                // Go to About page
+                AppBarButton(
+                  onPressed: (BuildContext context) =>
+                      BlocProvider.of<NavCubitScreen>(context).goToScreenAbout(),
+                  icon: appConfig.navigation.screenAbout.icon,
+                ),
+
+                // Go to Settings page
+                AppBarButton(
+                  onPressed: (BuildContext context) =>
+                      BlocProvider.of<NavCubitScreen>(context).goToScreenSettings(),
+                  icon: appConfig.navigation.screenSettings.icon,
+                ),
+
+                // Back to Home page
+                AppBarButton(
+                  onPressed: (BuildContext context) =>
+                      BlocProvider.of<NavCubitScreen>(context).goToScreenActivity(),
+                  icon: appConfig.navigation.screenActivity.icon,
+                ),
+              ];
+            };
+
+    final List<Widget> menuActions = [];
+
+    // left pushed "quit activity" button
+    if (isActivityRunning && displayQuitActivityButton && pushQuitActivityButtonLeft) {
+      menuActions.add(ActivityButtonQuit(
+        onPressed: () {},
+        onLongPress: () => appConfig.quitCurrentActivity(context),
+      ));
+
+      menuActions.add(const Spacer(flex: 6));
+    }
+
+    // add buttons
+    final List<AppBarButton> buttons = builder(context);
+    for (AppBarButton button in buttons) {
+      menuActions.add(ElevatedButton(
+        onPressed: () => button.onPressed!(context),
+        onLongPress: () => button.onLongPress!(context),
+        style: ElevatedButton.styleFrom(shape: const CircleBorder()),
+        child: button.icon,
+      ));
+    }
+
+    // standard right pushed "quit activity" button
+    if (isActivityRunning && displayQuitActivityButton && !pushQuitActivityButtonLeft) {
+      menuActions.add(ActivityButtonQuit(
+        onPressed: () {},
+        onLongPress: () => appConfig.quitCurrentActivity(context),
+      ));
+    }
+
+    return AppBar(
+      title: showApplicationTitle ? const AppHeader(text: 'app_name') : null,
+      actions: menuActions,
+    );
+  }
+
+  @override
+  Size get preferredSize => const Size.fromHeight(50);
+}
diff --git a/lib/nav/ui/screens/about.dart b/lib/nav/ui/screens/about.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f7a14a9a7e574a7b6f9ed181f38d08ba8c2285fe
--- /dev/null
+++ b/lib/nav/ui/screens/about.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+class ScreenAbout extends StatelessWidget {
+  const ScreenAbout({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 8),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.max,
+        children: <Widget>[
+          const SizedBox(height: 8),
+          const AppTitle(text: 'about_title'),
+          const Text('about_content').tr(),
+          FutureBuilder<PackageInfo>(
+            future: PackageInfo.fromPlatform(),
+            builder: (context, snapshot) {
+              switch (snapshot.connectionState) {
+                case ConnectionState.done:
+                  return const Text('about_version').tr(
+                    namedArgs: {
+                      'version': snapshot.data!.version,
+                    },
+                  );
+                default:
+                  return const SizedBox();
+              }
+            },
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/nav/ui/screens/activity.dart b/lib/nav/ui/screens/activity.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f1d1f3184ede79b2f73f7cc343cc4202adf774b1
--- /dev/null
+++ b/lib/nav/ui/screens/activity.dart
@@ -0,0 +1,29 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+class ScreenActivity extends StatelessWidget {
+  const ScreenActivity({
+    super.key,
+    required this.appConfig,
+  });
+
+  final ApplicationConfigDefinition appConfig;
+
+  ActivityPageItem getActivityPage(int pageIndex) {
+    if (appConfig.navigation.activityPages.keys.contains(pageIndex)) {
+      return appConfig.navigation.activityPages[pageIndex] ?? ActivityPageItem.empty();
+    } else {
+      return getActivityPage(appConfig.navigation.activityPages.keys.first);
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<NavCubitPage, int>(
+      builder: (BuildContext context, int pageIndex) {
+        final ActivityPageItem page = getActivityPage(pageIndex);
+        return page.builder(appConfig: appConfig);
+      },
+    );
+  }
+}
diff --git a/lib/nav/ui/screens/settings.dart b/lib/nav/ui/screens/settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..7981b1c6becc4f5b925c3058b05423750d80f62e
--- /dev/null
+++ b/lib/nav/ui/screens/settings.dart
@@ -0,0 +1,24 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+class ScreenSettings extends StatelessWidget {
+  const ScreenSettings({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return const Padding(
+      padding: EdgeInsets.symmetric(horizontal: 8),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.max,
+        children: <Widget>[
+          SizedBox(height: 8),
+          AppTitle(text: 'settings_title'),
+          SizedBox(height: 8),
+          ApplicationSettingsForm(),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/parameters/application_config_definition.dart b/lib/parameters/application_config_definition.dart
index 82c0e2e2589a602fede7e68dff317295f79b4d5d..2abba76dece58b4a47722c7584bb8ef2ecf06eff 100644
--- a/lib/parameters/application_config_definition.dart
+++ b/lib/parameters/application_config_definition.dart
@@ -5,16 +5,22 @@ import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 class ApplicationConfigDefinition {
   final String appTitle;
   final List<ApplicationSettingsParameter> activitySettings;
+  final bool autoStartActivity;
   final void Function(BuildContext context) startNewActivity;
+  final void Function(BuildContext context) quitCurrentActivity;
   final void Function(BuildContext context) deleteCurrentActivity;
   final void Function(BuildContext context) resumeActivity;
+  final ApplicationNavigation navigation;
 
   const ApplicationConfigDefinition({
     required this.appTitle,
     required this.activitySettings,
+    this.autoStartActivity = false,
     required this.startNewActivity,
+    required this.quitCurrentActivity,
     required this.deleteCurrentActivity,
     required this.resumeActivity,
+    required this.navigation,
   });
 
   ApplicationSettingsParameter getFromCode(String paramCode) {
diff --git a/lib/parameters/pages/parameters.dart b/lib/parameters/pages/parameters.dart
index 92a065d3779ef68e850929340cebcb57fa2a4e06..4d98e6191f30e57dde5d6403013edc44b639abdf 100644
--- a/lib/parameters/pages/parameters.dart
+++ b/lib/parameters/pages/parameters.dart
@@ -5,11 +5,11 @@ import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 class PageParameters extends StatelessWidget {
   const PageParameters({
     super.key,
-    required this.config,
+    required this.appConfig,
     required this.canBeResumed,
   });
 
-  final ApplicationConfigDefinition config;
+  final ApplicationConfigDefinition appConfig;
   final bool canBeResumed;
 
   final double separatorHeight = 8.0;
@@ -19,7 +19,7 @@ class PageParameters extends StatelessWidget {
     final List<Widget> lines = [];
 
     // Activity settings (top)
-    for (ApplicationSettingsParameter parameter in config.activitySettings) {
+    for (ApplicationSettingsParameter parameter in appConfig.activitySettings) {
       if (parameter.displayedOnTop) {
         lines.add(Row(
           mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -43,7 +43,7 @@ class PageParameters extends StatelessWidget {
         aspectRatio: 3,
         child: ActivityButtonResumeSaved(
           onPressed: () {
-            config.resumeActivity(context);
+            appConfig.resumeActivity(context);
           },
         ),
       ));
@@ -52,7 +52,7 @@ class PageParameters extends StatelessWidget {
         dimension: MediaQuery.of(context).size.width / 5,
         child: ActivityButtonDeleteSaved(
           onPressed: () {
-            config.deleteCurrentActivity(context);
+            appConfig.deleteCurrentActivity(context);
           },
         ),
       ));
@@ -63,7 +63,7 @@ class PageParameters extends StatelessWidget {
           aspectRatio: 3,
           child: ActivityButtonStartNew(
             onPressed: () {
-              config.startNewActivity(context);
+              appConfig.startNewActivity(context);
             },
           ),
         ),
@@ -73,7 +73,7 @@ class PageParameters extends StatelessWidget {
     lines.add(SizedBox(height: separatorHeight));
 
     // Activity settings (bottom)
-    for (ApplicationSettingsParameter parameter in config.activitySettings) {
+    for (ApplicationSettingsParameter parameter in appConfig.activitySettings) {
       if (!parameter.displayedOnTop) {
         lines.add(Row(
           mainAxisAlignment: MainAxisAlignment.spaceBetween,
diff --git a/pubspec.yaml b/pubspec.yaml
index 231b7b68f2f835d5774c630a3df874a0969f1ede..883ba0bd428ba33f3bc40c91c2207021a0979bd0 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: "Flutter custom toolbox for org.benoitharrault.* projects."
 
 publish_to: "none"
 
-version: 0.5.0
+version: 0.6.0
 
 homepage: https://git.harrault.fr/android/flutter-toolbox