diff --git a/android/gradle.properties b/android/gradle.properties
index 777ac2de0980e935649cf32bd85097eaf789185a..cd2d833ca96b3d1ada4a39df51dc5f5ee67665b7 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.16
-app.versionCode=16
+app.versionName=0.0.17
+app.versionCode=17
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..edfb95a30bace7bf5b2c37e3946e068ccbea735e
--- /dev/null
+++ b/assets/translations/en.json
@@ -0,0 +1,16 @@
+{
+  "app_name": "Solitaire",
+
+  "long_press_to_quit": "Long press to quit game...",
+
+  "bottom_nav_home": "Game",
+  "bottom_nav_settings": "Settings",
+  "bottom_nav_about": "About",
+
+  "settings_title": "Settings",
+  "settings_label_theme": "Theme mode",
+
+  "about_title": "About",
+  "about_content": "Solitaire.",
+  "about_version": "Version: {version}"
+}
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
new file mode 100644
index 0000000000000000000000000000000000000000..a4e231eb9e29deab5b2082bfcd0e981020be4b9e
--- /dev/null
+++ b/assets/translations/fr.json
@@ -0,0 +1,16 @@
+{
+  "app_name": "Solitaire",
+
+  "long_press_to_quit": "Appuyer longtemps pour quitter le jeu...",
+
+  "bottom_nav_home": "Jeu",
+  "bottom_nav_settings": "Réglages",
+  "bottom_nav_about": "Infos",
+
+  "settings_title": "Réglages",
+  "settings_label_theme": "Thème de couleurs",
+
+  "about_title": "Informations",
+  "about_content": "Solitaire.",
+  "about_version": "Version : {version}"
+}
diff --git a/fastlane/metadata/android/en-US/changelogs/17.txt b/fastlane/metadata/android/en-US/changelogs/17.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6b884ec4ea3e942b988f5815114a1c3ab59810b8
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/17.txt
@@ -0,0 +1 @@
+Improve game conception/architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/17.txt b/fastlane/metadata/android/fr-FR/changelogs/17.txt
new file mode 100644
index 0000000000000000000000000000000000000000..386b2cdcc090f19264599ba6dc6b215246489bce
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/17.txt
@@ -0,0 +1 @@
+Amélioration de la conception/architecture du jeu.
diff --git a/lib/config/menu.dart b/lib/config/menu.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ca5d227fee343cb63c211fd9904fd9d1a48477b1
--- /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:solitaire/ui/screens/about_page.dart';
+import 'package:solitaire/ui/screens/game_page.dart';
+import 'package:solitaire/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..8f04dffa9682eb52139e44fcb2ab9a4d75a613a8
--- /dev/null
+++ b/lib/cubit/bottom_nav_cubit.dart
@@ -0,0 +1,31 @@
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:solitaire/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/theme_cubit.dart b/lib/cubit/theme_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b793e895dbb0c672d451cd403e0036c3d9ac9b42
--- /dev/null
+++ b/lib/cubit/theme_cubit.dart
@@ -0,0 +1,31 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+part 'theme_state.dart';
+
+class ThemeCubit extends HydratedCubit<ThemeModeState> {
+  ThemeCubit() : super(const ThemeModeState());
+
+  void getTheme(ThemeModeState state) {
+    emit(state);
+  }
+
+  @override
+  ThemeModeState? fromJson(Map<String, dynamic> json) {
+    switch (json['themeMode']) {
+      case 'ThemeMode.dark':
+        return const ThemeModeState(themeMode: ThemeMode.dark);
+      case 'ThemeMode.light':
+        return const ThemeModeState(themeMode: ThemeMode.light);
+      case 'ThemeMode.system':
+      default:
+        return const ThemeModeState(themeMode: ThemeMode.system);
+    }
+  }
+
+  @override
+  Map<String, String>? toJson(ThemeModeState state) {
+    return <String, String>{'themeMode': state.themeMode.toString()};
+  }
+}
diff --git a/lib/cubit/theme_state.dart b/lib/cubit/theme_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e479a50f12fe72a35a1fd1722ff72afbb692a136
--- /dev/null
+++ b/lib/cubit/theme_state.dart
@@ -0,0 +1,15 @@
+part of 'theme_cubit.dart';
+
+@immutable
+class ThemeModeState extends Equatable {
+  const ThemeModeState({
+    this.themeMode,
+  });
+
+  final ThemeMode? themeMode;
+
+  @override
+  List<Object?> get props => <Object?>[
+        themeMode,
+      ];
+}
diff --git a/lib/entities/tile.dart b/lib/entities/tile.dart
index c9d585dbd766be04de40247b75bfd1e903c786a3..5f88b97058b643f3b357bd60efdfc7bca2fe0e26 100644
--- a/lib/entities/tile.dart
+++ b/lib/entities/tile.dart
@@ -1,6 +1,6 @@
 import 'package:flutter/material.dart';
-import 'package:solitaire_game/provider/data.dart';
-import 'package:solitaire_game/utils/game_utils.dart';
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/utils/game_utils.dart';
 
 class Tile {
   int currentRow;
diff --git a/lib/layout/board.dart b/lib/layout/board.dart
deleted file mode 100644
index d00a12d842b5713a69249731d9e9e367d325e8c4..0000000000000000000000000000000000000000
--- a/lib/layout/board.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:solitaire_game/entities/tile.dart';
-import 'package:solitaire_game/provider/data.dart';
-
-class Board {
-  static Widget buildGameBoard(Data myProvider) {
-    return Column(
-      children: [
-        buildGameTileset(myProvider),
-      ],
-    );
-  }
-
-  static Table buildGameTileset(Data myProvider) {
-    List<List<Tile?>> board = myProvider.board;
-
-    Widget boardTileWithoutHole = Image(
-      image: AssetImage('assets/skins/${myProvider.parameterSkin}_board.png'),
-      width: myProvider.tileSize,
-      height: myProvider.tileSize,
-      fit: BoxFit.fill,
-    );
-
-    return Table(
-      defaultColumnWidth: const IntrinsicColumnWidth(),
-      children: [
-        for (int row = 0; row < board.length; row++)
-          TableRow(
-            children: [
-              for (int col = 0; col < board[row].length; col++)
-                TableCell(
-                  child: board[row][col] != null
-                      ? (board[row][col]?.render(myProvider) ?? Container())
-                      : boardTileWithoutHole,
-                ),
-            ],
-          ),
-      ],
-    );
-  }
-}
diff --git a/lib/layout/game.dart b/lib/layout/game.dart
deleted file mode 100644
index 69d533d52639dca309a4fe61efcc57bdf33ee457..0000000000000000000000000000000000000000
--- a/lib/layout/game.dart
+++ /dev/null
@@ -1,113 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:solitaire_game/layout/board.dart';
-import 'package:solitaire_game/provider/data.dart';
-import 'package:solitaire_game/utils/game_utils.dart';
-
-class Game {
-  static Widget buildGameWidget(Data myProvider) {
-    final bool gameIsFinished = myProvider.gameIsFinished;
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: [
-        const SizedBox(height: 8),
-        Game.buildTopIndicatorWidget(myProvider),
-        const SizedBox(height: 2),
-        Expanded(
-          child: Board.buildGameBoard(myProvider),
-        ),
-        const SizedBox(height: 2),
-        Container(
-          child: gameIsFinished
-              ? Game.buildEndGameMessage(myProvider)
-              : const SizedBox(height: 2),
-        ),
-      ],
-    );
-  }
-
-  static Widget buildTopIndicatorWidget(Data myProvider) {
-    final int allowedMovesCount = myProvider.allowedMovesCount;
-
-    return Table(
-      children: [
-        TableRow(
-          children: [
-            Column(
-              children: [
-                Text(
-                  '♟️ ${myProvider.remainingPegsCount}',
-                  style: const TextStyle(
-                    fontSize: 40,
-                    fontWeight: FontWeight.w600,
-                    color: Colors.black,
-                  ),
-                ),
-              ],
-            ),
-            Column(
-              children: [
-                Text(
-                  allowedMovesCount.toString(),
-                  style: const TextStyle(
-                    fontSize: 20,
-                    fontWeight: FontWeight.w600,
-                    color: Colors.green,
-                  ),
-                ),
-              ],
-            ),
-          ],
-        ),
-      ],
-    );
-  }
-
-  static TextButton buildQuitGameButton(Data myProvider) {
-    return TextButton(
-      child: const Image(
-        image: AssetImage('assets/icons/button_back.png'),
-        fit: BoxFit.fill,
-      ),
-      onPressed: () => GameUtils.quitAndDeleteCurrentGame(myProvider),
-    );
-  }
-
-  static Container buildEndGameMessage(Data myProvider) {
-    String decorationImageAssetName = '';
-    if (myProvider.gameWon()) {
-      decorationImageAssetName = 'assets/icons/game_win.png';
-    } else {
-      decorationImageAssetName = 'assets/icons/placeholder.png';
-    }
-
-    final Image decorationImage = Image(
-      image: AssetImage(decorationImageAssetName),
-      fit: BoxFit.fill,
-    );
-
-    return Container(
-      margin: const EdgeInsets.all(2),
-      padding: const EdgeInsets.all(2),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              Column(
-                children: [decorationImage],
-              ),
-              Column(
-                children: [buildQuitGameButton(myProvider)],
-              ),
-              Column(
-                children: [decorationImage],
-              ),
-            ],
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/layout/parameters.dart b/lib/layout/parameters.dart
deleted file mode 100644
index f2edf749b878980c9b953f55c87ebf320e2592f7..0000000000000000000000000000000000000000
--- a/lib/layout/parameters.dart
+++ /dev/null
@@ -1,182 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:solitaire_game/provider/data.dart';
-import 'package:solitaire_game/utils/game_utils.dart';
-
-class Parameters {
-  static double separatorHeight = 2.0;
-  static double blockMargin = 3.0;
-  static double blockPadding = 2.0;
-  static Color buttonBackgroundColor = Colors.white;
-  static Color buttonBorderColorActive = Colors.blue;
-  static Color buttonBorderColorInactive = Colors.white;
-  static double buttonBorderWidth = 10.0;
-  static double buttonBorderRadius = 8.0;
-  static double buttonPadding = 0.0;
-  static double buttonMargin = 0.0;
-
-  static Widget buildParametersSelector(Data myProvider) {
-    List<Widget> lines = [];
-
-    List parameters = myProvider.availableParameters;
-    for (int index = 0; index < parameters.length; index++) {
-      lines.add(buildParameterSelector(myProvider, parameters[index]));
-      lines.add(SizedBox(height: separatorHeight));
-    }
-
-    myProvider.loadCurrentSavedState();
-    Widget buttonsBlock = myProvider.hasCurrentSavedState()
-        ? buildResumeGameButton(myProvider)
-        : buildStartNewGameButton(myProvider);
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: [
-        SizedBox(height: separatorHeight),
-        Expanded(
-          child: Column(
-            mainAxisSize: MainAxisSize.min,
-            mainAxisAlignment: MainAxisAlignment.center,
-            children: lines,
-          ),
-        ),
-        SizedBox(height: separatorHeight),
-        Container(
-          child: buttonsBlock,
-        ),
-      ],
-    );
-  }
-
-  static Image buildImageWidget(String imageAssetCode) {
-    return Image(
-      image: AssetImage('assets/icons/$imageAssetCode.png'),
-      fit: BoxFit.fill,
-    );
-  }
-
-  static Container buildImageContainerWidget(String imageAssetCode) {
-    return Container(
-      child: buildImageWidget(imageAssetCode),
-    );
-  }
-
-  static Column buildDecorationImageWidget() {
-    return Column(
-      children: [
-        TextButton(
-          child: buildImageContainerWidget('placeholder'),
-          onPressed: () {},
-        ),
-      ],
-    );
-  }
-
-  static Container buildStartNewGameButton(Data myProvider) {
-    return Container(
-      margin: EdgeInsets.all(blockMargin),
-      padding: EdgeInsets.all(blockPadding),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              buildDecorationImageWidget(),
-              Column(
-                children: [
-                  TextButton(
-                    child: buildImageContainerWidget('button_start'),
-                    onPressed: () => GameUtils.startNewGame(myProvider),
-                  ),
-                ],
-              ),
-              buildDecorationImageWidget(),
-            ],
-          ),
-        ],
-      ),
-    );
-  }
-
-  static Container buildResumeGameButton(Data myProvider) {
-    return Container(
-      margin: EdgeInsets.all(blockMargin),
-      padding: EdgeInsets.all(blockPadding),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              Column(
-                children: [
-                  TextButton(
-                    child: buildImageContainerWidget('button_delete_saved_game'),
-                    onPressed: () => GameUtils.deleteSavedGame(myProvider),
-                  ),
-                ],
-              ),
-              Column(
-                children: [
-                  TextButton(
-                    child: buildImageContainerWidget('button_resume_game'),
-                    onPressed: () => GameUtils.resumeSavedGame(myProvider),
-                  ),
-                ],
-              ),
-              buildDecorationImageWidget(),
-            ],
-          ),
-        ],
-      ),
-    );
-  }
-
-  static Widget buildParameterSelector(Data myProvider, String parameterCode) {
-    List availableValues = myProvider.getParameterAvailableValues(parameterCode);
-
-    if (availableValues.length == 1) {
-      return const SizedBox(height: 0.0);
-    }
-
-    return Table(
-      defaultColumnWidth: const IntrinsicColumnWidth(),
-      children: [
-        TableRow(
-          children: [
-            for (int index = 0; index < availableValues.length; index++)
-              Column(
-                children: [
-                  _buildParameterButton(myProvider, parameterCode, availableValues[index])
-                ],
-              ),
-          ],
-        ),
-      ],
-    );
-  }
-
-  static Widget _buildParameterButton(
-      Data myProvider, String parameterCode, String parameterValue) {
-    String currentValue = myProvider.getParameterValue(parameterCode).toString();
-
-    bool isActive = (parameterValue == currentValue);
-    String imageAsset = '${parameterCode}_$parameterValue';
-
-    return TextButton(
-      child: Container(
-        margin: EdgeInsets.all(buttonMargin),
-        padding: EdgeInsets.all(buttonPadding),
-        decoration: BoxDecoration(
-          color: buttonBackgroundColor,
-          borderRadius: BorderRadius.circular(buttonBorderRadius),
-          border: Border.all(
-            color: isActive ? buttonBorderColorActive : buttonBorderColorInactive,
-            width: buttonBorderWidth,
-          ),
-        ),
-        child: buildImageWidget(imageAsset),
-      ),
-      onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue),
-    );
-  }
-}
diff --git a/lib/main.dart b/lib/main.dart
index 1967ce48b7b68fc784b45da9f4ee9e121c7acdd9..e84151f467ffe84165623e79580b02b340e2aa35 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/services.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:overlay_support/overlay_support.dart';
-import 'package:solitaire_game/provider/data.dart';
-import 'package:solitaire_game/screens/home.dart';
 
-void main() {
+import 'package:solitaire/config/theme.dart';
+import 'package:solitaire/cubit/bottom_nav_cubit.dart';
+import 'package:solitaire/cubit/theme_cubit.dart';
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/ui/skeleton.dart';
+
+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,23 +44,39 @@ class MyApp extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return ChangeNotifierProvider(
-      create: (BuildContext context) => Data(),
-      child: Consumer<Data>(builder: (context, data, child) {
-        return OverlaySupport(
-          child: MaterialApp(
-            debugShowCheckedModeBanner: false,
-            theme: ThemeData(
-              primaryColor: Colors.blue,
-              visualDensity: VisualDensity.adaptivePlatformDensity,
+    return MultiBlocProvider(
+      providers: [
+        BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
+        BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()),
+      ],
+      child: BlocBuilder<ThemeCubit, ThemeModeState>(
+        builder: (BuildContext context, ThemeModeState state) {
+          return ChangeNotifierProvider(
+            create: (BuildContext context) => Data(),
+            child: Consumer<Data>(
+              builder: (context, data, child) {
+                return OverlaySupport(
+                  child: MaterialApp(
+                    title: 'Solitaire',
+                    home: const SkeletonScreen(),
+
+                    // Theme stuff
+                    theme: lightTheme,
+                    darkTheme: darkTheme,
+                    themeMode: state.themeMode,
+
+                    // Localization stuff
+                    localizationsDelegates: context.localizationDelegates,
+                    supportedLocales: context.supportedLocales,
+                    locale: context.locale,
+                    debugShowCheckedModeBanner: false,
+                  ),
+                );
+              },
             ),
-            home: const Home(),
-            routes: {
-              Home.id: (context) => const Home(),
-            },
-          ),
-        );
-      }),
+          );
+        },
+      ),
     );
   }
 }
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
index 699b5c5f0cde537a8a9f39334b3e1758dcb1050f..9c18e794f5d5eb7045d31de5a7a7c3b26582a444 100644
--- a/lib/provider/data.dart
+++ b/lib/provider/data.dart
@@ -2,8 +2,10 @@ import 'dart:convert';
 
 import 'package:flutter/foundation.dart';
 import 'package:shared_preferences/shared_preferences.dart';
-import 'package:solitaire_game/entities/tile.dart';
-import 'package:solitaire_game/utils/game_utils.dart';
+import 'package:solitaire/entities/tile.dart';
+import 'package:solitaire/utils/game_utils.dart';
+
+typedef Board = List<List<Tile?>>;
 
 class Data extends ChangeNotifier {
   // Configuration available values
@@ -30,7 +32,7 @@ class Data extends ChangeNotifier {
   bool _assetsPreloaded = false;
   bool _gameIsRunning = false;
   bool _gameIsFinished = false;
-  List<List<Tile?>> _board = [];
+  Board _board = [];
   int _boardSize = 0;
   double _tileSize = 0;
   int _movesCount = 0;
@@ -145,7 +147,7 @@ class Data extends ChangeNotifier {
 
   Map<String, dynamic> getCurrentSavedState() {
     if (_currentState != '') {
-      Map<String, dynamic> savedState = json.decode(_currentState);
+      final Map<String, dynamic> savedState = json.decode(_currentState);
       if (savedState.isNotEmpty) {
         return savedState;
       }
@@ -168,8 +170,8 @@ class Data extends ChangeNotifier {
     _boardSize = boardSize;
   }
 
-  List<List<Tile?>> get board => _board;
-  void updateBoard(List<List<Tile?>> board) {
+  Board get board => _board;
+  void updateBoard(Board board) {
     _board = board;
     updateBoardSize(board.length);
     updateRemainingPegsCount(GameUtils.countRemainingPegs(this));
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
deleted file mode 100644
index 62b3a0ff7abf625c6460087864f9f7430dfabeff..0000000000000000000000000000000000000000
--- a/lib/screens/home.dart
+++ /dev/null
@@ -1,117 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'package:overlay_support/overlay_support.dart';
-import 'package:solitaire_game/layout/game.dart';
-import 'package:solitaire_game/layout/parameters.dart';
-import 'package:solitaire_game/provider/data.dart';
-import 'package:solitaire_game/utils/game_utils.dart';
-
-class Home extends StatefulWidget {
-  const Home({super.key});
-
-  static const String id = 'home';
-
-  @override
-  HomeState createState() => HomeState();
-}
-
-class HomeState extends State<Home> {
-  @override
-  void initState() {
-    super.initState();
-
-    Data myProvider = Provider.of<Data>(context, listen: false);
-    myProvider.initParametersValues();
-    myProvider.loadCurrentSavedState();
-  }
-
-  List<String> getImagesAssets(Data myProvider) {
-    final List<String> assets = [];
-
-    final List<String> gameImages = [
-      'button_back',
-      'button_delete_saved_game',
-      'button_resume_game',
-      'button_start',
-      'game_fail',
-      'game_win',
-      'placeholder',
-    ];
-    for (String layout in myProvider.availableLayoutValues) {
-      gameImages.add('layout_$layout');
-    }
-    for (String skin in myProvider.availableSkinValues) {
-      gameImages.add('skin_$skin');
-    }
-
-    for (String image in gameImages) {
-      assets.add('${'assets/icons/$image'}.png');
-    }
-
-    const List<String> skinImages = [
-      'board',
-      'hole',
-      'peg',
-    ];
-
-    for (String skin in myProvider.availableSkinValues) {
-      for (String image in skinImages) {
-        assets.add('${'${'assets/skins/$skin'}_$image'}.png');
-      }
-    }
-
-    return assets;
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    Data myProvider = Provider.of<Data>(context);
-
-    if (!myProvider.assetsPreloaded) {
-      List<String> assets = getImagesAssets(myProvider);
-      for (String asset in assets) {
-        precacheImage(AssetImage(asset), context);
-      }
-      myProvider.updateAssetsPreloaded(true);
-    }
-
-    myProvider.updateTileSize((MediaQuery.of(context).size.width - 40) / myProvider.boardSize);
-
-    List<Widget> menuActions = [];
-
-    if (myProvider.gameIsRunning) {
-      menuActions = [
-        TextButton(
-          child: Container(
-            decoration: BoxDecoration(
-              borderRadius: BorderRadius.circular(4),
-              border: Border.all(
-                color: Colors.blue,
-                width: 4,
-              ),
-            ),
-            child: const Image(
-              image: AssetImage('assets/icons/button_back.png'),
-              fit: BoxFit.fill,
-            ),
-          ),
-          onPressed: () => toast('Long press to quit game...'),
-          onLongPress: () => GameUtils.quitGame(myProvider),
-        ),
-      ];
-    }
-
-    return Scaffold(
-      appBar: AppBar(
-        actions: menuActions,
-      ),
-      body: SafeArea(
-        child: Center(
-          child: myProvider.gameIsRunning
-              ? Game.buildGameWidget(myProvider)
-              : Parameters.buildParametersSelector(myProvider),
-        ),
-      ),
-    );
-  }
-}
diff --git a/lib/ui/layout/game.dart b/lib/ui/layout/game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..aa9d47c9fdf68e5c14eff6121c3108ceb10376bb
--- /dev/null
+++ b/lib/ui/layout/game.dart
@@ -0,0 +1,36 @@
+import 'package:flutter/material.dart';
+
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/ui/layout/tileset.dart';
+import 'package:solitaire/ui/widgets/game/indicator_top.dart';
+import 'package:solitaire/ui/widgets/game/message_game_end.dart';
+
+class Game extends StatelessWidget {
+  const Game({super.key, required this.myProvider});
+
+  final Data myProvider;
+
+  @override
+  Widget build(BuildContext context) {
+    final bool gameIsFinished = myProvider.gameIsFinished;
+
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.center,
+      children: [
+        const SizedBox(height: 8),
+        TopIndicator(myProvider: myProvider),
+        const SizedBox(height: 2),
+        Expanded(
+          child: Tileset(myProvider: myProvider),
+        ),
+        const SizedBox(height: 2),
+        Container(
+          child: gameIsFinished
+              ? EndGameMessage(myProvider: myProvider)
+              : const SizedBox(height: 2),
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/layout/parameters.dart b/lib/ui/layout/parameters.dart
new file mode 100644
index 0000000000000000000000000000000000000000..68d9ac836bb4c5bfc6c5017ec291fe3da4819f03
--- /dev/null
+++ b/lib/ui/layout/parameters.dart
@@ -0,0 +1,129 @@
+import 'package:flutter/material.dart';
+
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/ui/widgets/home/button_game_resume.dart';
+import 'package:solitaire/ui/widgets/home/button_game_start_new.dart';
+
+class Parameters extends StatelessWidget {
+  const Parameters({super.key, required this.myProvider});
+
+  final Data myProvider;
+
+  static const double separatorHeight = 2.0;
+  static const double blockMargin = 0.0;
+  static const double blockPadding = 0.0;
+  static const Color buttonBackgroundColor = Colors.white;
+  static const Color buttonBorderColorActive = Colors.blue;
+  static const Color buttonBorderColorInactive = Colors.white;
+  static const double buttonBorderWidth = 6.0;
+  static const double buttonBorderRadius = 8.0;
+  static const double buttonPadding = 0.0;
+  static const double buttonMargin = 0.0;
+
+  @override
+  Widget build(BuildContext context) {
+    List<Widget> lines = [];
+
+    List parameters = myProvider.availableParameters;
+    for (int index = 0; index < parameters.length; index++) {
+      lines.add(buildParameterSelector(myProvider, parameters[index]));
+      lines.add(const SizedBox(height: separatorHeight));
+    }
+
+    myProvider.loadCurrentSavedState();
+    Widget buttonsBlock = myProvider.hasCurrentSavedState()
+        ? ResumeGameButton(myProvider: myProvider)
+        : StartNewGameButton(myProvider: myProvider);
+
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.center,
+      children: [
+        const SizedBox(height: separatorHeight),
+        Expanded(
+          child: Column(
+            mainAxisSize: MainAxisSize.min,
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: lines,
+          ),
+        ),
+        const SizedBox(height: separatorHeight),
+        Container(
+          child: buttonsBlock,
+        ),
+      ],
+    );
+  }
+
+  static Image buildImageWidget(String imageAssetCode) {
+    return Image(
+      image: AssetImage('assets/icons/$imageAssetCode.png'),
+      fit: BoxFit.fill,
+    );
+  }
+
+  static Container buildImageContainerWidget(String imageAssetCode) {
+    return Container(
+      child: buildImageWidget(imageAssetCode),
+    );
+  }
+
+  static Column buildDecorationImageWidget() {
+    return Column(
+      children: [
+        TextButton(
+          child: buildImageContainerWidget('placeholder'),
+          onPressed: () {},
+        ),
+      ],
+    );
+  }
+
+  Widget buildParameterSelector(Data myProvider, String parameterCode) {
+    List availableValues = myProvider.getParameterAvailableValues(parameterCode);
+
+    if (availableValues.length == 1) {
+      return const SizedBox(height: 0.0);
+    }
+
+    return Table(
+      defaultColumnWidth: const IntrinsicColumnWidth(),
+      children: [
+        TableRow(
+          children: [
+            for (int index = 0; index < availableValues.length; index++)
+              Column(
+                children: [
+                  buildParameterButton(myProvider, parameterCode, availableValues[index])
+                ],
+              ),
+          ],
+        ),
+      ],
+    );
+  }
+
+  Widget buildParameterButton(Data myProvider, String parameterCode, String parameterValue) {
+    String currentValue = myProvider.getParameterValue(parameterCode).toString();
+
+    bool isActive = (parameterValue == currentValue);
+    String imageAsset = '${parameterCode}_$parameterValue';
+
+    return TextButton(
+      child: Container(
+        margin: const EdgeInsets.all(buttonMargin),
+        padding: const EdgeInsets.all(buttonPadding),
+        decoration: BoxDecoration(
+          color: buttonBackgroundColor,
+          borderRadius: BorderRadius.circular(buttonBorderRadius),
+          border: Border.all(
+            color: isActive ? buttonBorderColorActive : buttonBorderColorInactive,
+            width: buttonBorderWidth,
+          ),
+        ),
+        child: buildImageWidget(imageAsset),
+      ),
+      onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue),
+    );
+  }
+}
diff --git a/lib/ui/layout/tileset.dart b/lib/ui/layout/tileset.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4fe85a743bfc7cb8ccb3035a3dddd9c32d6b210c
--- /dev/null
+++ b/lib/ui/layout/tileset.dart
@@ -0,0 +1,42 @@
+import 'package:flutter/material.dart';
+
+import 'package:solitaire/provider/data.dart';
+
+class Tileset extends StatelessWidget {
+  const Tileset({super.key, required this.myProvider});
+
+  final Data myProvider;
+
+  @override
+  Widget build(BuildContext context) {
+    final Board board = myProvider.board;
+
+    Widget boardTileWithoutHole = Image(
+      image: AssetImage('assets/skins/${myProvider.parameterSkin}_board.png'),
+      width: myProvider.tileSize,
+      height: myProvider.tileSize,
+      fit: BoxFit.fill,
+    );
+
+    return Column(
+      children: [
+        Table(
+          defaultColumnWidth: const IntrinsicColumnWidth(),
+          children: [
+            for (int row = 0; row < board.length; row++)
+              TableRow(
+                children: [
+                  for (int col = 0; col < board[row].length; col++)
+                    TableCell(
+                      child: board[row][col] != null
+                          ? (board[row][col]?.render(myProvider) ?? Container())
+                          : boardTileWithoutHole,
+                    ),
+                ],
+              ),
+          ],
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/about_page.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f22e2adbcf2c3fbf29b74937ef251a5ab64db479
--- /dev/null
+++ b/lib/ui/screens/about_page.dart
@@ -0,0 +1,41 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:package_info_plus/package_info_plus.dart';
+
+import 'package:solitaire/ui/widgets/header_app.dart';
+
+class AboutPage extends StatelessWidget {
+  const AboutPage({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 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..9171fc2ac981a36123338eedce6cd09105852e5f
--- /dev/null
+++ b/lib/ui/screens/game_page.dart
@@ -0,0 +1,85 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/ui/layout/game.dart';
+import 'package:solitaire/ui/layout/parameters.dart';
+
+class GamePage extends StatefulWidget {
+  const GamePage({super.key});
+
+  @override
+  GamePageState createState() => GamePageState();
+}
+
+class GamePageState extends State<GamePage> {
+  @override
+  void initState() {
+    super.initState();
+
+    final Data myProvider = Provider.of<Data>(context, listen: false);
+    myProvider.initParametersValues();
+    myProvider.loadCurrentSavedState();
+  }
+
+  List<String> getImagesAssets(Data myProvider) {
+    final List<String> assets = [];
+
+    final List<String> gameImages = [
+      'button_back',
+      'button_delete_saved_game',
+      'button_resume_game',
+      'button_start',
+      'game_fail',
+      'game_win',
+      'placeholder',
+    ];
+    for (String layout in myProvider.availableLayoutValues) {
+      gameImages.add('layout_$layout');
+    }
+    for (String skin in myProvider.availableSkinValues) {
+      gameImages.add('skin_$skin');
+    }
+
+    for (String image in gameImages) {
+      assets.add('${'assets/icons/$image'}.png');
+    }
+
+    const List<String> skinImages = [
+      'board',
+      'hole',
+      'peg',
+    ];
+
+    for (String skin in myProvider.availableSkinValues) {
+      for (String image in skinImages) {
+        assets.add('${'${'assets/skins/$skin'}_$image'}.png');
+      }
+    }
+
+    return assets;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final Data myProvider = Provider.of<Data>(context);
+
+    if (!myProvider.assetsPreloaded) {
+      final List<String> assets = getImagesAssets(myProvider);
+      for (String asset in assets) {
+        precacheImage(AssetImage(asset), context);
+      }
+      myProvider.updateAssetsPreloaded(true);
+    }
+
+    myProvider.updateTileSize((MediaQuery.of(context).size.width - 40) / myProvider.boardSize);
+
+    return SafeArea(
+      child: Center(
+        child: myProvider.gameIsRunning
+            ? Game(myProvider: myProvider)
+            : Parameters(myProvider: myProvider),
+      ),
+    );
+  }
+}
diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/settings_page.dart
new file mode 100644
index 0000000000000000000000000000000000000000..63cb3f2c502e952d128108dceff49b16dce7a10d
--- /dev/null
+++ b/lib/ui/screens/settings_page.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+
+import 'package:solitaire/ui/widgets/header_app.dart';
+import 'package:solitaire/ui/widgets/settings/settings_form.dart';
+
+class SettingsPage extends StatelessWidget {
+  const SettingsPage({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),
+          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..36cd48520de4304219d8273481aecd572b181e5f
--- /dev/null
+++ b/lib/ui/skeleton.dart
@@ -0,0 +1,33 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:provider/provider.dart';
+
+import 'package:solitaire/config/menu.dart';
+import 'package:solitaire/cubit/bottom_nav_cubit.dart';
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/ui/widgets/app_bar.dart';
+import 'package:solitaire/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) {
+    final Data myProvider = Provider.of<Data>(context);
+
+    return Scaffold(
+      extendBodyBehindAppBar: false,
+      appBar: StandardAppBar(myProvider: myProvider),
+      bottomNavigationBar: const BottomNavBar(),
+      body: BlocBuilder<BottomNavCubit, int>(builder: (BuildContext context, int state) {
+        return Menu.getPageWidget(state);
+      }),
+      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..1dc274e7c430ae5822e3c01d400e16ee1844227f
--- /dev/null
+++ b/lib/ui/widgets/app_bar.dart
@@ -0,0 +1,37 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:overlay_support/overlay_support.dart';
+
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/ui/widgets/header_app.dart';
+import 'package:solitaire/utils/game_utils.dart';
+
+class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
+  const StandardAppBar({super.key, required this.myProvider});
+
+  final Data myProvider;
+
+  @override
+  Widget build(BuildContext context) {
+    final List<Widget> menuActions = [];
+
+    if (myProvider.gameIsRunning) {
+      menuActions.add(TextButton(
+        child: const Image(
+          image: AssetImage('assets/icons/button_back.png'),
+          fit: BoxFit.fill,
+        ),
+        onPressed: () => toast(tr('long_press_to_quit')),
+        onLongPress: () => GameUtils.quitGame(myProvider),
+      ));
+    }
+
+    return AppBar(
+      title: const AppHeader(text: 'app_name'),
+      actions: menuActions,
+    );
+  }
+
+  @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..7e3d4717dfcaff4a58173b18531da62361a389b8
--- /dev/null
+++ b/lib/ui/widgets/bottom_nav_bar.dart
@@ -0,0 +1,36 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:solitaire/config/menu.dart';
+import 'package:solitaire/cubit/bottom_nav_cubit.dart';
+
+class BottomNavBar extends StatelessWidget {
+  const BottomNavBar({super.key});
+
+  @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);
+            },
+            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/game/indicator_top.dart b/lib/ui/widgets/game/indicator_top.dart
new file mode 100644
index 0000000000000000000000000000000000000000..7ce0c3ef4fe6cfeab481697472e822a1823768cd
--- /dev/null
+++ b/lib/ui/widgets/game/indicator_top.dart
@@ -0,0 +1,47 @@
+import 'package:flutter/material.dart';
+
+import 'package:solitaire/provider/data.dart';
+
+class TopIndicator extends StatelessWidget {
+  const TopIndicator({super.key, required this.myProvider});
+
+  final Data myProvider;
+
+  @override
+  Widget build(BuildContext context) {
+    final int allowedMovesCount = myProvider.allowedMovesCount;
+
+    return Table(
+      children: [
+        TableRow(
+          children: [
+            Column(
+              children: [
+                Text(
+                  '♟️ ${myProvider.remainingPegsCount}',
+                  style: const TextStyle(
+                    fontSize: 40,
+                    fontWeight: FontWeight.w600,
+                    color: Colors.black,
+                  ),
+                ),
+              ],
+            ),
+            Column(
+              children: [
+                Text(
+                  allowedMovesCount.toString(),
+                  style: const TextStyle(
+                    fontSize: 20,
+                    fontWeight: FontWeight.w600,
+                    color: Colors.green,
+                  ),
+                ),
+              ],
+            ),
+          ],
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/message_game_end.dart b/lib/ui/widgets/game/message_game_end.dart
new file mode 100644
index 0000000000000000000000000000000000000000..cd6ca3ad64384a7cf48e93a3c91519bd04ffe06f
--- /dev/null
+++ b/lib/ui/widgets/game/message_game_end.dart
@@ -0,0 +1,42 @@
+import 'package:flutter/material.dart';
+
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/ui/widgets/home/button_game_restart.dart';
+
+class EndGameMessage extends StatelessWidget {
+  const EndGameMessage({super.key, required this.myProvider});
+
+  final Data myProvider;
+
+  @override
+  Widget build(BuildContext context) {
+    String decorationImageAssetName = '';
+    if (myProvider.gameWon()) {
+      decorationImageAssetName = 'assets/icons/game_win.png';
+    } else {
+      decorationImageAssetName = 'assets/icons/placeholder.png';
+    }
+
+    final Image decorationImage = Image(
+      image: AssetImage(decorationImageAssetName),
+      fit: BoxFit.fill,
+    );
+
+    return Container(
+      margin: const EdgeInsets.all(2),
+      padding: const EdgeInsets.all(2),
+      child: Table(
+        defaultColumnWidth: const IntrinsicColumnWidth(),
+        children: [
+          TableRow(
+            children: [
+              Column(children: [decorationImage]),
+              Column(children: [RestartGameButton(myProvider: myProvider)]),
+              Column(children: [decorationImage]),
+            ],
+          ),
+        ],
+      ),
+    );
+  }
+}
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/home/button_game_restart.dart b/lib/ui/widgets/home/button_game_restart.dart
new file mode 100644
index 0000000000000000000000000000000000000000..48dfc3438732370f607b916c7f15a4c1b6968673
--- /dev/null
+++ b/lib/ui/widgets/home/button_game_restart.dart
@@ -0,0 +1,21 @@
+import 'package:flutter/material.dart';
+
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/utils/game_utils.dart';
+
+class RestartGameButton extends StatelessWidget {
+  const RestartGameButton({super.key, required this.myProvider});
+
+  final Data myProvider;
+
+  @override
+  Widget build(BuildContext context) {
+    return TextButton(
+      child: const Image(
+        image: AssetImage('assets/icons/button_back.png'),
+        fit: BoxFit.fill,
+      ),
+      onPressed: () => GameUtils.quitAndDeleteCurrentGame(myProvider),
+    );
+  }
+}
diff --git a/lib/ui/widgets/home/button_game_resume.dart b/lib/ui/widgets/home/button_game_resume.dart
new file mode 100644
index 0000000000000000000000000000000000000000..185c92f9c1fc6d607c9d947804700a74f8ae4a84
--- /dev/null
+++ b/lib/ui/widgets/home/button_game_resume.dart
@@ -0,0 +1,42 @@
+import 'package:flutter/material.dart';
+
+import 'package:solitaire/ui/layout/parameters.dart';
+import 'package:solitaire/utils/game_utils.dart';
+
+class ResumeGameButton extends Parameters {
+  const ResumeGameButton({super.key, required super.myProvider});
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      margin: const EdgeInsets.all(Parameters.blockMargin),
+      padding: const EdgeInsets.all(Parameters.blockPadding),
+      child: Table(
+        defaultColumnWidth: const IntrinsicColumnWidth(),
+        children: [
+          TableRow(
+            children: [
+              Column(
+                children: [
+                  TextButton(
+                    child: Parameters.buildImageContainerWidget('button_delete_saved_game'),
+                    onPressed: () => GameUtils.deleteSavedGame(myProvider),
+                  ),
+                ],
+              ),
+              Column(
+                children: [
+                  TextButton(
+                    child: Parameters.buildImageContainerWidget('button_resume_game'),
+                    onPressed: () => GameUtils.resumeSavedGame(myProvider),
+                  ),
+                ],
+              ),
+              Parameters.buildDecorationImageWidget(),
+            ],
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/home/button_game_start_new.dart b/lib/ui/widgets/home/button_game_start_new.dart
new file mode 100644
index 0000000000000000000000000000000000000000..2de0c55bc99e5830965595bde7dd09617add80a2
--- /dev/null
+++ b/lib/ui/widgets/home/button_game_start_new.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/ui/layout/parameters.dart';
+import 'package:solitaire/utils/game_utils.dart';
+
+class StartNewGameButton extends StatelessWidget {
+  const StartNewGameButton({super.key, required this.myProvider});
+
+  final Data myProvider;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      margin: const EdgeInsets.all(Parameters.blockMargin),
+      padding: const EdgeInsets.all(Parameters.blockPadding),
+      child: Table(
+        defaultColumnWidth: const IntrinsicColumnWidth(),
+        children: [
+          TableRow(
+            children: [
+              Parameters.buildDecorationImageWidget(),
+              Column(
+                children: [
+                  TextButton(
+                    child: Parameters.buildImageContainerWidget('button_start'),
+                    onPressed: () => GameUtils.startNewGame(myProvider),
+                  ),
+                ],
+              ),
+              Parameters.buildDecorationImageWidget(),
+            ],
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/settings/settings_form.dart b/lib/ui/widgets/settings/settings_form.dart
new file mode 100644
index 0000000000000000000000000000000000000000..91e9fd50423ac3bdadcccfde1abb3d0939e0dcba
--- /dev/null
+++ b/lib/ui/widgets/settings/settings_form.dart
@@ -0,0 +1,63 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:unicons/unicons.dart';
+
+import 'package:solitaire/ui/widgets/settings/theme_card.dart';
+
+class SettingsForm extends StatefulWidget {
+  const SettingsForm({super.key});
+
+  @override
+  State<SettingsForm> createState() => _SettingsFormState();
+}
+
+class _SettingsFormState extends State<SettingsForm> {
+  @override
+  void dispose() {
+    super.dispose();
+  }
+
+  @override
+  void didChangeDependencies() {
+    super.didChangeDependencies();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        // Light/dark theme
+        Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: <Widget>[
+            const Text('settings_label_theme').tr(),
+            const Row(
+              mainAxisAlignment: MainAxisAlignment.end,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                ThemeCard(
+                  mode: ThemeMode.system,
+                  icon: UniconsLine.cog,
+                ),
+                ThemeCard(
+                  mode: ThemeMode.light,
+                  icon: UniconsLine.sun,
+                ),
+                ThemeCard(
+                  mode: ThemeMode.dark,
+                  icon: UniconsLine.moon,
+                )
+              ],
+            ),
+          ],
+        ),
+
+        const SizedBox(height: 16),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/widgets/settings/theme_card.dart b/lib/ui/widgets/settings/theme_card.dart
new file mode 100644
index 0000000000000000000000000000000000000000..71aafb03b99cb4909868892735a2ec48e019b01b
--- /dev/null
+++ b/lib/ui/widgets/settings/theme_card.dart
@@ -0,0 +1,47 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:solitaire/cubit/theme_cubit.dart';
+
+class ThemeCard extends StatelessWidget {
+  const ThemeCard({
+    super.key,
+    required this.mode,
+    required this.icon,
+  });
+
+  final IconData icon;
+  final ThemeMode mode;
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<ThemeCubit, ThemeModeState>(
+      builder: (BuildContext context, ThemeModeState state) {
+        return Card(
+          elevation: 2,
+          shadowColor: Theme.of(context).colorScheme.shadow,
+          color: state.themeMode == mode
+              ? Theme.of(context).colorScheme.primary
+              : Theme.of(context).colorScheme.surface,
+          shape: const RoundedRectangleBorder(
+            borderRadius: BorderRadius.all(Radius.circular(12)),
+          ),
+          margin: const EdgeInsets.all(5),
+          child: InkWell(
+            onTap: () => BlocProvider.of<ThemeCubit>(context).getTheme(
+              ThemeModeState(themeMode: mode),
+            ),
+            borderRadius: const BorderRadius.all(Radius.circular(12)),
+            child: Icon(
+              icon,
+              size: 32,
+              color: state.themeMode != mode
+                  ? Theme.of(context).colorScheme.primary
+                  : Colors.white,
+            ),
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart
index 19754fb6a536c31587ff7118954b0c3e22f0c5b8..349b05dd4e48f223109bb7647591e9bcbb27a12b 100644
--- a/lib/utils/board_utils.dart
+++ b/lib/utils/board_utils.dart
@@ -1,8 +1,8 @@
 import 'dart:math';
 
-import 'package:solitaire_game/entities/tile.dart';
-import 'package:solitaire_game/provider/data.dart';
-import 'package:solitaire_game/utils/tools.dart';
+import 'package:solitaire/entities/tile.dart';
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/utils/tools.dart';
 
 class BoardUtils {
   static printGrid(List cells) {
@@ -28,8 +28,8 @@ class BoardUtils {
     printlog('');
   }
 
-  static List<List<Tile?>> createBoardFromSavedState(Data myProvider, String savedBoard) {
-    List<List<Tile?>> board = [];
+  static Board createBoardFromSavedState(Data myProvider, String savedBoard) {
+    Board board = [];
     int boardSize = pow((savedBoard.length), 1 / 2).round();
     myProvider.updateBoardSize(boardSize);
 
@@ -99,7 +99,7 @@ class BoardUtils {
 
     List<String>? template = templates[myProvider.parameterLayout];
 
-    List<List<Tile?>> grid = [];
+    Board grid = [];
     int row = 0;
     template?.forEach((String line) {
       List<Tile?> gridLine = [];
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
index cd0c5ea7c309f56876771e558b54a1d8c7540670..69b0f4f014abb036969d43e86a62c94f405540e3 100644
--- a/lib/utils/game_utils.dart
+++ b/lib/utils/game_utils.dart
@@ -1,7 +1,7 @@
-import 'package:solitaire_game/entities/tile.dart';
-import 'package:solitaire_game/provider/data.dart';
-import 'package:solitaire_game/utils/board_utils.dart';
-import 'package:solitaire_game/utils/tools.dart';
+import 'package:solitaire/entities/tile.dart';
+import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/utils/board_utils.dart';
+import 'package:solitaire/utils/tools.dart';
 
 class GameUtils {
   static Future<void> quitGame(Data myProvider) async {
@@ -51,11 +51,11 @@ class GameUtils {
 
   static bool isMoveAllowed(Data myProvider, List<int> source, List<int> target) {
     // printlog('(test) Pick from ' + source.toString() + ' and drop on ' + target.toString());
-    List<List<Tile?>> board = myProvider.board;
-    int sourceCol = source[0];
-    int sourceRow = source[1];
-    int targetCol = target[0];
-    int targetRow = target[1];
+    final Board board = myProvider.board;
+    final int sourceCol = source[0];
+    final int sourceRow = source[1];
+    final int targetCol = target[0];
+    final int targetRow = target[1];
 
     // ensure source and target are inside range
     if (sourceRow < 0 ||
@@ -99,8 +99,8 @@ class GameUtils {
     }
 
     // ensure middle tile exists and has a peg
-    int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
-    int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
+    final int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
+    final int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
     if (board[middleRow][middleCol] == null || board[middleRow][middleCol]?.hasPeg == false) {
       // printlog('move forbidden: tile between source and target does not contain a peg');
       return false;
@@ -112,13 +112,13 @@ class GameUtils {
 
   static void move(Data myProvider, List<int> source, List<int> target) {
     printlog('Move from $source to $target');
-    int sourceCol = source[0];
-    int sourceRow = source[1];
-    int targetCol = target[0];
-    int targetRow = target[1];
+    final int sourceCol = source[0];
+    final int sourceRow = source[1];
+    final int targetCol = target[0];
+    final int targetRow = target[1];
 
-    int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
-    int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
+    final int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
+    final int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
 
     // remove peg from source
     myProvider.updatePegValue(sourceRow, sourceCol, false);
@@ -138,7 +138,7 @@ class GameUtils {
   static List<Tile> listRemainingPegs(Data myProvider) {
     List<Tile> pegs = [];
 
-    List<List<Tile?>> board = myProvider.board;
+    Board board = myProvider.board;
     for (int rowIndex = 0; rowIndex < board.length; rowIndex++) {
       for (int colIndex = 0; colIndex < board[rowIndex].length; colIndex++) {
         Tile? tile = board[rowIndex][colIndex];
@@ -159,10 +159,10 @@ class GameUtils {
     int allowedMovesCount = 0;
     List<Tile> pegs = GameUtils.listRemainingPegs(myProvider);
     for (Tile tile in pegs) {
-      int row = tile.currentRow;
-      int col = tile.currentCol;
-      List<int> source = [col, row];
-      List<List<int>> targets = [
+      final int row = tile.currentRow;
+      final int col = tile.currentCol;
+      final List<int> source = [col, row];
+      final List<List<int>> targets = [
         [col - 2, row],
         [col + 2, row],
         [col, row - 2],
diff --git a/pubspec.lock b/pubspec.lock
index 6b1fdfef808496ebd4ff8ce5bb9e51bfbc6469e8..12d429bb18ac218313d455ba71028cdbb3234bb9 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,6 +1,14 @@
 # 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:
@@ -9,6 +17,14 @@ packages:
       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:
@@ -17,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:
@@ -25,6 +49,38 @@ 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:
@@ -46,6 +102,14 @@ packages:
     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:
@@ -54,11 +118,56 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "3.0.1"
+  flutter_localizations:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.0"
   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:
@@ -99,14 +208,54 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.1.0"
-  path:
+  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:
@@ -199,10 +348,10 @@ packages:
     dependency: transitive
     description:
       name: shared_preferences_web
-      sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a"
+      sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.0"
+    version: "2.2.2"
   shared_preferences_windows:
     dependency: transitive
     description:
@@ -216,6 +365,54 @@ packages:
     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:
@@ -228,18 +425,18 @@ packages:
     dependency: transitive
     description:
       name: web
-      sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad"
+      sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.0"
+    version: "0.4.2"
   win32:
     dependency: transitive
     description:
       name: win32
-      sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
+      sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480"
       url: "https://pub.dev"
     source: hosted
-    version: "5.2.0"
+    version: "5.3.0"
   xdg_directories:
     dependency: transitive
     description:
@@ -250,4 +447,4 @@ packages:
     version: "1.0.4"
 sdks:
   dart: ">=3.3.0 <4.0.0"
-  flutter: ">=3.19.0"
+  flutter: ">=3.16.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index f79e714a58972baa888f2bdfe1e18571c7daa1a9..5c4cd59b3a02df9bff6342803c1f8201562af795 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,7 +1,8 @@
-name: solitaire_game
+name: solitaire
 description: Solitaire Game
+
 publish_to: 'none'
-version: 0.0.16+16
+version: 0.0.17+17
 
 environment:
   sdk: '^3.0.0'
@@ -9,9 +10,19 @@ environment:
 dependencies:
   flutter:
     sdk: flutter
+
+  easy_localization: ^3.0.1
+  equatable: ^2.0.5
+  flutter_bloc: ^8.1.1
+  hive: ^2.2.3
+  hydrated_bloc: ^9.0.0
+  overlay_support: ^2.1.0
   provider: ^6.0.5
   shared_preferences: ^2.2.1
-  overlay_support: ^2.1.0
+  package_info_plus: ^5.0.1
+  path: ^1.9.0
+  path_provider: ^2.0.11
+  unicons: ^2.1.1
 
 dev_dependencies:
   flutter_lints: ^3.0.1
@@ -21,3 +32,17 @@ flutter:
   assets:
     - assets/icons/
     - assets/skins/
+    - 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
+