diff --git a/android/app/build.gradle b/android/app/build.gradle
index 7e47b56357ab61b4f65d37b63a614ce814af536a..b66c7309008023fd1c5bbe9acda14bb0851f8780 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -37,7 +37,7 @@ if (keystorePropertiesFile.exists()) {
 }
 
 android {
-    compileSdkVersion 33
+    compileSdkVersion 34
     namespace "org.benoitharrault.stopmotion"
 
     defaultConfig {
diff --git a/android/gradle.properties b/android/gradle.properties
index 85b94f88ee157e1d1b3cec184c8948902443d36f..65eed6426393974efb5a056ec44936d42b5ef2a1 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.7
-app.versionCode=7
+app.versionName=0.0.8
+app.versionCode=8
diff --git a/assets/translations/en.json b/assets/translations/en.json
index f53b1cdd7eb11b40a9bfa48b5ced2628de1cb912..2fbf22ada976732bc4ffb4752cb8bc0897c397b5 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -1,13 +1,16 @@
 {
-  "app_name": "Stop Motion assistant",
-
-  "bottom_nav_home": "Home",
-  "bottom_nav_camera": "Camera",
-  "bottom_nav_settings": "Settings",
+  "app_name": "Stop Motion",
 
   "settings_title": "Settings",
-  "settings_title_global": "Global settings",
-  "settings_label_dummy_value": "Dummy parameter: ",
+  "settings_label_theme": "Theme mode",
+
+  "about_title": "Informations",
+  "about_content": "MIDI synth",
+  "about_version": "Version: {version}",
+
+  "page_home": "Home",
+  "page_editor": "Editor",
+  "page_player": "Player",
 
-  "lang_prefix": "en"
+  "": ""
 }
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index 69be2063cc2af3de1d9ec30788c798a32313653c..770ad86a5155394806ef7408fc162ba8b602e01f 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -1,13 +1,16 @@
 {
-  "app_name": "Assistant Stop Motion",
-
-  "bottom_nav_home": "Accueil",
-  "bottom_nav_camera": "Caméra",
-  "bottom_nav_settings": "Réglages",
+  "app_name": "Stop Motion",
 
   "settings_title": "Réglages",
-  "settings_title_global": "Réglages globaux",
-  "settings_label_dummy_value": "Réglage bidon : ",
+  "settings_label_theme": "Thème de couleurs",
+
+  "about_title": "Informations",
+  "about_content": "MIDI synth.",
+  "about_version": "Version : {version}",
+
+  "page_home": "Accueil",
+  "page_editor": "Édition",
+  "page_player": "Lecture",
 
-  "lang_prefix": "fr"
+  "": ""
 }
diff --git a/fastlane/metadata/android/en-US/changelogs/8.txt b/fastlane/metadata/android/en-US/changelogs/8.txt
new file mode 100644
index 0000000000000000000000000000000000000000..060b202b87dcd33388eb8a9d1a45cbd276fc8ba3
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/8.txt
@@ -0,0 +1 @@
+Improve/normalize app architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/8.txt b/fastlane/metadata/android/fr-FR/changelogs/8.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3cab228cbe7443782c4b187cbe805e4d0ba8e71a
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/8.txt
@@ -0,0 +1 @@
+Amélioration/normalisation de l'architecture de l'application.
diff --git a/lib/config/activity_page.dart b/lib/config/activity_page.dart
new file mode 100644
index 0000000000000000000000000000000000000000..29314379fa159675e4c47fa91ce6eb19063d9854
--- /dev/null
+++ b/lib/config/activity_page.dart
@@ -0,0 +1,61 @@
+import 'package:flutter/material.dart';
+import 'package:unicons/unicons.dart';
+
+import 'package:stopmotion/ui/pages/editor.dart';
+import 'package:stopmotion/ui/pages/home.dart';
+import 'package:stopmotion/ui/pages/player.dart';
+
+class ActivityPageItem {
+  final Icon icon;
+  final Widget page;
+  final String code;
+
+  const ActivityPageItem({
+    required this.icon,
+    required this.page,
+    required this.code,
+  });
+}
+
+class ActivityPage {
+  static const indexHome = 0;
+  static const pageHome = ActivityPageItem(
+    icon: Icon(UniconsLine.home),
+    page: PageHome(),
+    code: 'page_home',
+  );
+
+  static const indexEditor = 1;
+  static const pageEditor = ActivityPageItem(
+    icon: Icon(UniconsLine.setting),
+    page: PageEditor(),
+    code: 'page_editor',
+  );
+
+  static const indexPlayer = 2;
+  static const pagePlayer = ActivityPageItem(
+    icon: Icon(UniconsLine.info_circle),
+    page: PagePlayer(),
+    code: 'page_player',
+  );
+
+  static Map<int, ActivityPageItem> items = {
+    indexHome: pageHome,
+    indexEditor: pageEditor,
+    indexPlayer: pagePlayer,
+  };
+
+  static bool isIndexAllowed(int pageIndex) {
+    return items.keys.contains(pageIndex);
+  }
+
+  static ActivityPageItem getPageItem(int pageIndex) {
+    return items[pageIndex] ?? pageHome;
+  }
+
+  static Widget getPageWidget(int pageIndex) {
+    return items[pageIndex]?.page ?? pageHome.page;
+  }
+
+  static int itemsCount = ActivityPage.items.length;
+}
diff --git a/lib/config/default_activity_settings.dart b/lib/config/default_activity_settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..23b9a5c4b13be14661db04285a7525cf1bf14539
--- /dev/null
+++ b/lib/config/default_activity_settings.dart
@@ -0,0 +1,33 @@
+import 'package:stopmotion/utils/tools.dart';
+
+class DefaultActivitySettings {
+  // available activity parameters codes
+  static const String parameterCodeMovieType = 'movieType';
+  static const List<String> availableParameters = [
+    parameterCodeMovieType,
+  ];
+
+  // items count: available values
+  static const String movieTypeValueDefault = 'default';
+  static const List<String> allowedMovieTypeValues = [
+    movieTypeValueDefault,
+  ];
+  // items count: default value
+  static const String defaultMovieTypeValue = movieTypeValueDefault;
+
+  // available values from parameter code
+  static List<String> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case parameterCodeMovieType:
+        return DefaultActivitySettings.allowedMovieTypeValues;
+    }
+
+    printlog('Did not find any available value for activity parameter "$parameterCode".');
+    return [];
+  }
+
+  // parameters displayed with assets (instead of painter)
+  static List<String> displayedWithAssets = [
+    //
+  ];
+}
diff --git a/lib/config/default_global_settings.dart b/lib/config/default_global_settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b40decad910ede779fb5be49b0cda80812682e4d
--- /dev/null
+++ b/lib/config/default_global_settings.dart
@@ -0,0 +1,33 @@
+import 'package:stopmotion/utils/tools.dart';
+
+class DefaultGlobalSettings {
+  // available global parameters codes
+  static const String parameterCodeSkin = 'skin';
+  static const List<String> availableParameters = [
+    parameterCodeSkin,
+  ];
+
+  // skin: available values
+  static const String skinValueDefault = 'default';
+  static const List<String> allowedSkinValues = [
+    skinValueDefault,
+  ];
+  // skin: default value
+  static const String defaultSkinValue = skinValueDefault;
+
+  // available values from parameter code
+  static List<String> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case parameterCodeSkin:
+        return DefaultGlobalSettings.allowedSkinValues;
+    }
+
+    printlog('Did not find any available value for global parameter "$parameterCode".');
+    return [];
+  }
+
+  // parameters displayed with assets (instead of painter)
+  static List<String> displayedWithAssets = [
+    //
+  ];
+}
diff --git a/lib/config/default_settings.dart b/lib/config/default_settings.dart
deleted file mode 100644
index 751fd3c28a8cc6bcec81285d504621896da998d0..0000000000000000000000000000000000000000
--- a/lib/config/default_settings.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-class DefaultSettings {
-  static const int defaultDummyValue = 20;
-
-  static const List<int> allowedDummyValues = [
-    10,
-    defaultDummyValue,
-    30,
-  ];
-}
diff --git a/lib/config/screen.dart b/lib/config/screen.dart
new file mode 100644
index 0000000000000000000000000000000000000000..46382ae9824be4b247aff08f051634a591a23287
--- /dev/null
+++ b/lib/config/screen.dart
@@ -0,0 +1,61 @@
+import 'package:flutter/material.dart';
+import 'package:unicons/unicons.dart';
+
+import 'package:stopmotion/ui/screens/about.dart';
+import 'package:stopmotion/ui/screens/activity.dart';
+import 'package:stopmotion/ui/screens/settings.dart';
+
+class ScreenItem {
+  final Icon icon;
+  final Widget screen;
+  final bool displayBottomNavBar;
+
+  const ScreenItem({
+    required this.icon,
+    required this.screen,
+    required this.displayBottomNavBar,
+  });
+}
+
+class Screen {
+  static const indexActivity = 0;
+  static const screenActivity = ScreenItem(
+    icon: Icon(UniconsLine.home),
+    screen: ScreenActivity(),
+    displayBottomNavBar: true,
+  );
+
+  static const indexSettings = 1;
+  static const screenSettings = ScreenItem(
+    icon: Icon(UniconsLine.setting),
+    screen: ScreenSettings(),
+    displayBottomNavBar: false,
+  );
+
+  static const indexAbout = 2;
+  static const screenAbout = ScreenItem(
+    icon: Icon(UniconsLine.info_circle),
+    screen: ScreenAbout(),
+    displayBottomNavBar: false,
+  );
+
+  static Map<int, ScreenItem> items = {
+    indexActivity: screenActivity,
+    indexSettings: screenSettings,
+    indexAbout: screenAbout,
+  };
+
+  static bool isIndexAllowed(int screenIndex) {
+    return items.keys.contains(screenIndex);
+  }
+
+  static Widget getWidget(int screenIndex) {
+    return items[screenIndex]?.screen ?? screenActivity.screen;
+  }
+
+  static bool displayBottomNavBar(int screenIndex) {
+    return items[screenIndex]?.displayBottomNavBar ?? screenActivity.displayBottomNavBar;
+  }
+
+  static int itemsCount = Screen.items.length;
+}
diff --git a/lib/config/theme.dart b/lib/config/theme.dart
index be390348c7868e7c63387df13e13c46de43f8a23..74f532fd5abf693979118609564d29167e902009 100644
--- a/lib/config/theme.dart
+++ b/lib/config/theme.dart
@@ -39,11 +39,9 @@ final ColorScheme lightColorScheme = ColorScheme.light(
   secondary: primarySwatch.shade500,
   onSecondary: Colors.white,
   error: errorColor,
-  background: textSwatch.shade200,
-  onBackground: textSwatch.shade500,
   onSurface: textSwatch.shade500,
   surface: textSwatch.shade50,
-  surfaceVariant: Colors.white,
+  surfaceContainerHighest: Colors.white,
   shadow: textSwatch.shade900.withOpacity(.1),
 );
 
@@ -52,11 +50,9 @@ final ColorScheme darkColorScheme = ColorScheme.dark(
   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),
+  surfaceContainerHighest: const Color(0xFF282832),
   shadow: textSwatch.shade900.withOpacity(.2),
 );
 
@@ -192,5 +188,3 @@ final ThemeData darkTheme = lightTheme.copyWith(
     ),
   ),
 );
-
-final ThemeData appTheme = darkTheme;
diff --git a/lib/cubit/activity_cubit.dart b/lib/cubit/activity_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..9ab361adcac13a9b1562fee1723dd22593b08d66
--- /dev/null
+++ b/lib/cubit/activity_cubit.dart
@@ -0,0 +1,90 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:stopmotion/models/activity/activity.dart';
+import 'package:stopmotion/models/settings/settings_activity.dart';
+import 'package:stopmotion/models/settings/settings_global.dart';
+
+part 'activity_state.dart';
+
+class ActivityCubit extends HydratedCubit<ActivityState> {
+  ActivityCubit()
+      : super(ActivityState(
+          currentActivity: Activity.createNull(),
+        ));
+
+  void updateState(Activity activity) {
+    emit(ActivityState(
+      currentActivity: activity,
+    ));
+  }
+
+  void refresh() {
+    final Activity activity = Activity(
+      // Settings
+      activitySettings: state.currentActivity.activitySettings,
+      globalSettings: state.currentActivity.globalSettings,
+      // State
+      isRunning: state.currentActivity.isRunning,
+      isStarted: state.currentActivity.isStarted,
+      isFinished: state.currentActivity.isFinished,
+      animationInProgress: state.currentActivity.animationInProgress,
+      // Base data
+      pictures: state.currentActivity.pictures,
+      // Activity data
+      position: state.currentActivity.position,
+    );
+    // activity.dump();
+
+    updateState(activity);
+  }
+
+  void startNewActivity({
+    required ActivitySettings activitySettings,
+    required GlobalSettings globalSettings,
+  }) {
+    final Activity newActivity = Activity.createNew(
+      // Settings
+      activitySettings: activitySettings,
+      globalSettings: globalSettings,
+    );
+
+    newActivity.dump();
+
+    updateState(newActivity);
+    refresh();
+  }
+
+  void quitActivity() {
+    state.currentActivity.isRunning = false;
+    refresh();
+  }
+
+  void resumeSavedActivity() {
+    state.currentActivity.isRunning = true;
+    refresh();
+  }
+
+  void deleteSavedActivity() {
+    state.currentActivity.isRunning = false;
+    state.currentActivity.isFinished = true;
+    refresh();
+  }
+
+  @override
+  ActivityState? fromJson(Map<String, dynamic> json) {
+    final Activity currentActivity = json['currentActivity'] as Activity;
+
+    return ActivityState(
+      currentActivity: currentActivity,
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(ActivityState state) {
+    return <String, dynamic>{
+      'currentActivity': state.currentActivity.toJson(),
+    };
+  }
+}
diff --git a/lib/cubit/activity_state.dart b/lib/cubit/activity_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..887b45e4255fd7de1cc7744569d82a38a66602f2
--- /dev/null
+++ b/lib/cubit/activity_state.dart
@@ -0,0 +1,15 @@
+part of 'activity_cubit.dart';
+
+@immutable
+class ActivityState extends Equatable {
+  const ActivityState({
+    required this.currentActivity,
+  });
+
+  final Activity currentActivity;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        currentActivity,
+      ];
+}
diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/bottom_nav_cubit.dart
deleted file mode 100644
index 8753255ac7acba27b594ea5cfb5b46aafee31625..0000000000000000000000000000000000000000
--- a/lib/cubit/bottom_nav_cubit.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-import 'package:hydrated_bloc/hydrated_bloc.dart';
-
-class BottomNavCubit extends HydratedCubit<int> {
-  BottomNavCubit() : super(0);
-
-  int pagesCount = 3;
-
-  void updateIndex(int index) {
-    if (isIndexAllowed(index)) {
-      emit(index);
-    } else {
-      goToHomePage();
-    }
-  }
-
-  bool isIndexAllowed(int index) {
-    return (index >= 0) && (index < pagesCount);
-  }
-
-  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/nav_cubit_pages.dart b/lib/cubit/nav_cubit_pages.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e64bc1139f40c761eea2fba07f80ce0c496c464e
--- /dev/null
+++ b/lib/cubit/nav_cubit_pages.dart
@@ -0,0 +1,25 @@
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:stopmotion/config/activity_page.dart';
+
+class NavCubitPage extends HydratedCubit<int> {
+  NavCubitPage() : super(0);
+
+  void updateIndex(int index) {
+    if (ActivityPage.isIndexAllowed(index)) {
+      emit(index);
+    } else {
+      emit(ActivityPage.indexHome);
+    }
+  }
+
+  @override
+  int fromJson(Map<String, dynamic> json) {
+    return ActivityPage.indexHome;
+  }
+
+  @override
+  Map<String, dynamic>? toJson(int state) {
+    return <String, int>{'pageIndex': state};
+  }
+}
diff --git a/lib/cubit/nav_cubit_screens.dart b/lib/cubit/nav_cubit_screens.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ca76f548b52c21b221e53f6b565c4efa0b52773a
--- /dev/null
+++ b/lib/cubit/nav_cubit_screens.dart
@@ -0,0 +1,37 @@
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:stopmotion/config/screen.dart';
+
+class NavCubitScreen extends HydratedCubit<int> {
+  NavCubitScreen() : super(0);
+
+  void updateIndex(int index) {
+    if (Screen.isIndexAllowed(index)) {
+      emit(index);
+    } else {
+      goToActivityPage();
+    }
+  }
+
+  void goToActivityPage() {
+    emit(Screen.indexActivity);
+  }
+
+  void goToSettingsPage() {
+    emit(Screen.indexSettings);
+  }
+
+  void goToAboutPage() {
+    emit(Screen.indexAbout);
+  }
+
+  @override
+  int fromJson(Map<String, dynamic> json) {
+    return Screen.indexActivity;
+  }
+
+  @override
+  Map<String, dynamic>? toJson(int state) {
+    return <String, int>{'screenIndex': state};
+  }
+}
diff --git a/lib/cubit/settings_activity_cubit.dart b/lib/cubit/settings_activity_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f0e460d7bcfbcc83b9ce009ada99f5ecceeb4090
--- /dev/null
+++ b/lib/cubit/settings_activity_cubit.dart
@@ -0,0 +1,62 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:stopmotion/config/default_activity_settings.dart';
+import 'package:stopmotion/models/settings/settings_activity.dart';
+
+part 'settings_activity_state.dart';
+
+class ActivitySettingsCubit extends HydratedCubit<ActivitySettingsState> {
+  ActivitySettingsCubit()
+      : super(ActivitySettingsState(settings: ActivitySettings.createDefault()));
+
+  void setValues({
+    String? movieType,
+  }) {
+    emit(
+      ActivitySettingsState(
+        settings: ActivitySettings(
+          movieType: movieType ?? state.settings.movieType,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultActivitySettings.parameterCodeMovieType:
+        return ActivitySettings.getMovieTypeValueFromUnsafe(state.settings.movieType);
+    }
+
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    final String movieType = code == DefaultActivitySettings.parameterCodeMovieType
+        ? value
+        : getParameterValue(DefaultActivitySettings.parameterCodeMovieType);
+
+    setValues(
+      movieType: movieType,
+    );
+  }
+
+  @override
+  ActivitySettingsState? fromJson(Map<String, dynamic> json) {
+    final String movieType = json[DefaultActivitySettings.parameterCodeMovieType] as String;
+
+    return ActivitySettingsState(
+      settings: ActivitySettings(
+        movieType: movieType,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(ActivitySettingsState state) {
+    return <String, dynamic>{
+      DefaultActivitySettings.parameterCodeMovieType: state.settings.movieType,
+    };
+  }
+}
diff --git a/lib/cubit/settings_activity_state.dart b/lib/cubit/settings_activity_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..2b2de42011634e81ae9e6f8bcaa1577f239c778b
--- /dev/null
+++ b/lib/cubit/settings_activity_state.dart
@@ -0,0 +1,15 @@
+part of 'settings_activity_cubit.dart';
+
+@immutable
+class ActivitySettingsState extends Equatable {
+  const ActivitySettingsState({
+    required this.settings,
+  });
+
+  final ActivitySettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+}
diff --git a/lib/cubit/settings_cubit.dart b/lib/cubit/settings_cubit.dart
deleted file mode 100644
index 0c681feef3211012fa516631ef2b079365856206..0000000000000000000000000000000000000000
--- a/lib/cubit/settings_cubit.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-import 'package:equatable/equatable.dart';
-import 'package:flutter/material.dart';
-import 'package:hydrated_bloc/hydrated_bloc.dart';
-
-import 'package:stopmotion/config/default_settings.dart';
-
-part 'settings_state.dart';
-
-class SettingsCubit extends HydratedCubit<SettingsState> {
-  SettingsCubit() : super(const SettingsState());
-
-  int getDummyValue() {
-    return state.dummyValue ?? DefaultSettings.defaultDummyValue;
-  }
-
-  void setValues({
-    int? dummyValue,
-  }) {
-    emit(SettingsState(
-      dummyValue: dummyValue ?? state.dummyValue,
-    ));
-  }
-
-  @override
-  SettingsState? fromJson(Map<String, dynamic> json) {
-    int dummyValue = json['dummyValue'] as int;
-
-    return SettingsState(
-      dummyValue: dummyValue,
-    );
-  }
-
-  @override
-  Map<String, dynamic>? toJson(SettingsState state) {
-    return <String, dynamic>{
-      'dummyValue': state.dummyValue ?? DefaultSettings.defaultDummyValue,
-    };
-  }
-}
diff --git a/lib/cubit/settings_global_cubit.dart b/lib/cubit/settings_global_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f5b2f0667916c5144243eec7532a795e80a523e7
--- /dev/null
+++ b/lib/cubit/settings_global_cubit.dart
@@ -0,0 +1,60 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:stopmotion/config/default_global_settings.dart';
+import 'package:stopmotion/models/settings/settings_global.dart';
+
+part 'settings_global_state.dart';
+
+class GlobalSettingsCubit extends HydratedCubit<GlobalSettingsState> {
+  GlobalSettingsCubit() : super(GlobalSettingsState(settings: GlobalSettings.createDefault()));
+
+  void setValues({
+    String? skin,
+  }) {
+    emit(
+      GlobalSettingsState(
+        settings: GlobalSettings(
+          skin: skin ?? state.settings.skin,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultGlobalSettings.parameterCodeSkin:
+        return GlobalSettings.getSkinValueFromUnsafe(state.settings.skin);
+    }
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    final String skin = (code == DefaultGlobalSettings.parameterCodeSkin)
+        ? value
+        : getParameterValue(DefaultGlobalSettings.parameterCodeSkin);
+
+    setValues(
+      skin: skin,
+    );
+  }
+
+  @override
+  GlobalSettingsState? fromJson(Map<String, dynamic> json) {
+    final String skin = json[DefaultGlobalSettings.parameterCodeSkin] as String;
+
+    return GlobalSettingsState(
+      settings: GlobalSettings(
+        skin: skin,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GlobalSettingsState state) {
+    return <String, dynamic>{
+      DefaultGlobalSettings.parameterCodeSkin: state.settings.skin,
+    };
+  }
+}
diff --git a/lib/cubit/settings_global_state.dart b/lib/cubit/settings_global_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ebcddd700f252257223ca8e16c85202b04f3ff24
--- /dev/null
+++ b/lib/cubit/settings_global_state.dart
@@ -0,0 +1,15 @@
+part of 'settings_global_cubit.dart';
+
+@immutable
+class GlobalSettingsState extends Equatable {
+  const GlobalSettingsState({
+    required this.settings,
+  });
+
+  final GlobalSettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+}
diff --git a/lib/cubit/settings_state.dart b/lib/cubit/settings_state.dart
deleted file mode 100644
index 33953d6aada4d1aa30273543f91660cbcdd9c341..0000000000000000000000000000000000000000
--- a/lib/cubit/settings_state.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-part of 'settings_cubit.dart';
-
-@immutable
-class SettingsState extends Equatable {
-  const SettingsState({
-    this.dummyValue,
-  });
-
-  final int? dummyValue;
-
-  @override
-  List<dynamic> get props => <dynamic>[
-        dummyValue,
-      ];
-
-  Map<String, dynamic> get values => <String, dynamic>{
-        'dummyValue': dummyValue,
-      };
-}
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/main.dart b/lib/main.dart
index 7ce98c62d7c9ae45735ede3e07a831da6a6e0308..042dbd65e41f6c10c4b6f947f51d0fc07c62b534 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -2,20 +2,24 @@ 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:stopmotion/config/theme.dart';
-import 'package:stopmotion/cubit/bottom_nav_cubit.dart';
-import 'package:stopmotion/cubit/settings_cubit.dart';
+import 'package:stopmotion/cubit/activity_cubit.dart';
+import 'package:stopmotion/cubit/nav_cubit_pages.dart';
+import 'package:stopmotion/cubit/nav_cubit_screens.dart';
+import 'package:stopmotion/cubit/settings_global_cubit.dart';
+import 'package:stopmotion/cubit/settings_activity_cubit.dart';
+import 'package:stopmotion/cubit/theme_cubit.dart';
 import 'package:stopmotion/ui/skeleton.dart';
 
 void main() async {
-  /// Initialize packages
+  // Initialize packages
   WidgetsFlutterBinding.ensureInitialized();
-
   await EasyLocalization.ensureInitialized();
   final Directory tmpDir = await getTemporaryDirectory();
   Hive.init(tmpDir.toString());
@@ -23,18 +27,17 @@ void main() async {
     storageDirectory: tmpDir,
   );
 
-  runApp(
-    EasyLocalization(
-      path: 'assets/translations',
-      supportedLocales: const <Locale>[
-        Locale('en'),
-        Locale('fr'),
-      ],
-      fallbackLocale: const Locale('en'),
-      useFallbackTranslations: true,
-      child: const MyApp(),
-    ),
-  );
+  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
+      .then((value) => 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 {
@@ -44,19 +47,31 @@ class MyApp extends StatelessWidget {
   Widget build(BuildContext context) {
     return MultiBlocProvider(
       providers: [
-        BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
-        BlocProvider<SettingsCubit>(create: (context) => SettingsCubit()),
+        BlocProvider<NavCubitPage>(create: (context) => NavCubitPage()),
+        BlocProvider<NavCubitScreen>(create: (context) => NavCubitScreen()),
+        BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()),
+        BlocProvider<ActivityCubit>(create: (context) => ActivityCubit()),
+        BlocProvider<GlobalSettingsCubit>(create: (context) => GlobalSettingsCubit()),
+        BlocProvider<ActivitySettingsCubit>(create: (context) => ActivitySettingsCubit()),
       ],
-      child: MaterialApp(
-        title: 'Stop Motion',
-        theme: appTheme,
-        home: const SkeletonScreen(),
-
-        // Localization stuff
-        localizationsDelegates: context.localizationDelegates,
-        supportedLocales: context.supportedLocales,
-        locale: context.locale,
-        debugShowCheckedModeBanner: false,
+      child: BlocBuilder<ThemeCubit, ThemeModeState>(
+        builder: (BuildContext context, ThemeModeState state) {
+          return MaterialApp(
+            title: 'Stop Motion',
+            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,
+          );
+        },
       ),
     );
   }
diff --git a/lib/models/activity/activity.dart b/lib/models/activity/activity.dart
new file mode 100644
index 0000000000000000000000000000000000000000..6b778cb963c164c320d4ffee4327db0ee239806b
--- /dev/null
+++ b/lib/models/activity/activity.dart
@@ -0,0 +1,113 @@
+import 'package:stopmotion/models/data/picture.dart';
+import 'package:stopmotion/models/settings/settings_activity.dart';
+import 'package:stopmotion/models/settings/settings_global.dart';
+import 'package:stopmotion/utils/tools.dart';
+
+class Activity {
+  Activity({
+    // Settings
+    required this.activitySettings,
+    required this.globalSettings,
+
+    // State
+    this.isRunning = false,
+    this.isStarted = false,
+    this.isFinished = false,
+    this.animationInProgress = false,
+
+    // Base data
+    this.pictures = const [],
+
+    // Activity data
+    this.position = 1,
+  });
+
+  // Settings
+  final ActivitySettings activitySettings;
+  final GlobalSettings globalSettings;
+
+  // State
+  bool isRunning;
+  bool isStarted;
+  bool isFinished;
+  bool animationInProgress;
+
+  // Base data
+  List<Picture> pictures;
+
+  // Activity data
+  int position;
+
+  factory Activity.createNull() {
+    return Activity(
+      // Settings
+      activitySettings: ActivitySettings.createDefault(),
+      globalSettings: GlobalSettings.createDefault(),
+      // Base data
+      pictures: [],
+    );
+  }
+
+  factory Activity.createNew({
+    ActivitySettings? activitySettings,
+    GlobalSettings? globalSettings,
+  }) {
+    final ActivitySettings newActivitySettings =
+        activitySettings ?? ActivitySettings.createDefault();
+    final GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
+
+    return Activity(
+      // Settings
+      activitySettings: newActivitySettings,
+      globalSettings: newGlobalSettings,
+      // State
+      isRunning: true,
+      // Base data
+      pictures: [],
+    );
+  }
+
+  bool get canBeResumed => isStarted && !isFinished;
+
+  void dump() {
+    printlog('');
+    printlog('## Current activity dump:');
+    printlog('');
+    printlog('$Activity:');
+    printlog('  Settings');
+    activitySettings.dump();
+    globalSettings.dump();
+    printlog('  State');
+    printlog('    isRunning: $isRunning');
+    printlog('    isStarted: $isStarted');
+    printlog('    isFinished: $isFinished');
+    printlog('    animationInProgress: $animationInProgress');
+    printlog('  Base data');
+    printlog('    pictures: $pictures');
+    printlog('  Activity data');
+    printlog('    position: $position');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$Activity(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      // Settings
+      'activitySettings': activitySettings.toJson(),
+      'globalSettings': globalSettings.toJson(),
+      // State
+      'isRunning': isRunning,
+      'isStarted': isStarted,
+      'isFinished': isFinished,
+      'animationInProgress': animationInProgress,
+      // Base data
+      'pictures': pictures,
+      // Activity data
+      'position': position,
+    };
+  }
+}
diff --git a/lib/models/data/picture.dart b/lib/models/data/picture.dart
new file mode 100644
index 0000000000000000000000000000000000000000..73df607fab99cde1d5a68a37f7869211f952c288
--- /dev/null
+++ b/lib/models/data/picture.dart
@@ -0,0 +1,21 @@
+class Picture {
+  final String key;
+  final String file;
+
+  const Picture({
+    required this.key,
+    required this.file,
+  });
+
+  @override
+  String toString() {
+    return '$Picture(${toJson()})';
+  }
+
+  Map<String, dynamic> toJson() {
+    return {
+      'key': key,
+      'file': file,
+    };
+  }
+}
diff --git a/lib/models/settings/settings_activity.dart b/lib/models/settings/settings_activity.dart
new file mode 100644
index 0000000000000000000000000000000000000000..434ea010e783c23838485ca0b7c0186295803eaa
--- /dev/null
+++ b/lib/models/settings/settings_activity.dart
@@ -0,0 +1,41 @@
+import 'package:stopmotion/config/default_activity_settings.dart';
+import 'package:stopmotion/utils/tools.dart';
+
+class ActivitySettings {
+  final String movieType;
+
+  ActivitySettings({
+    required this.movieType,
+  });
+
+  static String getMovieTypeValueFromUnsafe(String movieType) {
+    if (DefaultActivitySettings.allowedMovieTypeValues.contains(movieType)) {
+      return movieType;
+    }
+
+    return DefaultActivitySettings.defaultMovieTypeValue;
+  }
+
+  factory ActivitySettings.createDefault() {
+    return ActivitySettings(
+      movieType: DefaultActivitySettings.defaultMovieTypeValue,
+    );
+  }
+
+  void dump() {
+    printlog('$ActivitySettings:');
+    printlog('  ${DefaultActivitySettings.parameterCodeMovieType}: $movieType');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$ActivitySettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultActivitySettings.parameterCodeMovieType: movieType,
+    };
+  }
+}
diff --git a/lib/models/settings/settings_global.dart b/lib/models/settings/settings_global.dart
new file mode 100644
index 0000000000000000000000000000000000000000..060d7d49a494c6ec9b1dbf01d9572d8dbe676ab6
--- /dev/null
+++ b/lib/models/settings/settings_global.dart
@@ -0,0 +1,41 @@
+import 'package:stopmotion/config/default_global_settings.dart';
+import 'package:stopmotion/utils/tools.dart';
+
+class GlobalSettings {
+  String skin;
+
+  GlobalSettings({
+    required this.skin,
+  });
+
+  static String getSkinValueFromUnsafe(String skin) {
+    if (DefaultGlobalSettings.allowedSkinValues.contains(skin)) {
+      return skin;
+    }
+
+    return DefaultGlobalSettings.defaultSkinValue;
+  }
+
+  factory GlobalSettings.createDefault() {
+    return GlobalSettings(
+      skin: DefaultGlobalSettings.defaultSkinValue,
+    );
+  }
+
+  void dump() {
+    printlog('$GlobalSettings:');
+    printlog('  ${DefaultGlobalSettings.parameterCodeSkin}: $skin');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$GlobalSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultGlobalSettings.parameterCodeSkin: skin,
+    };
+  }
+}
diff --git a/lib/ui/widgets/app_titles.dart b/lib/ui/helpers/app_titles.dart
similarity index 52%
rename from lib/ui/widgets/app_titles.dart
rename to lib/ui/helpers/app_titles.dart
index 93541243613b0f20e76485520a275d1527a6fcc9..b98107b12fabc3114ebfbec994166b588abcf1ad 100644
--- a/lib/ui/widgets/app_titles.dart
+++ b/lib/ui/helpers/app_titles.dart
@@ -1,8 +1,8 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 
-class AppTitle extends StatelessWidget {
-  const AppTitle({super.key, required this.text});
+class AppHeader extends StatelessWidget {
+  const AppHeader({super.key, required this.text});
 
   final String text;
 
@@ -11,37 +11,22 @@ class AppTitle extends StatelessWidget {
     return Text(
       tr(text),
       textAlign: TextAlign.start,
-      style: Theme.of(context).textTheme.headlineLarge!.apply(fontWeightDelta: 2),
+      style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
     );
   }
 }
 
-class AppTitle1 extends StatelessWidget {
-  const AppTitle1({super.key, required this.text});
+class AppTitle extends StatelessWidget {
+  const AppTitle({super.key, required this.text});
 
   final String text;
 
   @override
   Widget build(BuildContext context) {
     return Text(
-      text,
+      tr(text),
       textAlign: TextAlign.start,
       style: Theme.of(context).textTheme.titleLarge!.apply(fontWeightDelta: 2),
     );
   }
 }
-
-class AppTitle2 extends StatelessWidget {
-  const AppTitle2({super.key, required this.text});
-
-  final String text;
-
-  @override
-  Widget build(BuildContext context) {
-    return Text(
-      text,
-      textAlign: TextAlign.start,
-      style: Theme.of(context).textTheme.titleMedium!.apply(fontWeightDelta: 2),
-    );
-  }
-}
diff --git a/lib/ui/helpers/outlined_text_widget.dart b/lib/ui/helpers/outlined_text_widget.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e8cbb93a282c081d59cc9b0963dd9cf3554b0860
--- /dev/null
+++ b/lib/ui/helpers/outlined_text_widget.dart
@@ -0,0 +1,51 @@
+import 'package:flutter/material.dart';
+
+import 'package:stopmotion/utils/color_extensions.dart';
+
+class OutlinedText extends StatelessWidget {
+  const OutlinedText({
+    super.key,
+    required this.text,
+    required this.fontSize,
+    required this.textColor,
+    this.outlineColor,
+  });
+
+  final String text;
+  final double fontSize;
+  final Color textColor;
+  final Color? outlineColor;
+
+  @override
+  Widget build(BuildContext context) {
+    final double delta = fontSize / 30;
+
+    return Text(
+      text,
+      style: TextStyle(
+        inherit: true,
+        fontSize: fontSize,
+        fontWeight: FontWeight.w600,
+        color: textColor,
+        shadows: [
+          Shadow(
+            offset: Offset(-delta, -delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(delta, -delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(delta, delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(-delta, delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/nav/bottom_nav_bar.dart
similarity index 51%
rename from lib/ui/widgets/bottom_nav_bar.dart
rename to lib/ui/nav/bottom_nav_bar.dart
index 9ce8d67088e14107d2d8b2c3082355e5b4de322d..fb30fdec3daadf1d86a603f22ec58103d6160f77 100644
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ b/lib/ui/nav/bottom_nav_bar.dart
@@ -2,10 +2,8 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'package:stopmotion/cubit/bottom_nav_cubit.dart';
-import 'package:stopmotion/ui/screens/camera.dart';
-import 'package:stopmotion/ui/screens/settings.dart';
-import 'package:stopmotion/ui/screens/home.dart';
+import 'package:stopmotion/config/activity_page.dart';
+import 'package:stopmotion/cubit/nav_cubit_pages.dart';
 
 class BottomNavBar extends StatelessWidget {
   const BottomNavBar({super.key});
@@ -16,36 +14,35 @@ class BottomNavBar extends StatelessWidget {
       margin: const EdgeInsets.only(top: 1, right: 4, left: 4),
       elevation: 4,
       shadowColor: Theme.of(context).colorScheme.shadow,
-      color: Theme.of(context).colorScheme.surfaceVariant,
+      color: Theme.of(context).colorScheme.surfaceContainerHighest,
       shape: const RoundedRectangleBorder(
         borderRadius: BorderRadius.only(
           topLeft: Radius.circular(16),
           topRight: Radius.circular(16),
         ),
       ),
-      child: BlocBuilder<BottomNavCubit, int>(builder: (BuildContext context, int state) {
+      child: BlocBuilder<NavCubitPage, int>(builder: (BuildContext context, int state) {
+        final List<ActivityPageItem> pageItems = [
+          ActivityPage.pageHome,
+          ActivityPage.pageEditor,
+          ActivityPage.pagePlayer,
+        ];
+        final List<BottomNavigationBarItem> items = pageItems.map((ActivityPageItem item) {
+          return BottomNavigationBarItem(
+            icon: item.icon,
+            label: tr(item.code),
+          );
+        }).toList();
+
         return BottomNavigationBar(
           currentIndex: state,
-          onTap: (int index) => context.read<BottomNavCubit>().updateIndex(index),
+          onTap: (int index) => context.read<NavCubitPage>().updateIndex(index),
           type: BottomNavigationBarType.fixed,
           elevation: 0,
           backgroundColor: Colors.transparent,
           selectedItemColor: Theme.of(context).colorScheme.primary,
           unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
-          items: <BottomNavigationBarItem>[
-            BottomNavigationBarItem(
-              icon: ScreenHome.navBarIcon,
-              label: tr(ScreenHome.navBarText),
-            ),
-            BottomNavigationBarItem(
-              icon: ScreenCamera.navBarIcon,
-              label: tr(ScreenCamera.navBarText),
-            ),
-            BottomNavigationBarItem(
-              icon: ScreenSettings.navBarIcon,
-              label: tr(ScreenSettings.navBarText),
-            ),
-          ],
+          items: items,
         );
       }),
     );
diff --git a/lib/ui/nav/global_app_bar.dart b/lib/ui/nav/global_app_bar.dart
new file mode 100644
index 0000000000000000000000000000000000000000..0590d1dfaf047967ee80c1d750909f1553dc0cf8
--- /dev/null
+++ b/lib/ui/nav/global_app_bar.dart
@@ -0,0 +1,67 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:stopmotion/config/screen.dart';
+import 'package:stopmotion/cubit/activity_cubit.dart';
+import 'package:stopmotion/cubit/nav_cubit_screens.dart';
+import 'package:stopmotion/ui/helpers/app_titles.dart';
+
+class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
+  const GlobalAppBar({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<ActivityCubit, ActivityState>(
+      builder: (BuildContext context, ActivityState activityState) {
+        return BlocBuilder<NavCubitScreen, int>(
+          builder: (BuildContext context, int screenIndex) {
+            final List<Widget> menuActions = [];
+
+            if (screenIndex == Screen.indexActivity) {
+              // go to Settings page
+              menuActions.add(ElevatedButton(
+                onPressed: () {
+                  context.read<NavCubitScreen>().goToSettingsPage();
+                },
+                style: ElevatedButton.styleFrom(
+                  shape: const CircleBorder(),
+                ),
+                child: Screen.screenSettings.icon,
+              ));
+
+              // go to About page
+              menuActions.add(ElevatedButton(
+                onPressed: () {
+                  context.read<NavCubitScreen>().goToAboutPage();
+                },
+                style: ElevatedButton.styleFrom(
+                  shape: const CircleBorder(),
+                ),
+                child: Screen.screenAbout.icon,
+              ));
+            } else {
+              // back to Home page
+              menuActions.add(ElevatedButton(
+                onPressed: () {
+                  context.read<NavCubitScreen>().goToActivityPage();
+                },
+                style: ElevatedButton.styleFrom(
+                  shape: const CircleBorder(),
+                ),
+                child: Screen.screenActivity.icon,
+              ));
+            }
+
+            return AppBar(
+              title: const AppHeader(text: 'app_name'),
+              actions: menuActions,
+            );
+          },
+        );
+      },
+    );
+  }
+
+  @override
+  Size get preferredSize => const Size.fromHeight(50);
+}
diff --git a/lib/ui/pages/editor.dart b/lib/ui/pages/editor.dart
new file mode 100644
index 0000000000000000000000000000000000000000..2a0648fdbd1d3d593547e6865afe430d5674f857
--- /dev/null
+++ b/lib/ui/pages/editor.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:stopmotion/cubit/activity_cubit.dart';
+import 'package:stopmotion/ui/widgets/take_picture_widget.dart';
+
+class PageEditor extends StatelessWidget {
+  const PageEditor({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<ActivityCubit, ActivityState>(
+      builder: (BuildContext context, ActivityState activityState) {
+        return const Column(
+          mainAxisAlignment: MainAxisAlignment.start,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: <Widget>[
+            SizedBox(height: 8),
+            Text('[editor]'),
+            TakePictureWidget(),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/pages/home.dart b/lib/ui/pages/home.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ffe31c447aa85a04b6bc1a9dc0a7d92b8e96062c
--- /dev/null
+++ b/lib/ui/pages/home.dart
@@ -0,0 +1,35 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:stopmotion/cubit/activity_cubit.dart';
+import 'package:stopmotion/models/activity/activity.dart';
+import 'package:stopmotion/ui/helpers/outlined_text_widget.dart';
+import 'package:stopmotion/utils/color_extensions.dart';
+
+class PageHome extends StatelessWidget {
+  const PageHome({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<ActivityCubit, ActivityState>(
+      builder: (BuildContext context, ActivityState activityState) {
+        final Activity currentActivity = activityState.currentActivity;
+
+        return Column(
+          mainAxisAlignment: MainAxisAlignment.start,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: <Widget>[
+            const SizedBox(height: 8),
+            OutlinedText(
+              text: '[home]',
+              fontSize: 50,
+              textColor: Colors.blueAccent,
+              outlineColor: Colors.blueAccent.lighten(20),
+            ),
+            Text(currentActivity.toString()),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/pages/player.dart b/lib/ui/pages/player.dart
new file mode 100644
index 0000000000000000000000000000000000000000..5171cfc87c7e1465881c7150d9df5c81c1a8111e
--- /dev/null
+++ b/lib/ui/pages/player.dart
@@ -0,0 +1,35 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:stopmotion/cubit/activity_cubit.dart';
+import 'package:stopmotion/models/activity/activity.dart';
+import 'package:stopmotion/ui/helpers/outlined_text_widget.dart';
+import 'package:stopmotion/utils/color_extensions.dart';
+
+class PagePlayer extends StatelessWidget {
+  const PagePlayer({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<ActivityCubit, ActivityState>(
+      builder: (BuildContext context, ActivityState activityState) {
+        final Activity currentActivity = activityState.currentActivity;
+
+        return Column(
+          mainAxisAlignment: MainAxisAlignment.start,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: <Widget>[
+            const SizedBox(height: 8),
+            OutlinedText(
+              text: '[player]',
+              fontSize: 50,
+              textColor: Colors.blueAccent,
+              outlineColor: Colors.blueAccent.lighten(20),
+            ),
+            Text(currentActivity.toString()),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/screens/about.dart b/lib/ui/screens/about.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ec183f054b2c033fbc535ba80266bcb6fbcff0ba
--- /dev/null
+++ b/lib/ui/screens/about.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:stopmotion/ui/helpers/app_titles.dart';
+
+class ScreenAbout extends StatelessWidget {
+  const ScreenAbout({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 8),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.max,
+        children: <Widget>[
+          const SizedBox(height: 8),
+          const AppTitle(text: 'about_title'),
+          const Text('about_content').tr(),
+          FutureBuilder<PackageInfo>(
+            future: PackageInfo.fromPlatform(),
+            builder: (context, snapshot) {
+              switch (snapshot.connectionState) {
+                case ConnectionState.done:
+                  return const Text('about_version').tr(
+                    namedArgs: {
+                      'version': snapshot.data!.version,
+                    },
+                  );
+                default:
+                  return const SizedBox();
+              }
+            },
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/screens/activity.dart b/lib/ui/screens/activity.dart
new file mode 100644
index 0000000000000000000000000000000000000000..c4a4697a2a279942f72a2ff69773f1152c1c6d3f
--- /dev/null
+++ b/lib/ui/screens/activity.dart
@@ -0,0 +1,18 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:stopmotion/config/activity_page.dart';
+import 'package:stopmotion/cubit/nav_cubit_pages.dart';
+
+class ScreenActivity extends StatelessWidget {
+  const ScreenActivity({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<NavCubitPage, int>(
+      builder: (BuildContext context, int pageIndex) {
+        return ActivityPage.getPageWidget(pageIndex);
+      },
+    );
+  }
+}
diff --git a/lib/ui/screens/camera.dart b/lib/ui/screens/camera.dart
deleted file mode 100644
index 00278434f60bdad03f093efd3c1ea7a88c7fd8cf..0000000000000000000000000000000000000000
--- a/lib/ui/screens/camera.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:unicons/unicons.dart';
-
-import 'package:stopmotion/ui/widgets/take_picture_widget.dart';
-
-class ScreenCamera extends StatelessWidget {
-  const ScreenCamera({super.key});
-
-  static Icon navBarIcon = const Icon(UniconsLine.camera);
-  static String navBarText = 'bottom_nav_camera';
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      color: Theme.of(context).colorScheme.background,
-      child: const Column(
-        mainAxisAlignment: MainAxisAlignment.start,
-        crossAxisAlignment: CrossAxisAlignment.center,
-        children: <Widget>[
-          SizedBox(height: 8),
-          TakePictureWidget(),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/home.dart b/lib/ui/screens/home.dart
deleted file mode 100644
index c9c537457b02275095311939873152e0bfded8c3..0000000000000000000000000000000000000000
--- a/lib/ui/screens/home.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:unicons/unicons.dart';
-
-class ScreenHome extends StatelessWidget {
-  const ScreenHome({super.key});
-
-  static Icon navBarIcon = const Icon(UniconsLine.home);
-  static String navBarText = 'bottom_nav_home';
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      color: Theme.of(context).colorScheme.background,
-      child: ListView(
-        padding: const EdgeInsets.symmetric(horizontal: 4),
-        physics: const BouncingScrollPhysics(),
-        children: const <Widget>[
-          SizedBox(height: 8),
-          Text('CONTENT'),
-          SizedBox(height: 36),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/settings.dart b/lib/ui/screens/settings.dart
index db2e9214cf474767b2d5d66e89db18fde70aec42..d08b042e201531509d7d7ac81a41610b66259905 100644
--- a/lib/ui/screens/settings.dart
+++ b/lib/ui/screens/settings.dart
@@ -1,27 +1,24 @@
-import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 
-import 'package:stopmotion/ui/widgets/app_titles.dart';
-import 'package:stopmotion/ui/widgets/settings_form.dart';
-import 'package:unicons/unicons.dart';
+import 'package:stopmotion/ui/settings/settings_form.dart';
+import 'package:stopmotion/ui/helpers/app_titles.dart';
 
 class ScreenSettings extends StatelessWidget {
   const ScreenSettings({super.key});
 
-  static Icon navBarIcon = const Icon(UniconsLine.setting);
-  static String navBarText = 'bottom_nav_settings';
-
   @override
   Widget build(BuildContext context) {
-    return Material(
-      color: Theme.of(context).colorScheme.background,
-      child: ListView(
-        padding: const EdgeInsets.symmetric(horizontal: 4),
-        physics: const BouncingScrollPhysics(),
+    return const Padding(
+      padding: EdgeInsets.symmetric(horizontal: 8),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.max,
         children: <Widget>[
-          const SizedBox(height: 8),
-          AppTitle1(text: tr('settings_title')),
-          const SettingsForm(),
+          SizedBox(height: 8),
+          AppTitle(text: 'settings_title'),
+          SizedBox(height: 8),
+          SettingsForm(),
         ],
       ),
     );
diff --git a/lib/ui/settings/settings_form.dart b/lib/ui/settings/settings_form.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e9106fb751d10a80642254bc7c471bd59bd52cb3
--- /dev/null
+++ b/lib/ui/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:stopmotion/ui/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/settings/theme_card.dart b/lib/ui/settings/theme_card.dart
new file mode 100644
index 0000000000000000000000000000000000000000..74351a20082666571f8bcec4f320a74139683e55
--- /dev/null
+++ b/lib/ui/settings/theme_card.dart
@@ -0,0 +1,47 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:stopmotion/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/ui/skeleton.dart b/lib/ui/skeleton.dart
index 16d65ec2c7efc08ef3d6484b46f1c3df225945ab..8da2685aadfc2b261e682ded04aa4a38c14d9180 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -1,42 +1,37 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'package:stopmotion/cubit/bottom_nav_cubit.dart';
-import 'package:stopmotion/ui/screens/camera.dart';
-import 'package:stopmotion/ui/screens/home.dart';
-import 'package:stopmotion/ui/screens/settings.dart';
-import 'package:stopmotion/ui/widgets/app_bar.dart';
-import 'package:stopmotion/ui/widgets/bottom_nav_bar.dart';
+import 'package:stopmotion/config/screen.dart';
+import 'package:stopmotion/cubit/nav_cubit_screens.dart';
+import 'package:stopmotion/ui/nav/global_app_bar.dart';
+import 'package:stopmotion/ui/nav/bottom_nav_bar.dart';
 
-class SkeletonScreen extends StatefulWidget {
+class SkeletonScreen extends StatelessWidget {
   const SkeletonScreen({super.key});
 
-  @override
-  State<SkeletonScreen> createState() => _SkeletonScreenState();
-}
-
-class _SkeletonScreenState extends State<SkeletonScreen> {
   @override
   Widget build(BuildContext context) {
-    List<Widget> pageNavigation = <Widget>[
-      const ScreenHome(),
-      const ScreenCamera(),
-      const ScreenSettings(),
-    ];
-
-    return Scaffold(
-      appBar: const StandardAppBar(),
-      extendBodyBehindAppBar: false,
-      body: BlocBuilder<BottomNavCubit, int>(
-        builder: (BuildContext context, int state) {
-          return AnimatedSwitcher(
-            duration: const Duration(milliseconds: 300),
-            child: pageNavigation.elementAt(state),
-          );
-        },
-      ),
-      backgroundColor: Theme.of(context).colorScheme.background,
-      bottomNavigationBar: const BottomNavBar(),
+    return BlocBuilder<NavCubitScreen, int>(
+      builder: (BuildContext context, int screenIndex) {
+        return Scaffold(
+          appBar: const GlobalAppBar(),
+          extendBodyBehindAppBar: false,
+          body: Material(
+            color: Theme.of(context).colorScheme.surface,
+            child: Padding(
+              padding: const EdgeInsets.only(
+                top: 8,
+                left: 2,
+                right: 2,
+              ),
+              child: Screen.getWidget(screenIndex),
+            ),
+          ),
+          backgroundColor: Theme.of(context).colorScheme.surface,
+          bottomNavigationBar:
+              Screen.displayBottomNavBar(screenIndex) ? const BottomNavBar() : null,
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart
deleted file mode 100644
index 35094c7252b900686a3d0b3b567636740b38ac08..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/app_bar.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:stopmotion/ui/widgets/app_titles.dart';
-
-class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
-  const StandardAppBar({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return AppBar(
-      title: const AppTitle(text: 'app_name'),
-      actions: const [],
-    );
-  }
-
-  @override
-  Size get preferredSize => const Size.fromHeight(50);
-}
diff --git a/lib/ui/widgets/settings_form.dart b/lib/ui/widgets/settings_form.dart
deleted file mode 100644
index d527702b672d6d2306827910ad4cacc4cef87f57..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/settings_form.dart
+++ /dev/null
@@ -1,81 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:stopmotion/config/default_settings.dart';
-import 'package:stopmotion/cubit/settings_cubit.dart';
-import 'package:stopmotion/ui/widgets/app_titles.dart';
-
-class SettingsForm extends StatefulWidget {
-  const SettingsForm({super.key});
-
-  @override
-  State<SettingsForm> createState() => _SettingsFormState();
-}
-
-class _SettingsFormState extends State<SettingsForm> {
-  int dummyValue = DefaultSettings.defaultDummyValue;
-
-  List<bool> _selectedDummyValue = [];
-
-  @override
-  void didChangeDependencies() {
-    SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
-
-    dummyValue = settings.getDummyValue();
-
-    _selectedDummyValue =
-        DefaultSettings.allowedDummyValues.map((e) => (e == dummyValue)).toList();
-
-    super.didChangeDependencies();
-  }
-
-  @override
-  void dispose() {
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    void saveSettings() {
-      BlocProvider.of<SettingsCubit>(context).setValues(
-        dummyValue: dummyValue,
-      );
-    }
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.start,
-      mainAxisSize: MainAxisSize.max,
-      children: <Widget>[
-        const SizedBox(height: 8),
-        AppTitle2(text: tr('settings_title_global')),
-
-        // Dummy value
-        Row(
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            const Text('settings_label_dummy_value').tr(),
-            ToggleButtons(
-              onPressed: (int index) {
-                setState(() {
-                  dummyValue = DefaultSettings.allowedDummyValues[index];
-                  for (int i = 0; i < _selectedDummyValue.length; i++) {
-                    _selectedDummyValue[i] = i == index;
-                  }
-                });
-                saveSettings();
-              },
-              borderRadius: const BorderRadius.all(Radius.circular(8)),
-              constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
-              isSelected: _selectedDummyValue,
-              children:
-                  DefaultSettings.allowedDummyValues.map((e) => Text(e.toString())).toList(),
-            ),
-          ],
-        ),
-      ],
-    );
-  }
-}
diff --git a/pubspec.lock b/pubspec.lock
index 03fa8f88b17c79c6bba02eb84694453caa60e662..8c9e1fe3d069efaa7820da53174ab15e7b9adaaf 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,42 +5,50 @@ packages:
     dependency: transitive
     description:
       name: args
-      sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
+      sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
       url: "https://pub.dev"
     source: hosted
-    version: "2.4.2"
+    version: "2.5.0"
+  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
+      sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.3"
+    version: "8.1.4"
   camera:
     dependency: "direct main"
     description:
       name: camera
-      sha256: "9499cbc2e51d8eb0beadc158b288380037618ce4e30c9acbc4fae1ac3ecb5797"
+      sha256: "2170a943dcb67be2af2c6bcda8775e74b41d4c02d6a4eb10bdc832ee185c4eea"
       url: "https://pub.dev"
     source: hosted
-    version: "0.10.5+9"
-  camera_android:
+    version: "0.11.0+1"
+  camera_android_camerax:
     dependency: transitive
     description:
-      name: camera_android
-      sha256: "351429510121d179b9aac5a2e8cb525c3cd6c39f4d709c5f72dfb21726e52371"
+      name: camera_android_camerax
+      sha256: "7abb0faddbf103c59365e805ad9a30ab4d602b2eb7a8de469697945fd4a69daa"
       url: "https://pub.dev"
     source: hosted
-    version: "0.10.8+16"
+    version: "0.6.5+6"
   camera_avfoundation:
     dependency: transitive
     description:
       name: camera_avfoundation
-      sha256: "7d0763dfcbf060f56aa254a68c103210280bee9e97bbe4fdef23e257a4f70ab9"
+      sha256: "7d021e8cd30d9b71b8b92b4ad669e80af432d722d18d6aac338572754a786c15"
       url: "https://pub.dev"
     source: hosted
-    version: "0.9.14"
+    version: "0.9.16"
   camera_platform_interface:
     dependency: transitive
     description:
@@ -53,10 +61,10 @@ packages:
     dependency: transitive
     description:
       name: camera_web
-      sha256: f18ccfb33b2a7c49a52ad5aa3f07330b7422faaecbdfd9b9fe8e51182f6ad67d
+      sha256: "9e9aba2fbab77ce2472924196ff8ac4dd8f9126c4f9a3096171cd1d870d6b26c"
       url: "https://pub.dev"
     source: hosted
-    version: "0.3.2+4"
+    version: "0.3.3"
   characters:
     dependency: transitive
     description:
@@ -101,10 +109,10 @@ packages:
     dependency: "direct main"
     description:
       name: easy_localization
-      sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c
+      sha256: fa59bcdbbb911a764aa6acf96bbb6fa7a5cf8234354fc45ec1a43a0349ef0201
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.5"
+    version: "3.0.7"
   easy_logger:
     dependency: transitive
     description:
@@ -146,18 +154,18 @@ packages:
     dependency: "direct main"
     description:
       name: flutter_bloc
-      sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1"
+      sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.4"
+    version: "8.1.6"
   flutter_lints:
     dependency: "direct dev"
     description:
       name: flutter_lints
-      sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
+      sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.1"
+    version: "4.0.0"
   flutter_localizations:
     dependency: transitive
     description: flutter
@@ -167,10 +175,10 @@ packages:
     dependency: transitive
     description:
       name: flutter_plugin_android_lifecycle
-      sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da
+      sha256: c6b0b4c05c458e1c01ad9bcc14041dd7b1f6783d487be4386f793f47a8a4d03e
       url: "https://pub.dev"
     source: hosted
-    version: "2.0.17"
+    version: "2.0.20"
   flutter_web_plugins:
     dependency: transitive
     description: flutter
@@ -184,30 +192,46 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.2.3"
+  http:
+    dependency: transitive
+    description:
+      name: http
+      sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.1"
+  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"
+      sha256: af35b357739fe41728df10bec03aad422cdc725a1e702e03af9d2a41ea05160c
       url: "https://pub.dev"
     source: hosted
-    version: "9.1.4"
+    version: "9.1.5"
   intl:
     dependency: transitive
     description:
       name: intl
-      sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
+      sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
       url: "https://pub.dev"
     source: hosted
-    version: "0.18.1"
+    version: "0.19.0"
   lints:
     dependency: transitive
     description:
       name: lints
-      sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
+      sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.0"
+    version: "4.0.0"
   material_color_utilities:
     dependency: transitive
     description:
@@ -220,10 +244,10 @@ packages:
     dependency: transitive
     description:
       name: meta
-      sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
+      sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
       url: "https://pub.dev"
     source: hosted
-    version: "1.11.0"
+    version: "1.12.0"
   nested:
     dependency: transitive
     description:
@@ -232,6 +256,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.0.0"
+  package_info_plus:
+    dependency: "direct main"
+    description:
+      name: package_info_plus
+      sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0
+      url: "https://pub.dev"
+    source: hosted
+    version: "8.0.0"
+  package_info_plus_platform_interface:
+    dependency: transitive
+    description:
+      name: package_info_plus_platform_interface
+      sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.0"
   path:
     dependency: "direct main"
     description:
@@ -244,26 +284,26 @@ packages:
     dependency: "direct main"
     description:
       name: path_provider
-      sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
+      sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.2"
+    version: "2.1.3"
   path_provider_android:
     dependency: transitive
     description:
       name: path_provider_android
-      sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
+      sha256: bca87b0165ffd7cdb9cad8edd22d18d2201e886d9a9f19b4fb3452ea7df3a72a
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.6"
   path_provider_foundation:
     dependency: transitive
     description:
       name: path_provider_foundation
-      sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
+      sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.2"
+    version: "2.4.0"
   path_provider_linux:
     dependency: transitive
     description:
@@ -292,10 +332,10 @@ packages:
     dependency: transitive
     description:
       name: platform
-      sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
+      sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
       url: "https://pub.dev"
     source: hosted
-    version: "3.1.4"
+    version: "3.1.5"
   plugin_platform_interface:
     dependency: transitive
     description:
@@ -316,26 +356,26 @@ packages:
     dependency: transitive
     description:
       name: shared_preferences
-      sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
+      sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.3"
   shared_preferences_android:
     dependency: transitive
     description:
       name: shared_preferences_android
-      sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
+      sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.1"
+    version: "2.2.3"
   shared_preferences_foundation:
     dependency: transitive
     description:
       name: shared_preferences_foundation
-      sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
+      sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.5"
+    version: "2.4.0"
   shared_preferences_linux:
     dependency: transitive
     description:
@@ -373,6 +413,14 @@ 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"
   stream_transform:
     dependency: transitive
     description:
@@ -381,6 +429,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.1.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:
@@ -389,6 +445,14 @@ packages:
       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:
@@ -401,10 +465,10 @@ packages:
     dependency: "direct main"
     description:
       name: unicons
-      sha256: dbfcf93ff4d4ea19b324113857e358e4882115ab85db04417a4ba1c72b17a670
+      sha256: "1cca7462df18ff191b7e41b52f747d08854916531d1d7ab7cec0552095995206"
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.1"
+    version: "2.1.2"
   vector_math:
     dependency: transitive
     description:
@@ -417,18 +481,18 @@ packages:
     dependency: transitive
     description:
       name: web
-      sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad"
+      sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.0"
+    version: "0.5.1"
   win32:
     dependency: transitive
     description:
       name: win32
-      sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
+      sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
       url: "https://pub.dev"
     source: hosted
-    version: "5.2.0"
+    version: "5.5.1"
   xdg_directories:
     dependency: transitive
     description:
@@ -438,5 +502,5 @@ packages:
     source: hosted
     version: "1.0.4"
 sdks:
-  dart: ">=3.3.0 <4.0.0"
-  flutter: ">=3.19.0"
+  dart: ">=3.4.0 <4.0.0"
+  flutter: ">=3.22.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index c7072694801d238b5b613a59ac10a399a4bdf81b..6d5d0df0a506b04477ff181e66529cfc303ee0be 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,32 +1,36 @@
 name: stopmotion
 description: stop motion assistant
 
-publish_to: 'none'
+publish_to: "none"
 
-version: 0.0.7+7
+version: 0.0.8+8
 
 environment:
-  sdk: '^3.0.0'
+  sdk: "^3.0.0"
 
 dependencies:
   flutter:
     sdk: flutter
 
-  camera: ^0.10.5+8
+  # base
   easy_localization: ^3.0.1
   equatable: ^2.0.5
   flutter_bloc: ^8.1.1
   hive: ^2.2.3
   hydrated_bloc: ^9.0.0
-  path: ^1.8.3
-  path_provider: ^2.1.1
+  package_info_plus: ^8.0.0
+  path_provider: ^2.0.11
   unicons: ^2.1.1
 
+  # specific
+  camera: ^0.11.0+1
+  path: ^1.8.3
+
 dev_dependencies:
-  flutter_lints: ^3.0.1
+  flutter_lints: ^4.0.0
 
 flutter:
-  uses-material-design: false
+  uses-material-design: true
   assets:
     - assets/translations/
 
@@ -41,3 +45,4 @@ flutter:
           weight: 400
         - asset: assets/fonts/Nunito-Light.ttf
           weight: 300
+
diff --git a/icons/build_repository_icons.sh b/resources/app/build_application_resources.sh
similarity index 98%
rename from icons/build_repository_icons.sh
rename to resources/app/build_application_resources.sh
index 27dbe2647fe4e6d562fbd99451716d1b7d448570..6d67b8f4f9eca701d1aed7331ef41dfb0bd44f20 100755
--- a/icons/build_repository_icons.sh
+++ b/resources/app/build_application_resources.sh
@@ -6,7 +6,7 @@ command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not ins
 command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
 
 CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
-BASE_DIR="$(dirname "${CURRENT_DIR}")"
+BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")"
 
 SOURCE_ICON="${CURRENT_DIR}/icon.svg"
 SOURCE_FASTLANE="${CURRENT_DIR}/featureGraphic.svg"
diff --git a/icons/featureGraphic.svg b/resources/app/featureGraphic.svg
similarity index 100%
rename from icons/featureGraphic.svg
rename to resources/app/featureGraphic.svg
diff --git a/icons/icon.svg b/resources/app/icon.svg
similarity index 100%
rename from icons/icon.svg
rename to resources/app/icon.svg
diff --git a/resources/build_resources.sh b/resources/build_resources.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8d5848a985ed1068f6e6226379a9cedb69c3fa15
--- /dev/null
+++ b/resources/build_resources.sh
@@ -0,0 +1,6 @@
+#! /bin/bash
+
+CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+
+${CURRENT_DIR}/app/build_application_resources.sh
+