diff --git a/android/gradle.properties b/android/gradle.properties
index 1716fb7f8a2bf4d5084295416dc53574c3ad38db..588e695c30a170652ec0f6e7ae0648d5d3a099ae 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=1.2.28
-app.versionCode=34
+app.versionName=1.2.29
+app.versionCode=35
diff --git a/assets/fonts/Nunito-Bold.ttf b/assets/fonts/Nunito-Bold.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..6519feb781449ebe0015cbc74dfd9e13110fbba9
Binary files /dev/null and b/assets/fonts/Nunito-Bold.ttf differ
diff --git a/assets/fonts/Nunito-Light.ttf b/assets/fonts/Nunito-Light.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..8a0736c41cd6c2a1225d356bf274de1d0afc3497
Binary files /dev/null and b/assets/fonts/Nunito-Light.ttf differ
diff --git a/assets/fonts/Nunito-Medium.ttf b/assets/fonts/Nunito-Medium.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..88fccdc0638b6f5d6ac49d9d269dc3d518618ad1
Binary files /dev/null and b/assets/fonts/Nunito-Medium.ttf differ
diff --git a/assets/fonts/Nunito-Regular.ttf b/assets/fonts/Nunito-Regular.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..e7b8375a896ef0cd8e06730a78c84532b377e784
Binary files /dev/null and b/assets/fonts/Nunito-Regular.ttf differ
diff --git a/assets/translations/en.json b/assets/translations/en.json
new file mode 100644
index 0000000000000000000000000000000000000000..42ca82760c02ee4dfb2a118e5147f15875ad76f7
--- /dev/null
+++ b/assets/translations/en.json
@@ -0,0 +1,16 @@
+{
+  "app_name": "Categories",
+
+  "bottom_nav_home": "Game",
+  "bottom_nav_settings": "Settings",
+  "bottom_nav_about": "About",
+
+  "settings_title": "Settings",
+  "settings_label_timer_value":"Game turn allowed time",
+
+  "about_title": "Informations",
+  "about_content": "Categories",
+  "about_version": "Version: {version}",
+
+  "": ""
+}
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
new file mode 100644
index 0000000000000000000000000000000000000000..d953c429bb3b25ba086ce5f855f1931c22320866
--- /dev/null
+++ b/assets/translations/fr.json
@@ -0,0 +1,16 @@
+{
+  "app_name": "Petit Bac",
+
+  "bottom_nav_home": "Jeu",
+  "bottom_nav_settings": "Réglages",
+  "bottom_nav_about": "Infos",
+
+  "settings_title": "Réglages",
+  "settings_label_timer_value":"Durée du tour de jeu",
+
+  "about_title": "Informations",
+  "about_content": "Petit Bac.",
+  "about_version": "Version : {version}",
+
+  "": ""
+}
diff --git a/fastlane/metadata/android/en-US/changelogs/35.txt b/fastlane/metadata/android/en-US/changelogs/35.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6e253a4fc4840823e9a2501baad2a1c3d9c59c5e
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/35.txt
@@ -0,0 +1 @@
+Improve game architecture / conception.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/35.txt b/fastlane/metadata/android/fr-FR/changelogs/35.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6b644ba4d7245c59acd73fcbeb8fc47e1e843daa
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/35.txt
@@ -0,0 +1 @@
+Amélioration de l'architecture / conception du jeu.
diff --git a/lib/config/default_settings.dart b/lib/config/default_settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..fa6914950abd4edacadc6209c65cc769aceabf97
--- /dev/null
+++ b/lib/config/default_settings.dart
@@ -0,0 +1,12 @@
+class DefaultSettings {
+  static const List<int> allowedTimerValues = [
+    5,
+    10,
+    20,
+    30,
+    60,
+    90,
+  ];
+
+  static const int defaultTimerValue = 10;
+}
diff --git a/lib/config/menu.dart b/lib/config/menu.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4ba90b267d401a8c9ddfb8a611e88a7c0662f3c1
--- /dev/null
+++ b/lib/config/menu.dart
@@ -0,0 +1,54 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:unicons/unicons.dart';
+
+import 'package:petitbac/ui/screens/about_page.dart';
+import 'package:petitbac/ui/screens/game_page.dart';
+import 'package:petitbac/ui/screens/settings_page.dart';
+
+class MenuItem {
+  final String code;
+  final Icon icon;
+  final Widget page;
+
+  const MenuItem({
+    required this.code,
+    required this.icon,
+    required this.page,
+  });
+}
+
+class Menu {
+  static List<MenuItem> items = [
+    const MenuItem(
+      code: 'bottom_nav_home',
+      icon: Icon(UniconsLine.home),
+      page: GamePage(),
+    ),
+    const MenuItem(
+      code: 'bottom_nav_settings',
+      icon: Icon(UniconsLine.setting),
+      page: SettingsPage(),
+    ),
+    const MenuItem(
+      code: 'bottom_nav_about',
+      icon: Icon(UniconsLine.info_circle),
+      page: AboutPage(),
+    ),
+  ];
+
+  static Widget getPageWidget(int pageIndex) {
+    return Menu.items.elementAt(pageIndex).page;
+  }
+
+  static List<BottomNavigationBarItem> getMenuItems() {
+    return Menu.items
+        .map((MenuItem item) => BottomNavigationBarItem(
+              icon: item.icon,
+              label: tr(item.code),
+            ))
+        .toList();
+  }
+
+  static int itemsCount = Menu.items.length;
+}
diff --git a/lib/config/theme.dart b/lib/config/theme.dart
new file mode 100644
index 0000000000000000000000000000000000000000..be390348c7868e7c63387df13e13c46de43f8a23
--- /dev/null
+++ b/lib/config/theme.dart
@@ -0,0 +1,196 @@
+import 'package:flutter/material.dart';
+
+/// Colors from Tailwind CSS (v3.0) - June 2022
+///
+/// https://tailwindcss.com/docs/customizing-colors
+
+const int _primaryColor = 0xFF6366F1;
+const MaterialColor primarySwatch = MaterialColor(_primaryColor, <int, Color>{
+  50: Color(0xFFEEF2FF), // indigo-50
+  100: Color(0xFFE0E7FF), // indigo-100
+  200: Color(0xFFC7D2FE), // indigo-200
+  300: Color(0xFFA5B4FC), // indigo-300
+  400: Color(0xFF818CF8), // indigo-400
+  500: Color(_primaryColor), // indigo-500
+  600: Color(0xFF4F46E5), // indigo-600
+  700: Color(0xFF4338CA), // indigo-700
+  800: Color(0xFF3730A3), // indigo-800
+  900: Color(0xFF312E81), // indigo-900
+});
+
+const int _textColor = 0xFF64748B;
+const MaterialColor textSwatch = MaterialColor(_textColor, <int, Color>{
+  50: Color(0xFFF8FAFC), // slate-50
+  100: Color(0xFFF1F5F9), // slate-100
+  200: Color(0xFFE2E8F0), // slate-200
+  300: Color(0xFFCBD5E1), // slate-300
+  400: Color(0xFF94A3B8), // slate-400
+  500: Color(_textColor), // slate-500
+  600: Color(0xFF475569), // slate-600
+  700: Color(0xFF334155), // slate-700
+  800: Color(0xFF1E293B), // slate-800
+  900: Color(0xFF0F172A), // slate-900
+});
+
+const Color errorColor = Color(0xFFDC2626); // red-600
+
+final ColorScheme lightColorScheme = ColorScheme.light(
+  primary: primarySwatch.shade500,
+  secondary: primarySwatch.shade500,
+  onSecondary: Colors.white,
+  error: errorColor,
+  background: textSwatch.shade200,
+  onBackground: textSwatch.shade500,
+  onSurface: textSwatch.shade500,
+  surface: textSwatch.shade50,
+  surfaceVariant: Colors.white,
+  shadow: textSwatch.shade900.withOpacity(.1),
+);
+
+final ColorScheme darkColorScheme = ColorScheme.dark(
+  primary: primarySwatch.shade500,
+  secondary: primarySwatch.shade500,
+  onSecondary: Colors.white,
+  error: errorColor,
+  background: const Color(0xFF171724),
+  onBackground: textSwatch.shade400,
+  onSurface: textSwatch.shade300,
+  surface: const Color(0xFF262630),
+  surfaceVariant: const Color(0xFF282832),
+  shadow: textSwatch.shade900.withOpacity(.2),
+);
+
+final ThemeData lightTheme = ThemeData(
+  colorScheme: lightColorScheme,
+  fontFamily: 'Nunito',
+  textTheme: TextTheme(
+    displayLarge: TextStyle(
+      color: textSwatch.shade700,
+      fontFamily: 'Nunito',
+    ),
+    displayMedium: TextStyle(
+      color: textSwatch.shade600,
+      fontFamily: 'Nunito',
+    ),
+    displaySmall: TextStyle(
+      color: textSwatch.shade500,
+      fontFamily: 'Nunito',
+    ),
+    headlineLarge: TextStyle(
+      color: textSwatch.shade700,
+      fontFamily: 'Nunito',
+    ),
+    headlineMedium: TextStyle(
+      color: textSwatch.shade600,
+      fontFamily: 'Nunito',
+    ),
+    headlineSmall: TextStyle(
+      color: textSwatch.shade500,
+      fontFamily: 'Nunito',
+    ),
+    titleLarge: TextStyle(
+      color: textSwatch.shade700,
+      fontFamily: 'Nunito',
+    ),
+    titleMedium: TextStyle(
+      color: textSwatch.shade600,
+      fontFamily: 'Nunito',
+    ),
+    titleSmall: TextStyle(
+      color: textSwatch.shade500,
+      fontFamily: 'Nunito',
+    ),
+    bodyLarge: TextStyle(
+      color: textSwatch.shade700,
+      fontFamily: 'Nunito',
+    ),
+    bodyMedium: TextStyle(
+      color: textSwatch.shade600,
+      fontFamily: 'Nunito',
+    ),
+    bodySmall: TextStyle(
+      color: textSwatch.shade500,
+      fontFamily: 'Nunito',
+    ),
+    labelLarge: TextStyle(
+      color: textSwatch.shade700,
+      fontFamily: 'Nunito',
+    ),
+    labelMedium: TextStyle(
+      color: textSwatch.shade600,
+      fontFamily: 'Nunito',
+    ),
+    labelSmall: TextStyle(
+      color: textSwatch.shade500,
+      fontFamily: 'Nunito',
+    ),
+  ),
+);
+
+final ThemeData darkTheme = lightTheme.copyWith(
+  colorScheme: darkColorScheme,
+  textTheme: TextTheme(
+    displayLarge: TextStyle(
+      color: textSwatch.shade200,
+      fontFamily: 'Nunito',
+    ),
+    displayMedium: TextStyle(
+      color: textSwatch.shade300,
+      fontFamily: 'Nunito',
+    ),
+    displaySmall: TextStyle(
+      color: textSwatch.shade400,
+      fontFamily: 'Nunito',
+    ),
+    headlineLarge: TextStyle(
+      color: textSwatch.shade200,
+      fontFamily: 'Nunito',
+    ),
+    headlineMedium: TextStyle(
+      color: textSwatch.shade300,
+      fontFamily: 'Nunito',
+    ),
+    headlineSmall: TextStyle(
+      color: textSwatch.shade400,
+      fontFamily: 'Nunito',
+    ),
+    titleLarge: TextStyle(
+      color: textSwatch.shade200,
+      fontFamily: 'Nunito',
+    ),
+    titleMedium: TextStyle(
+      color: textSwatch.shade300,
+      fontFamily: 'Nunito',
+    ),
+    titleSmall: TextStyle(
+      color: textSwatch.shade400,
+      fontFamily: 'Nunito',
+    ),
+    bodyLarge: TextStyle(
+      color: textSwatch.shade200,
+      fontFamily: 'Nunito',
+    ),
+    bodyMedium: TextStyle(
+      color: textSwatch.shade300,
+      fontFamily: 'Nunito',
+    ),
+    bodySmall: TextStyle(
+      color: textSwatch.shade400,
+      fontFamily: 'Nunito',
+    ),
+    labelLarge: TextStyle(
+      color: textSwatch.shade200,
+      fontFamily: 'Nunito',
+    ),
+    labelMedium: TextStyle(
+      color: textSwatch.shade300,
+      fontFamily: 'Nunito',
+    ),
+    labelSmall: TextStyle(
+      color: textSwatch.shade400,
+      fontFamily: 'Nunito',
+    ),
+  ),
+);
+
+final ThemeData appTheme = darkTheme;
diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/bottom_nav_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ac26ae9efa1973afc7bbc10f413d59f0fa2155d8
--- /dev/null
+++ b/lib/cubit/bottom_nav_cubit.dart
@@ -0,0 +1,31 @@
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:petitbac/config/menu.dart';
+
+class BottomNavCubit extends HydratedCubit<int> {
+  BottomNavCubit() : super(0);
+
+  void updateIndex(int index) {
+    if (isIndexAllowed(index)) {
+      emit(index);
+    } else {
+      goToHomePage();
+    }
+  }
+
+  bool isIndexAllowed(int index) {
+    return (index >= 0) && (index < Menu.itemsCount);
+  }
+
+  void goToHomePage() => emit(0);
+
+  @override
+  int fromJson(Map<String, dynamic> json) {
+    return 0;
+  }
+
+  @override
+  Map<String, dynamic>? toJson(int state) {
+    return <String, int>{'pageIndex': state};
+  }
+}
diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..bfe94d2013ffa3bbf089f6a836373856c3fadb6c
--- /dev/null
+++ b/lib/cubit/game_cubit.dart
@@ -0,0 +1,35 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:petitbac/models/game/game.dart';
+
+part 'game_state.dart';
+
+class GameCubit extends HydratedCubit<GameState> {
+  GameCubit() : super(const GameState());
+
+  void getData(GameState gameState) {
+    emit(gameState);
+  }
+
+  void updateGameState(Game gameData) {
+    emit(GameState(game: gameData));
+  }
+
+  @override
+  GameState? fromJson(Map<String, dynamic> json) {
+    Game game = json['game'] as Game;
+
+    return GameState(
+      game: game,
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GameState state) {
+    return <String, dynamic>{
+      'game': state.game?.toJson(),
+    };
+  }
+}
diff --git a/lib/cubit/game_state.dart b/lib/cubit/game_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3e4d0d092cf5da751fd66f72dedea0501878acbd
--- /dev/null
+++ b/lib/cubit/game_state.dart
@@ -0,0 +1,15 @@
+part of 'game_cubit.dart';
+
+@immutable
+class GameState extends Equatable {
+  const GameState({
+    this.game,
+  });
+
+  final Game? game;
+
+  @override
+  List<Object?> get props => <Object?>[
+        game,
+      ];
+}
diff --git a/lib/cubit/settings_cubit.dart b/lib/cubit/settings_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d105a3fd9046cfcd57ad9cd9cda694698cb6f94a
--- /dev/null
+++ b/lib/cubit/settings_cubit.dart
@@ -0,0 +1,47 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:petitbac/config/default_settings.dart';
+
+part 'settings_state.dart';
+
+class SettingsCubit extends HydratedCubit<SettingsState> {
+  SettingsCubit() : super(const SettingsState());
+
+  Object getSetting(String key, [String? defaultValue]) {
+    if (state.values.keys.contains(key)) {
+      return state.values[key] ?? defaultValue ?? '';
+    }
+
+    return defaultValue ?? '';
+  }
+
+  int getTimerValue() {
+    return state.timerValue ?? DefaultSettings.defaultTimerValue;
+  }
+
+  void setValues({
+    int? timerValue,
+  }) {
+    emit(SettingsState(
+      timerValue: timerValue ?? state.timerValue,
+    ));
+  }
+
+  @override
+  SettingsState? fromJson(Map<String, dynamic> json) {
+    int timerValue = json['timerValue'] as int;
+
+    return SettingsState(
+      timerValue: timerValue,
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(SettingsState state) {
+    return <String, dynamic>{
+      'timerValue': state.timerValue ?? DefaultSettings.defaultTimerValue,
+    };
+  }
+}
diff --git a/lib/cubit/settings_state.dart b/lib/cubit/settings_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..6048256f247aeb898ba1b3b10ca2daae3468a7c9
--- /dev/null
+++ b/lib/cubit/settings_state.dart
@@ -0,0 +1,19 @@
+part of 'settings_cubit.dart';
+
+@immutable
+class SettingsState extends Equatable {
+  const SettingsState({
+    this.timerValue,
+  });
+
+  final int? timerValue;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        timerValue,
+      ];
+
+  Map<String, dynamic> get values => <String, dynamic>{
+        'timerValue': timerValue,
+      };
+}
diff --git a/lib/main.dart b/lib/main.dart
index 099ea049c3496af9005fad712fec50da153392d2..b90609c0fa03bf7963ee98aabd965f253995dc05 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,14 +1,42 @@
+import 'dart:io';
+
+import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:hive/hive.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+import 'package:path_provider/path_provider.dart';
 import 'package:provider/provider.dart';
-import 'package:flutter/services.dart';
 
+import 'package:petitbac/config/theme.dart';
+import 'package:petitbac/cubit/bottom_nav_cubit.dart';
+import 'package:petitbac/cubit/game_cubit.dart';
+import 'package:petitbac/cubit/settings_cubit.dart';
 import 'package:petitbac/provider/data.dart';
-import 'package:petitbac/screens/home.dart';
+import 'package:petitbac/ui/skeleton.dart';
 
-void main() {
+void main() async {
+  /// Initialize packages
   WidgetsFlutterBinding.ensureInitialized();
-  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
-      .then((value) => runApp(const MyApp()));
+  await EasyLocalization.ensureInitialized();
+  final Directory tmpDir = await getTemporaryDirectory();
+  Hive.init(tmpDir.toString());
+  HydratedBloc.storage = await HydratedStorage.build(
+    storageDirectory: tmpDir,
+  );
+
+  runApp(
+    EasyLocalization(
+      path: 'assets/translations',
+      supportedLocales: const <Locale>[
+        Locale('en'),
+        Locale('fr'),
+      ],
+      fallbackLocale: const Locale('en'),
+      useFallbackTranslations: true,
+      child: const MyApp(),
+    ),
+  );
 }
 
 class MyApp extends StatelessWidget {
@@ -16,22 +44,27 @@ class MyApp extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return ChangeNotifierProvider(
-      create: (BuildContext context) => Data(),
-      child: Consumer<Data>(
-        builder: (context, data, child) {
-          return MaterialApp(
-            debugShowCheckedModeBanner: false,
-            theme: ThemeData(
-              primaryColor: Colors.blue,
-              visualDensity: VisualDensity.adaptivePlatformDensity,
-            ),
-            home: const Home(),
-            routes: {
-              Home.id: (context) => const Home(),
-            },
-          );
-        },
+    return MultiBlocProvider(
+      providers: [
+        BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
+        BlocProvider<GameCubit>(create: (context) => GameCubit()),
+        BlocProvider<SettingsCubit>(create: (context) => SettingsCubit()),
+      ],
+      child: ChangeNotifierProvider(
+        create: (BuildContext context) => Data(),
+        child: Consumer<Data>(
+          builder: (context, data, child) {
+            return MaterialApp(
+              title: 'Petit Bac',
+              theme: appTheme,
+              home: const SkeletonScreen(),
+              localizationsDelegates: context.localizationDelegates,
+              supportedLocales: context.supportedLocales,
+              locale: context.locale,
+              debugShowCheckedModeBanner: false,
+            );
+          },
+        ),
       ),
     );
   }
diff --git a/lib/models/game/game.dart b/lib/models/game/game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ebe3d57f78a1ea5ed0b817ff40a1e293cde65ee7
--- /dev/null
+++ b/lib/models/game/game.dart
@@ -0,0 +1,38 @@
+import 'package:petitbac/utils/tools.dart';
+
+class Game {
+  bool isRunning = false;
+
+  Game({
+    this.isRunning = false,
+  });
+
+  factory Game.createNull() {
+    return Game();
+  }
+
+  factory Game.createNew() {
+    return Game(
+      isRunning: true,
+    );
+  }
+
+  void stop() {
+    isRunning = false;
+  }
+
+  @override
+  String toString() {
+    return 'Game(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'isRunning': isRunning,
+    };
+  }
+
+  void dump() {
+    printlog(toString());
+  }
+}
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
deleted file mode 100644
index c54e9a612d5727d8b77746b2e7ce0077dfb5b410..0000000000000000000000000000000000000000
--- a/lib/screens/home.dart
+++ /dev/null
@@ -1,306 +0,0 @@
-import 'dart:async';
-
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-import 'package:petitbac/provider/data.dart';
-import 'package:petitbac/utils/random_pick_category.dart';
-import 'package:petitbac/utils/random_pick_letter.dart';
-
-class Home extends StatelessWidget {
-  const Home({super.key});
-
-  static const String id = 'home';
-
-  static Timer? _timer;
-  static int _countdownStart = 10;
-
-  Future<void> startMiniGame(Data myProvider) async {
-    if (myProvider.countdown <= 0) {
-      pickCategory(myProvider);
-      pickLetter(myProvider);
-      startTimer(myProvider);
-    }
-  }
-
-  Future<void> startTimer(Data myProvider) async {
-    const oneSec = Duration(seconds: 1);
-    if (_timer != null) {
-      dispose();
-    }
-    _countdownStart = 10;
-    myProvider.updateCountdown(_countdownStart);
-    _timer = Timer.periodic(
-      oneSec,
-      (Timer timer) {
-        if (_countdownStart < 0) {
-          timer.cancel();
-        } else {
-          _countdownStart--;
-          myProvider.updateCountdown(_countdownStart);
-        }
-      },
-    );
-  }
-
-  void dispose() {
-    _timer?.cancel();
-  }
-
-  Future<void> pickCategory(Data myProvider) async {
-    myProvider.setSearchingCategory(true);
-    RandomPickCategory randomPickCategory;
-    int attempts = 0;
-    do {
-      randomPickCategory = RandomPickCategory();
-      await randomPickCategory.init();
-      if (!myProvider.isCategoryRecentlyPicked(randomPickCategory.category)) {
-        myProvider.updateCategory(randomPickCategory.category);
-        myProvider.setSearchingCategory(false);
-        break;
-      }
-      attempts++;
-    } while (attempts < 10);
-  }
-
-  Future<void> pickLetter(Data myProvider) async {
-    myProvider.setSearchingLetter(true);
-    RandomPickLetter randomPickLetter;
-    int attempts = 0;
-    do {
-      randomPickLetter = RandomPickLetter();
-      await randomPickLetter.init();
-      if (!myProvider.isLetterRecentlyPicked(randomPickLetter.letter)) {
-        myProvider.updateLetter(randomPickLetter.letter);
-        myProvider.setSearchingLetter(false);
-        break;
-      }
-      attempts++;
-    } while (attempts < 10);
-  }
-
-  Color darken(Color baseColor, {double amount = 0.2}) {
-    final hsl = HSLColor.fromColor(baseColor);
-    final hslDark = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0));
-    return hslDark.toColor();
-  }
-
-  Container mainLetterButtonContainer(
-    Data myProvider,
-    Color backgroundColor,
-    double borderWidth,
-  ) {
-    final Color borderColor = darken(backgroundColor);
-
-    return Container(
-      margin: EdgeInsets.all(borderWidth),
-      padding: EdgeInsets.all(borderWidth),
-      decoration: BoxDecoration(
-        color: backgroundColor,
-        borderRadius: BorderRadius.circular(borderWidth),
-        border: Border.all(
-          color: borderColor,
-          width: borderWidth,
-        ),
-      ),
-      child: TextButton(
-        onPressed: () => pickLetter(myProvider),
-        child: Text(
-          myProvider.letter == '' ? "🔀" : myProvider.letter,
-          style: const TextStyle(
-            fontSize: 40,
-            fontWeight: FontWeight.w600,
-            color: Colors.black,
-          ),
-        ),
-      ),
-    );
-  }
-
-  Container previousLetterBlockContainer(Data myProvider, int position, bool displayed) {
-    const double spacingWidth = 2;
-    const double borderWidth = 3;
-    Color backgroundColor = Colors.grey;
-    Color borderColor = darken(backgroundColor);
-    Color fontColor = Colors.black;
-
-    final String letter = myProvider.recentlyPickedLetter(position);
-
-    if (letter == '' || displayed == false) {
-      backgroundColor = Colors.white;
-      borderColor = Colors.white;
-      fontColor = Colors.white;
-    }
-
-    return Container(
-      margin: const EdgeInsets.all(spacingWidth),
-      padding: const EdgeInsets.all(spacingWidth),
-      decoration: BoxDecoration(
-        color: backgroundColor,
-        borderRadius: BorderRadius.circular(borderWidth),
-        border: Border.all(
-          color: borderColor,
-          width: borderWidth,
-        ),
-      ),
-      child: Text(
-        ' $letter ',
-        style: TextStyle(
-          fontSize: 35.0 - (7 * position),
-          fontWeight: FontWeight.w600,
-          color: fontColor,
-        ),
-      ),
-    );
-  }
-
-  Container _buildPickedLetterContainer(
-    Data myProvider,
-    Color backgroundColor,
-    double borderWidth,
-  ) {
-    const int previousLettersCountToShow = 3;
-
-    final List<Widget> cells = [];
-
-    // Add previous letters blocks
-    for (var i = 0; i < previousLettersCountToShow; i++) {
-      cells.add(TableCell(
-        verticalAlignment: TableCellVerticalAlignment.middle,
-        child: previousLetterBlockContainer(myProvider, previousLettersCountToShow - i, true),
-      ));
-    }
-
-    // Add current letter block
-    cells.add(TableCell(
-      verticalAlignment: TableCellVerticalAlignment.middle,
-      child: mainLetterButtonContainer(myProvider, backgroundColor, borderWidth),
-    ));
-
-    // Pad with empty blocks to keep symetrical layout
-    for (var i = 0; i < previousLettersCountToShow; i++) {
-      cells.add(TableCell(
-        verticalAlignment: TableCellVerticalAlignment.middle,
-        child: previousLetterBlockContainer(myProvider, i + 1, false),
-      ));
-    }
-
-    return Container(
-      margin: const EdgeInsets.all(2),
-      padding: const EdgeInsets.all(2),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(children: cells),
-        ],
-      ),
-    );
-  }
-
-  Widget _buildPickedCategoryContainer(
-    Data myProvider,
-    Color backgroundColor,
-    double borderWidth,
-  ) {
-    final Color borderColor = darken(backgroundColor);
-
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: [
-        Container(
-          margin: EdgeInsets.all(borderWidth),
-          padding: EdgeInsets.all(borderWidth),
-          decoration: BoxDecoration(
-            color: backgroundColor,
-            borderRadius: BorderRadius.circular(borderWidth),
-            border: Border.all(
-              color: borderColor,
-              width: borderWidth,
-            ),
-          ),
-          child: TextButton(
-            onPressed: () => pickCategory(myProvider),
-            child: Text(
-              myProvider.category == '' ? "🔀" : myProvider.category,
-              textAlign: TextAlign.center,
-              style: const TextStyle(
-                fontSize: 30,
-                fontWeight: FontWeight.w600,
-                color: Colors.black,
-              ),
-            ),
-          ),
-        ),
-      ],
-    );
-  }
-
-  Widget _buildMiniGameContainer(
-    Data myProvider,
-    Color backgroundColor,
-    double borderWidth,
-  ) {
-    final Color borderColor = darken(backgroundColor);
-
-    Color countDownColor = Colors.black;
-    if (myProvider.countdown == 0) {
-      countDownColor = Colors.red;
-    }
-
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: [
-        Container(
-          margin: EdgeInsets.all(borderWidth),
-          padding: EdgeInsets.all(borderWidth),
-          decoration: BoxDecoration(
-            color: backgroundColor,
-            borderRadius: BorderRadius.circular(borderWidth),
-            border: Border.all(
-              color: borderColor,
-              width: borderWidth,
-            ),
-          ),
-          child: TextButton(
-            onPressed: (myProvider.countdown >= 0) ? null : () => startMiniGame(myProvider),
-            child: Text(
-              (myProvider.countdown >= 0) ? myProvider.countdown.toString() : '🎲',
-              textAlign: TextAlign.center,
-              style: TextStyle(
-                fontSize: 50,
-                fontWeight: FontWeight.w600,
-                color: countDownColor,
-              ),
-            ),
-          ),
-        ),
-      ],
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final Data myProvider = Provider.of<Data>(context);
-    const double borderWidth = 8;
-
-    return Scaffold(
-      appBar: AppBar(
-        title: const Text('Petit bac'),
-      ),
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            _buildPickedLetterContainer(myProvider, Colors.orange, borderWidth),
-            const SizedBox(height: 5),
-            _buildMiniGameContainer(myProvider, Colors.blue, borderWidth),
-            const SizedBox(height: 5),
-            _buildPickedCategoryContainer(myProvider, Colors.green, borderWidth),
-          ],
-        ),
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/about_page.dart
new file mode 100644
index 0000000000000000000000000000000000000000..dd5c1767d113be9f7f3ef7c9b37c66e77b1650de
--- /dev/null
+++ b/lib/ui/screens/about_page.dart
@@ -0,0 +1,38 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:package_info_plus/package_info_plus.dart';
+
+import 'package:petitbac/ui/widgets/header_app.dart';
+
+class AboutPage extends StatelessWidget {
+  const AboutPage({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        const SizedBox(height: 8),
+        const AppHeader(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/ui/screens/game_page.dart b/lib/ui/screens/game_page.dart
new file mode 100644
index 0000000000000000000000000000000000000000..125ea9568037cb27654abf48c21263f653899b30
--- /dev/null
+++ b/lib/ui/screens/game_page.dart
@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+
+import 'package:petitbac/ui/widgets/mini_game.dart';
+import 'package:petitbac/ui/widgets/picked_category.dart';
+import 'package:petitbac/ui/widgets/picked_letter.dart';
+
+class GamePage extends StatelessWidget {
+  const GamePage({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    const double borderWidth = 8;
+
+    return const Column(
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: <Widget>[
+        PickedLetter(
+          backgroundColor: Colors.orange,
+          borderWidth: borderWidth,
+        ),
+        SizedBox(height: 5),
+        MiniGame(
+          backgroundColor: Colors.blue,
+          borderWidth: borderWidth,
+        ),
+        SizedBox(height: 5),
+        PickedCategory(
+          backgroundColor: Colors.green,
+          borderWidth: borderWidth,
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/settings_page.dart
new file mode 100644
index 0000000000000000000000000000000000000000..216fad9ec8786385142e21dc3aea08866e6b4d02
--- /dev/null
+++ b/lib/ui/screens/settings_page.dart
@@ -0,0 +1,23 @@
+import 'package:flutter/material.dart';
+
+import 'package:petitbac/ui/widgets/header_app.dart';
+import 'package:petitbac/ui/widgets/settings_form.dart';
+
+class SettingsPage extends StatelessWidget {
+  const SettingsPage({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return const Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        SizedBox(height: 8),
+        AppHeader(text: 'settings_title'),
+        SizedBox(height: 8),
+        SettingsForm(),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f5fc21f57e76940a071bdc1ad2abdc4369e2adff
--- /dev/null
+++ b/lib/ui/skeleton.dart
@@ -0,0 +1,45 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_swipe/flutter_swipe.dart';
+
+import 'package:petitbac/config/menu.dart';
+import 'package:petitbac/cubit/bottom_nav_cubit.dart';
+import 'package:petitbac/ui/widgets/app_bar.dart';
+import 'package:petitbac/ui/widgets/bottom_nav_bar.dart';
+
+class SkeletonScreen extends StatefulWidget {
+  const SkeletonScreen({super.key});
+
+  @override
+  State<SkeletonScreen> createState() => _SkeletonScreenState();
+}
+
+class _SkeletonScreenState extends State<SkeletonScreen> {
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      extendBodyBehindAppBar: false,
+      appBar: const StandardAppBar(),
+      body: Swiper(
+        itemCount: Menu.itemsCount,
+        itemBuilder: (BuildContext context, int index) {
+          return Menu.getPageWidget(index);
+        },
+        pagination: SwiperPagination(
+          margin: const EdgeInsets.all(0),
+          builder: SwiperCustomPagination(
+            builder: (BuildContext context, SwiperPluginConfig config) {
+              return BottomNavBar(swipeController: config.controller);
+            },
+          ),
+        ),
+        onIndexChanged: (newPageIndex) {
+          BlocProvider.of<BottomNavCubit>(context).updateIndex(newPageIndex);
+        },
+        outer: true,
+        loop: false,
+      ),
+      backgroundColor: Theme.of(context).colorScheme.background,
+    );
+  }
+}
diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart
new file mode 100644
index 0000000000000000000000000000000000000000..2e76fc6cb263f14b38699cc41299cebc31d50a03
--- /dev/null
+++ b/lib/ui/widgets/app_bar.dart
@@ -0,0 +1,20 @@
+import 'package:flutter/material.dart';
+
+import 'package:petitbac/ui/widgets/header_app.dart';
+
+class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
+  const StandardAppBar({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return AppBar(
+      title: const AppHeader(text: 'app_name'),
+      actions: const [
+        //
+      ],
+    );
+  }
+
+  @override
+  Size get preferredSize => const Size.fromHeight(50);
+}
diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d9f18eea081cb830b659f6d582be1e6255ef74c2
--- /dev/null
+++ b/lib/ui/widgets/bottom_nav_bar.dart
@@ -0,0 +1,40 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_swipe/flutter_swipe.dart';
+
+import 'package:petitbac/config/menu.dart';
+import 'package:petitbac/cubit/bottom_nav_cubit.dart';
+
+class BottomNavBar extends StatelessWidget {
+  const BottomNavBar({super.key, required this.swipeController});
+
+  final SwiperController swipeController;
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      margin: const EdgeInsets.all(0),
+      elevation: 4,
+      shadowColor: Theme.of(context).colorScheme.shadow,
+      color: Theme.of(context).colorScheme.surfaceVariant,
+      shape: const ContinuousRectangleBorder(),
+      child: BlocBuilder<BottomNavCubit, int>(
+        builder: (BuildContext context, int state) {
+          return BottomNavigationBar(
+            currentIndex: state,
+            onTap: (int index) {
+              context.read<BottomNavCubit>().updateIndex(index);
+              swipeController.move(index);
+            },
+            type: BottomNavigationBarType.fixed,
+            elevation: 0,
+            backgroundColor: Colors.transparent,
+            selectedItemColor: Theme.of(context).colorScheme.primary,
+            unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
+            items: Menu.getMenuItems(),
+          );
+        },
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/header_app.dart b/lib/ui/widgets/header_app.dart
new file mode 100644
index 0000000000000000000000000000000000000000..bf54b77375fbd0260f876f2885d0572b71715383
--- /dev/null
+++ b/lib/ui/widgets/header_app.dart
@@ -0,0 +1,23 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+class AppHeader extends StatelessWidget {
+  const AppHeader({super.key, required this.text});
+
+  final String text;
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        Text(
+          tr(text),
+          textAlign: TextAlign.start,
+          style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/widgets/mini_game.dart b/lib/ui/widgets/mini_game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3734c5f92597dc44c6ded3ab416437bf5c915a4c
--- /dev/null
+++ b/lib/ui/widgets/mini_game.dart
@@ -0,0 +1,107 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:petitbac/config/default_settings.dart';
+import 'package:petitbac/cubit/settings_cubit.dart';
+import 'package:provider/provider.dart';
+
+import 'package:petitbac/utils/color_extensions.dart';
+import 'package:petitbac/utils/game_utils.dart';
+import 'package:petitbac/provider/data.dart';
+
+class MiniGame extends StatelessWidget {
+  const MiniGame({
+    super.key,
+    required this.backgroundColor,
+    required this.borderWidth,
+  });
+
+  final Color backgroundColor;
+  final double borderWidth;
+
+  static Timer? _timer;
+  static int _countdownStart = 0;
+
+  void dispose() {
+    _timer?.cancel();
+  }
+
+  Future<void> startTimer(Data myProvider, int timerDuration) async {
+    const oneSec = Duration(seconds: 1);
+    if (_timer != null) {
+      dispose();
+    }
+    _countdownStart = timerDuration;
+    myProvider.updateCountdown(_countdownStart);
+    _timer = Timer.periodic(
+      oneSec,
+      (Timer timer) {
+        if (_countdownStart < 0) {
+          timer.cancel();
+        } else {
+          _countdownStart--;
+          myProvider.updateCountdown(_countdownStart);
+        }
+      },
+    );
+  }
+
+  Future<void> startMiniGame(Data myProvider, int timerDuration) async {
+    if (myProvider.countdown <= 0) {
+      GameUtils.pickCategory(myProvider);
+      GameUtils.pickLetter(myProvider);
+      startTimer(myProvider, timerDuration);
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final Data myProvider = Provider.of<Data>(context);
+
+    final Color borderColor = backgroundColor.darken();
+
+    Color countDownColor = Colors.black;
+    if (myProvider.countdown == 0) {
+      countDownColor = Colors.red;
+    }
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Container(
+          margin: EdgeInsets.all(borderWidth),
+          padding: EdgeInsets.all(borderWidth),
+          decoration: BoxDecoration(
+            color: backgroundColor,
+            borderRadius: BorderRadius.circular(borderWidth),
+            border: Border.all(
+              color: borderColor,
+              width: borderWidth,
+            ),
+          ),
+          child: BlocBuilder<SettingsCubit, SettingsState>(
+            builder: (context, settingsSate) {
+              return TextButton(
+                onPressed: (myProvider.countdown >= 0)
+                    ? null
+                    : () => startMiniGame(myProvider,
+                        settingsSate.timerValue ?? DefaultSettings.defaultTimerValue),
+                child: Text(
+                  (myProvider.countdown >= 0) ? myProvider.countdown.toString() : '🎲',
+                  textAlign: TextAlign.center,
+                  style: TextStyle(
+                    fontSize: 50,
+                    fontWeight: FontWeight.w600,
+                    color: countDownColor,
+                  ),
+                ),
+              );
+            },
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/widgets/picked_category.dart b/lib/ui/widgets/picked_category.dart
new file mode 100644
index 0000000000000000000000000000000000000000..de5781b4cf3cfa2ded6ad0064c6c35f1eb0ce93b
--- /dev/null
+++ b/lib/ui/widgets/picked_category.dart
@@ -0,0 +1,55 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import 'package:petitbac/utils/color_extensions.dart';
+import 'package:petitbac/utils/game_utils.dart';
+import 'package:petitbac/provider/data.dart';
+
+class PickedCategory extends StatelessWidget {
+  const PickedCategory({
+    super.key,
+    required this.backgroundColor,
+    required this.borderWidth,
+  });
+
+  final Color backgroundColor;
+  final double borderWidth;
+
+  @override
+  Widget build(BuildContext context) {
+    final Data myProvider = Provider.of<Data>(context);
+
+    final Color borderColor = backgroundColor.darken();
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Container(
+          margin: EdgeInsets.all(borderWidth),
+          padding: EdgeInsets.all(borderWidth),
+          decoration: BoxDecoration(
+            color: backgroundColor,
+            borderRadius: BorderRadius.circular(borderWidth),
+            border: Border.all(
+              color: borderColor,
+              width: borderWidth,
+            ),
+          ),
+          child: TextButton(
+            onPressed: () => GameUtils.pickCategory(myProvider),
+            child: Text(
+              myProvider.category == '' ? "🔀" : myProvider.category,
+              textAlign: TextAlign.center,
+              style: const TextStyle(
+                fontSize: 30,
+                fontWeight: FontWeight.w600,
+                color: Colors.black,
+              ),
+            ),
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/widgets/picked_letter.dart b/lib/ui/widgets/picked_letter.dart
new file mode 100644
index 0000000000000000000000000000000000000000..0c0e009301cbea545baf3762a1b5813990215c36
--- /dev/null
+++ b/lib/ui/widgets/picked_letter.dart
@@ -0,0 +1,101 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import 'package:petitbac/ui/widgets/previous_letter.dart';
+import 'package:petitbac/utils/color_extensions.dart';
+import 'package:petitbac/utils/game_utils.dart';
+import 'package:petitbac/provider/data.dart';
+
+class PickedLetter extends StatelessWidget {
+  const PickedLetter({
+    super.key,
+    required this.backgroundColor,
+    required this.borderWidth,
+  });
+
+  final Color backgroundColor;
+  final double borderWidth;
+
+  Container mainLetterButtonContainer(
+    Data myProvider,
+    Color backgroundColor,
+    double borderWidth,
+  ) {
+    final Color borderColor = backgroundColor.darken();
+
+    return Container(
+      margin: EdgeInsets.all(borderWidth),
+      padding: EdgeInsets.all(borderWidth),
+      decoration: BoxDecoration(
+        color: backgroundColor,
+        borderRadius: BorderRadius.circular(borderWidth),
+        border: Border.all(
+          color: borderColor,
+          width: borderWidth,
+        ),
+      ),
+      child: TextButton(
+        onPressed: () => GameUtils.pickLetter(myProvider),
+        child: Text(
+          myProvider.letter == '' ? "🔀" : myProvider.letter,
+          style: const TextStyle(
+            fontSize: 40,
+            fontWeight: FontWeight.w600,
+            color: Colors.black,
+          ),
+        ),
+      ),
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final Data myProvider = Provider.of<Data>(context);
+
+    const int previousLettersCountToShow = 3;
+
+    final List<Widget> cells = [];
+
+    // Add previous letters blocks
+    for (var i = 0; i < previousLettersCountToShow; i++) {
+      final int position = previousLettersCountToShow - i;
+      cells.add(TableCell(
+        verticalAlignment: TableCellVerticalAlignment.middle,
+        child: PreviousLetter(
+          letter: myProvider.recentlyPickedLetter(position),
+          position: position,
+          displayed: true,
+        ),
+      ));
+    }
+
+    // Add current letter block
+    cells.add(TableCell(
+      verticalAlignment: TableCellVerticalAlignment.middle,
+      child: mainLetterButtonContainer(myProvider, backgroundColor, borderWidth),
+    ));
+
+    // Pad with empty blocks to keep symetrical layout
+    for (var i = 0; i < previousLettersCountToShow; i++) {
+      cells.add(TableCell(
+        verticalAlignment: TableCellVerticalAlignment.middle,
+        child: PreviousLetter(
+          letter: myProvider.recentlyPickedLetter(i + 1),
+          position: i + 1,
+          displayed: false,
+        ),
+      ));
+    }
+
+    return Container(
+      margin: const EdgeInsets.all(2),
+      padding: const EdgeInsets.all(2),
+      child: Table(
+        defaultColumnWidth: const IntrinsicColumnWidth(),
+        children: [
+          TableRow(children: cells),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/previous_letter.dart b/lib/ui/widgets/previous_letter.dart
new file mode 100644
index 0000000000000000000000000000000000000000..558f27ccad159e8636aa5d1db189f65b33a9389f
--- /dev/null
+++ b/lib/ui/widgets/previous_letter.dart
@@ -0,0 +1,52 @@
+import 'package:flutter/material.dart';
+
+import 'package:petitbac/utils/color_extensions.dart';
+
+class PreviousLetter extends StatelessWidget {
+  const PreviousLetter({
+    super.key,
+    required this.letter,
+    required this.position,
+    required this.displayed,
+  });
+
+  final String letter;
+  final int position;
+  final bool displayed;
+
+  @override
+  Widget build(BuildContext context) {
+    const double spacingWidth = 2;
+    const double borderWidth = 3;
+    Color backgroundColor = Colors.grey;
+    Color borderColor = backgroundColor.darken();
+    Color fontColor = Colors.black;
+
+    if (letter == '' || displayed == false) {
+      backgroundColor = Theme.of(context).colorScheme.background;
+      borderColor = Theme.of(context).colorScheme.background;
+      fontColor = Theme.of(context).colorScheme.background;
+    }
+
+    return Container(
+      margin: const EdgeInsets.all(spacingWidth),
+      padding: const EdgeInsets.all(spacingWidth),
+      decoration: BoxDecoration(
+        color: backgroundColor,
+        borderRadius: BorderRadius.circular(borderWidth),
+        border: Border.all(
+          color: borderColor,
+          width: borderWidth,
+        ),
+      ),
+      child: Text(
+        ' $letter ',
+        style: TextStyle(
+          fontSize: 35.0 - (7 * position),
+          fontWeight: FontWeight.w600,
+          color: fontColor,
+        ),
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/settings_form.dart b/lib/ui/widgets/settings_form.dart
new file mode 100644
index 0000000000000000000000000000000000000000..431c9f1b6ae126d7a1699c0956a22216d31783e6
--- /dev/null
+++ b/lib/ui/widgets/settings_form.dart
@@ -0,0 +1,77 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/config/default_settings.dart';
+import 'package:petitbac/cubit/settings_cubit.dart';
+
+class SettingsForm extends StatefulWidget {
+  const SettingsForm({super.key});
+
+  @override
+  State<SettingsForm> createState() => _SettingsFormState();
+}
+
+class _SettingsFormState extends State<SettingsForm> {
+  int timerValue = DefaultSettings.defaultTimerValue;
+
+  List<bool> _selectedTimerValue = [];
+
+  @override
+  void dispose() {
+    super.dispose();
+  }
+
+  @override
+  void didChangeDependencies() {
+    SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
+
+    timerValue = settings.getTimerValue();
+
+    _selectedTimerValue =
+        DefaultSettings.allowedTimerValues.map((e) => (e == timerValue)).toList();
+
+    super.didChangeDependencies();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    void saveSettings() {
+      BlocProvider.of<SettingsCubit>(context).setValues(
+        timerValue: timerValue,
+      );
+    }
+
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        // Timer value
+        Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            const Text('settings_label_timer_value').tr(),
+            ToggleButtons(
+              onPressed: (int index) {
+                setState(() {
+                  timerValue = DefaultSettings.allowedTimerValues[index];
+                  for (int i = 0; i < _selectedTimerValue.length; i++) {
+                    _selectedTimerValue[i] = i == index;
+                  }
+                });
+                saveSettings();
+              },
+              borderRadius: const BorderRadius.all(Radius.circular(8)),
+              constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
+              isSelected: _selectedTimerValue,
+              children:
+                  DefaultSettings.allowedTimerValues.map((e) => Text(e.toString())).toList(),
+            ),
+          ],
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/utils/color_extensions.dart b/lib/utils/color_extensions.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4e55e338f0d3ed98b233d1ef887b7b3e17e29d97
--- /dev/null
+++ b/lib/utils/color_extensions.dart
@@ -0,0 +1,33 @@
+import 'dart:ui';
+
+extension ColorExtension on Color {
+  Color darken([int percent = 40]) {
+    assert(1 <= percent && percent <= 100);
+    final value = 1 - percent / 100;
+    return Color.fromARGB(
+      alpha,
+      (red * value).round(),
+      (green * value).round(),
+      (blue * value).round(),
+    );
+  }
+
+  Color lighten([int percent = 40]) {
+    assert(1 <= percent && percent <= 100);
+    final value = percent / 100;
+    return Color.fromARGB(
+      alpha,
+      (red + ((255 - red) * value)).round(),
+      (green + ((255 - green) * value)).round(),
+      (blue + ((255 - blue) * value)).round(),
+    );
+  }
+
+  Color avg(Color other) {
+    final red = (this.red + other.red) ~/ 2;
+    final green = (this.green + other.green) ~/ 2;
+    final blue = (this.blue + other.blue) ~/ 2;
+    final alpha = (this.alpha + other.alpha) ~/ 2;
+    return Color.fromARGB(alpha, red, green, blue);
+  }
+}
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e206a93dfcfe878f9a96c1291f824b2824e6c3ac
--- /dev/null
+++ b/lib/utils/game_utils.dart
@@ -0,0 +1,37 @@
+import 'package:petitbac/provider/data.dart';
+import 'package:petitbac/utils/random_pick_category.dart';
+import 'package:petitbac/utils/random_pick_letter.dart';
+
+class GameUtils {
+  static Future<void> pickLetter(Data myProvider) async {
+    myProvider.setSearchingLetter(true);
+    RandomPickLetter randomPickLetter;
+    int attempts = 0;
+    do {
+      randomPickLetter = RandomPickLetter();
+      await randomPickLetter.init();
+      if (!myProvider.isLetterRecentlyPicked(randomPickLetter.letter)) {
+        myProvider.updateLetter(randomPickLetter.letter);
+        myProvider.setSearchingLetter(false);
+        break;
+      }
+      attempts++;
+    } while (attempts < 10);
+  }
+
+  static Future<void> pickCategory(Data myProvider) async {
+    myProvider.setSearchingCategory(true);
+    RandomPickCategory randomPickCategory;
+    int attempts = 0;
+    do {
+      randomPickCategory = RandomPickCategory();
+      await randomPickCategory.init();
+      if (!myProvider.isCategoryRecentlyPicked(randomPickCategory.category)) {
+        myProvider.updateCategory(randomPickCategory.category);
+        myProvider.setSearchingCategory(false);
+        break;
+      }
+      attempts++;
+    } while (attempts < 10);
+  }
+}
diff --git a/pubspec.lock b/pubspec.lock
index b15ebfbb8fc4b11d61a5733db2b95e116d18c681..53bc85dec4bae56188e56f74edcd0c91e60c1f18 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,6 +1,30 @@
 # Generated by pub
 # See https://dart.dev/tools/pub/glossary#lockfile
 packages:
+  args:
+    dependency: transitive
+    description:
+      name: args
+      sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.4.2"
+  async:
+    dependency: transitive
+    description:
+      name: async
+      sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.11.0"
+  bloc:
+    dependency: transitive
+    description:
+      name: bloc
+      sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e
+      url: "https://pub.dev"
+    source: hosted
+    version: "8.1.3"
   characters:
     dependency: transitive
     description:
@@ -9,6 +33,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.3.0"
+  clock:
+    dependency: transitive
+    description:
+      name: clock
+      sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.1"
   collection:
     dependency: transitive
     description:
@@ -17,11 +49,67 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.18.0"
+  crypto:
+    dependency: transitive
+    description:
+      name: crypto
+      sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.3"
+  easy_localization:
+    dependency: "direct main"
+    description:
+      name: easy_localization
+      sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.5"
+  easy_logger:
+    dependency: transitive
+    description:
+      name: easy_logger
+      sha256: c764a6e024846f33405a2342caf91c62e357c24b02c04dbc712ef232bf30ffb7
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.0.2"
+  equatable:
+    dependency: "direct main"
+    description:
+      name: equatable
+      sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.5"
+  ffi:
+    dependency: transitive
+    description:
+      name: ffi
+      sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.2"
+  file:
+    dependency: transitive
+    description:
+      name: file
+      sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
+      url: "https://pub.dev"
+    source: hosted
+    version: "7.0.0"
   flutter:
     dependency: "direct main"
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_bloc:
+    dependency: "direct main"
+    description:
+      name: flutter_bloc
+      sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1"
+      url: "https://pub.dev"
+    source: hosted
+    version: "8.1.4"
   flutter_lints:
     dependency: "direct dev"
     description:
@@ -30,6 +118,64 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "3.0.1"
+  flutter_localizations:
+    dependency: transitive
+    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
+    source: sdk
+    version: "0.0.0"
+  hive:
+    dependency: "direct main"
+    description:
+      name: hive
+      sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.3"
+  http:
+    dependency: transitive
+    description:
+      name: http
+      sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.0"
+  http_parser:
+    dependency: transitive
+    description:
+      name: http_parser
+      sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
+      url: "https://pub.dev"
+    source: hosted
+    version: "4.0.2"
+  hydrated_bloc:
+    dependency: "direct main"
+    description:
+      name: hydrated_bloc
+      sha256: "00a2099680162e74b5a836b8a7f446e478520a9cae9f6032e028ad8129f4432d"
+      url: "https://pub.dev"
+    source: hosted
+    version: "9.1.4"
+  intl:
+    dependency: transitive
+    description:
+      name: intl
+      sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.18.1"
   lints:
     dependency: transitive
     description:
@@ -62,6 +208,94 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.0.0"
+  package_info_plus:
+    dependency: "direct main"
+    description:
+      name: package_info_plus
+      sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79"
+      url: "https://pub.dev"
+    source: hosted
+    version: "5.0.1"
+  package_info_plus_platform_interface:
+    dependency: transitive
+    description:
+      name: package_info_plus_platform_interface
+      sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.1"
+  path:
+    dependency: "direct main"
+    description:
+      name: path
+      sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.9.0"
+  path_provider:
+    dependency: "direct main"
+    description:
+      name: path_provider
+      sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.2"
+  path_provider_android:
+    dependency: transitive
+    description:
+      name: path_provider_android
+      sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.2"
+  path_provider_foundation:
+    dependency: transitive
+    description:
+      name: path_provider_foundation
+      sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.3.2"
+  path_provider_linux:
+    dependency: transitive
+    description:
+      name: path_provider_linux
+      sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.1"
+  path_provider_platform_interface:
+    dependency: transitive
+    description:
+      name: path_provider_platform_interface
+      sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.2"
+  path_provider_windows:
+    dependency: transitive
+    description:
+      name: path_provider_windows
+      sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.1"
+  platform:
+    dependency: transitive
+    description:
+      name: platform
+      sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.1.4"
+  plugin_platform_interface:
+    dependency: transitive
+    description:
+      name: plugin_platform_interface
+      sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.8"
   provider:
     dependency: "direct main"
     description:
@@ -70,11 +304,115 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "6.1.2"
+  shared_preferences:
+    dependency: transitive
+    description:
+      name: shared_preferences
+      sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.2"
+  shared_preferences_android:
+    dependency: transitive
+    description:
+      name: shared_preferences_android
+      sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.1"
+  shared_preferences_foundation:
+    dependency: transitive
+    description:
+      name: shared_preferences_foundation
+      sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.3.5"
+  shared_preferences_linux:
+    dependency: transitive
+    description:
+      name: shared_preferences_linux
+      sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.3.2"
+  shared_preferences_platform_interface:
+    dependency: transitive
+    description:
+      name: shared_preferences_platform_interface
+      sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.3.2"
+  shared_preferences_web:
+    dependency: transitive
+    description:
+      name: shared_preferences_web
+      sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.2"
+  shared_preferences_windows:
+    dependency: transitive
+    description:
+      name: shared_preferences_windows
+      sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.3.2"
   sky_engine:
     dependency: transitive
     description: flutter
     source: sdk
     version: "0.0.99"
+  source_span:
+    dependency: transitive
+    description:
+      name: source_span
+      sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.10.0"
+  string_scanner:
+    dependency: transitive
+    description:
+      name: string_scanner
+      sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.0"
+  synchronized:
+    dependency: transitive
+    description:
+      name: synchronized
+      sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.1.0+1"
+  term_glyph:
+    dependency: transitive
+    description:
+      name: term_glyph
+      sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.1"
+  typed_data:
+    dependency: transitive
+    description:
+      name: typed_data
+      sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.3.2"
+  unicons:
+    dependency: "direct main"
+    description:
+      name: unicons
+      sha256: dbfcf93ff4d4ea19b324113857e358e4882115ab85db04417a4ba1c72b17a670
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.1"
   vector_math:
     dependency: transitive
     description:
@@ -83,6 +421,30 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.1.4"
+  web:
+    dependency: transitive
+    description:
+      name: web
+      sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.4.2"
+  win32:
+    dependency: transitive
+    description:
+      name: win32
+      sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480"
+      url: "https://pub.dev"
+    source: hosted
+    version: "5.3.0"
+  xdg_directories:
+    dependency: transitive
+    description:
+      name: xdg_directories
+      sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.4"
 sdks:
-  dart: ">=3.2.0-0 <4.0.0"
-  flutter: ">=1.16.0"
+  dart: ">=3.3.0 <4.0.0"
+  flutter: ">=3.16.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index f8880cc164add0ffd02269a5b56e37c92b9b988b..540b2ae38963714d9183c5d11d3eff88b5c64c8b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,7 +1,8 @@
 name: petitbac
 description: A PetitBac game application.
+
 publish_to: 'none'
-version: 1.2.28+34
+version: 1.2.29+35
 
 environment:
   sdk: '^3.0.0'
@@ -9,12 +10,37 @@ environment:
 dependencies:
   flutter:
     sdk: flutter
+
+  easy_localization: ^3.0.1
+  equatable: ^2.0.5
+  flutter_bloc: ^8.1.1
+  flutter_swipe: ^1.0.1
+  hive: ^2.2.3
+  hydrated_bloc: ^9.0.0
+  package_info_plus: ^5.0.1
+  path: ^1.9.0
+  path_provider: ^2.0.11
   provider: ^6.0.5
+  unicons: ^2.1.1
 
 dev_dependencies:
   flutter_lints: ^3.0.1
 
 flutter:
-  uses-material-design: true
+  uses-material-design: false
   assets:
     - assets/files/
+    - assets/translations/
+
+  fonts:
+    - family: Nunito
+      fonts:
+        - asset: assets/fonts/Nunito-Bold.ttf
+          weight: 700
+        - asset: assets/fonts/Nunito-Medium.ttf
+          weight: 500
+        - asset: assets/fonts/Nunito-Regular.ttf
+          weight: 400
+        - asset: assets/fonts/Nunito-Light.ttf
+          weight: 300
+