diff --git a/android/gradle.properties b/android/gradle.properties
index 9afb4c689a0bff258d2a5403ef6a41e03d7faed5..007b41f87df662638a73e32c7ad937e5b08460a6 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.48
-app.versionCode=48
+app.versionName=0.0.49
+app.versionCode=49
diff --git a/assets/translations/en.json b/assets/translations/en.json
index 4ff99c8b7a7d1ca5abdb3ee305a0a56c684e7676..8ebe491d4fcc44fa1cb1ad5f4fb3af0ee7d49817 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -22,6 +22,8 @@
   "discoveries_title": "Discoveries ({daysCount} days)",
   "discoveries_artists_title": "Artists",
   "discoveries_tracks_title": "Tracks",
+  "new_artists_title": "New artists",
+  "new_tracks_title": "New tracks",
 
   "top_artists_title": "Top artists ({daysCount} days)",
 
@@ -35,6 +37,9 @@
   "settings_label_statistics_recent_days_count": "Statistics: ",
   "settings_label_timeline_days_count": "Global timeline: ",
   "settings_label_top_artists_days_count": "Top Artists: ",
+  "settings_title_counts": "Counts: ",
+  "settings_label_new_artists_count": "New artists: ",
+  "settings_label_new_tracks_count": "New tracks: ",
 
   "settings_button_save": "Save",
 
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index bbf6d69cc6b098c4a4c61dd8de0aaab7adc8eb92..39625aecb52e201581a06a0727eff33b689daf17 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -22,6 +22,8 @@
   "discoveries_title": "Découvertes ({daysCount} jours)",
   "discoveries_artists_title": "Artistes",
   "discoveries_tracks_title": "Morceaux",
+  "new_artists_title": "Nouveaux artistes",
+  "new_tracks_title": "Nouveaux morceaux",
 
   "top_artists_title": "Top artistes ({daysCount} jours)",
 
@@ -35,6 +37,10 @@
   "settings_label_statistics_recent_days_count": "Statistiques : ",
   "settings_label_timeline_days_count": "Timeline globale : ",
   "settings_label_top_artists_days_count": "Top Artistes : ",
+  "settings_title_counts": "Nombres :",
+  "settings_label_new_artists_count": "Nouveaux artistes :",
+  "settings_label_new_tracks_count": "Nouveaux morceaux :",
+
   "settings_button_save": "Enregistrer",
 
   "MON": "LUN",
diff --git a/fastlane/metadata/android/en-US/changelogs/49.txt b/fastlane/metadata/android/en-US/changelogs/49.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d54a19ed62988600ffa2848fcb6632647d2c7110
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/49.txt
@@ -0,0 +1 @@
+Display new discovered tracks and artists.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/49.txt b/fastlane/metadata/android/fr-FR/changelogs/49.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c5f41784ffd999298dd1912d68efa9de31db8876
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/49.txt
@@ -0,0 +1 @@
+Affiche les nouveaux morceaux et artistes découverts.
diff --git a/lib/config/default_settings.dart b/lib/config/default_settings.dart
index e56460587678ed53759c14cc68e3a8ebd899e3b3..525784f01d4966e604ee67e5446e81fe5c778472 100644
--- a/lib/config/default_settings.dart
+++ b/lib/config/default_settings.dart
@@ -1,5 +1,5 @@
 class DefaultSettings {
-  static const List<int> allowedValues = [
+  static const List<int> allowedDaysCountValues = [
     7,
     14,
     21,
@@ -7,9 +7,17 @@ class DefaultSettings {
     60,
     90,
   ];
+  static const List<int> allowedCountValues = [
+    5,
+    10,
+    20,
+  ];
+
   static const int defaultDiscoveriesDaysCount = 14;
   static const int defaultDistributionDaysCount = 21;
   static const int defaultStatisticsRecentDaysCount = 21;
   static const int defaultTimelineDaysCount = 14;
   static const int defaultTopArtistsDaysCount = 14;
+  static const int defaultNewArtistsCount = 5;
+  static const int defaultNewTracksCount = 5;
 }
diff --git a/lib/cubit/data_new_artists_cubit.dart b/lib/cubit/data_new_artists_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..6ef782b5dfa4b68124f4627951df2b82d6feae44
--- /dev/null
+++ b/lib/cubit/data_new_artists_cubit.dart
@@ -0,0 +1,45 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:scrobbles/models/new_artists.dart';
+
+part 'data_new_artists_state.dart';
+
+class DataNewArtistsCubit extends HydratedCubit<DataNewArtistsState> {
+  DataNewArtistsCubit() : super(const DataNewArtistsState());
+
+  void getData(DataNewArtistsState state) {
+    emit(state);
+  }
+
+  NewArtistsData? getValue() {
+    return state.newArtists;
+  }
+
+  void update(NewArtistsData? newArtists) {
+    if ((newArtists != null) && (state.newArtists.toString() != newArtists.toString())) {
+      setValue(newArtists);
+    }
+  }
+
+  void setValue(NewArtistsData? newArtists) {
+    emit(DataNewArtistsState(
+      newArtists: newArtists,
+    ));
+  }
+
+  @override
+  DataNewArtistsState? fromJson(Map<String, dynamic> json) {
+    return DataNewArtistsState(
+      newArtists: NewArtistsData.fromJson(json['newArtists']),
+    );
+  }
+
+  @override
+  Map<String, Object?>? toJson(DataNewArtistsState state) {
+    return <String, Object?>{
+      'newArtists': state.newArtists?.toJson(),
+    };
+  }
+}
diff --git a/lib/cubit/data_new_artists_state.dart b/lib/cubit/data_new_artists_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..eb6678c624e66563b534b788f959532d545ecd00
--- /dev/null
+++ b/lib/cubit/data_new_artists_state.dart
@@ -0,0 +1,15 @@
+part of 'data_new_artists_cubit.dart';
+
+@immutable
+class DataNewArtistsState extends Equatable {
+  const DataNewArtistsState({
+    this.newArtists,
+  });
+
+  final NewArtistsData? newArtists;
+
+  @override
+  List<Object?> get props => <Object?>[
+        newArtists,
+      ];
+}
diff --git a/lib/cubit/data_new_tracks_cubit.dart b/lib/cubit/data_new_tracks_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..10923886b3f7ad976cf67a353e9855326c42bf6c
--- /dev/null
+++ b/lib/cubit/data_new_tracks_cubit.dart
@@ -0,0 +1,45 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:scrobbles/models/new_tracks.dart';
+
+part 'data_new_tracks_state.dart';
+
+class DataNewTracksCubit extends HydratedCubit<DataNewTracksState> {
+  DataNewTracksCubit() : super(const DataNewTracksState());
+
+  void getData(DataNewTracksState state) {
+    emit(state);
+  }
+
+  NewTracksData? getValue() {
+    return state.newTracks;
+  }
+
+  void update(NewTracksData? newTracks) {
+    if ((newTracks != null) && (state.newTracks.toString() != newTracks.toString())) {
+      setValue(newTracks);
+    }
+  }
+
+  void setValue(NewTracksData? newTracks) {
+    emit(DataNewTracksState(
+      newTracks: newTracks,
+    ));
+  }
+
+  @override
+  DataNewTracksState? fromJson(Map<String, dynamic> json) {
+    return DataNewTracksState(
+      newTracks: NewTracksData.fromJson(json['newTracks']),
+    );
+  }
+
+  @override
+  Map<String, Object?>? toJson(DataNewTracksState state) {
+    return <String, Object?>{
+      'newTracks': state.newTracks?.toJson(),
+    };
+  }
+}
diff --git a/lib/cubit/data_new_tracks_state.dart b/lib/cubit/data_new_tracks_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..c23abe47f1c136b5a300957f6a2abdef76fa6b3b
--- /dev/null
+++ b/lib/cubit/data_new_tracks_state.dart
@@ -0,0 +1,15 @@
+part of 'data_new_tracks_cubit.dart';
+
+@immutable
+class DataNewTracksState extends Equatable {
+  const DataNewTracksState({
+    this.newTracks,
+  });
+
+  final NewTracksData? newTracks;
+
+  @override
+  List<Object?> get props => <Object?>[
+        newTracks,
+      ];
+}
diff --git a/lib/cubit/settings_cubit.dart b/lib/cubit/settings_cubit.dart
index 5b4374aa2b8ea5ec3450d8409b7d2ee2eb9b0fec..6c86444f3d23ddd6bf3e12a466b36f496dcc26aa 100644
--- a/lib/cubit/settings_cubit.dart
+++ b/lib/cubit/settings_cubit.dart
@@ -37,6 +37,14 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
     return state.topArtistsDaysCount ?? DefaultSettings.defaultTopArtistsDaysCount;
   }
 
+  int getNewArtistsCount() {
+    return state.newArtistsCount ?? DefaultSettings.defaultNewArtistsCount;
+  }
+
+  int getNewTracksCount() {
+    return state.newTracksCount ?? DefaultSettings.defaultNewTracksCount;
+  }
+
   void setValues({
     String? username,
     String? securityToken,
@@ -45,6 +53,8 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
     int? statisticsRecentDaysCount,
     int? timelineDaysCount,
     int? topArtistsDaysCount,
+    int? newArtistsCount,
+    int? newTracksCount,
   }) {
     emit(SettingsState(
       username: username ?? state.username,
@@ -54,6 +64,8 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
       statisticsRecentDaysCount: statisticsRecentDaysCount ?? state.statisticsRecentDaysCount,
       timelineDaysCount: timelineDaysCount ?? state.timelineDaysCount,
       topArtistsDaysCount: topArtistsDaysCount ?? state.topArtistsDaysCount,
+      newArtistsCount: newArtistsCount ?? state.newArtistsCount,
+      newTracksCount: newTracksCount ?? state.newTracksCount,
     ));
   }
 
@@ -66,6 +78,8 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
     int statisticsRecentDaysCount = json['statisticsRecentDaysCount'] as int;
     int timelineDaysCount = json['timelineDaysCount'] as int;
     int topArtistsDaysCount = json['topArtistsDaysCount'] as int;
+    int newArtistsCount = json['newArtistsCount'] as int;
+    int newTracksCount = json['newTracksCount'] as int;
 
     return SettingsState(
       username: username,
@@ -75,6 +89,8 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
       statisticsRecentDaysCount: statisticsRecentDaysCount,
       timelineDaysCount: timelineDaysCount,
       topArtistsDaysCount: topArtistsDaysCount,
+      newArtistsCount: newArtistsCount,
+      newTracksCount: newTracksCount,
     );
   }
 
@@ -92,6 +108,8 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
       'timelineDaysCount': state.timelineDaysCount ?? DefaultSettings.defaultTimelineDaysCount,
       'topArtistsDaysCount':
           state.topArtistsDaysCount ?? DefaultSettings.defaultTopArtistsDaysCount,
+      'newArtistsCount': state.newArtistsCount ?? DefaultSettings.defaultNewArtistsCount,
+      'newTracksCount': state.newTracksCount ?? DefaultSettings.defaultNewTracksCount,
     };
   }
 }
diff --git a/lib/cubit/settings_state.dart b/lib/cubit/settings_state.dart
index 46d965ebf1aa732b6bc6dff235c0451a8f95ba00..45ef6bb4eb11e57efbc584c77f3a311fe9090a7e 100644
--- a/lib/cubit/settings_state.dart
+++ b/lib/cubit/settings_state.dart
@@ -10,6 +10,8 @@ class SettingsState extends Equatable {
     this.statisticsRecentDaysCount,
     this.timelineDaysCount,
     this.topArtistsDaysCount,
+    this.newArtistsCount,
+    this.newTracksCount,
   });
 
   final String? username;
@@ -19,6 +21,8 @@ class SettingsState extends Equatable {
   final int? statisticsRecentDaysCount;
   final int? timelineDaysCount;
   final int? topArtistsDaysCount;
+  final int? newArtistsCount;
+  final int? newTracksCount;
 
   @override
   List<dynamic> get props => <dynamic>[
@@ -29,6 +33,8 @@ class SettingsState extends Equatable {
         statisticsRecentDaysCount,
         timelineDaysCount,
         topArtistsDaysCount,
+        newArtistsCount,
+        newTracksCount,
       ];
 
   Map<String, dynamic> get values => <String, dynamic>{
@@ -39,5 +45,7 @@ class SettingsState extends Equatable {
         'statisticsRecentDaysCount': statisticsRecentDaysCount,
         'timelineDaysCount': timelineDaysCount,
         'topArtistsDaysCount': topArtistsDaysCount,
+        'newArtistsCount': newArtistsCount,
+        'newTracksCount': newTracksCount,
       };
 }
diff --git a/lib/main.dart b/lib/main.dart
index d5123a18c168b1c89afbbea128aa1a11e5924935..6d990ff5759cfe2e6942e40f2ea6045ef2d49e0f 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -13,6 +13,8 @@ import 'package:scrobbles/cubit/data_counts_by_day_cubit.dart';
 import 'package:scrobbles/cubit/data_counts_by_hour_cubit.dart';
 import 'package:scrobbles/cubit/data_discoveries_cubit.dart';
 import 'package:scrobbles/cubit/data_heatmap_cubit.dart';
+import 'package:scrobbles/cubit/data_new_artists_cubit.dart';
+import 'package:scrobbles/cubit/data_new_tracks_cubit.dart';
 import 'package:scrobbles/cubit/data_statistics_global_cubit.dart';
 import 'package:scrobbles/cubit/data_statistics_recent_cubit.dart';
 import 'package:scrobbles/cubit/data_timeline_cubit.dart';
@@ -57,6 +59,8 @@ class MyApp extends StatelessWidget {
         BlocProvider<DataCountsByHourCubit>(create: (context) => DataCountsByHourCubit()),
         BlocProvider<DataDiscoveriesCubit>(create: (context) => DataDiscoveriesCubit()),
         BlocProvider<DataHeatmapCubit>(create: (context) => DataHeatmapCubit()),
+        BlocProvider<DataNewArtistsCubit>(create: (context) => DataNewArtistsCubit()),
+        BlocProvider<DataNewTracksCubit>(create: (context) => DataNewTracksCubit()),
         BlocProvider<DataStatisticsGlobalCubit>(
             create: (context) => DataStatisticsGlobalCubit()),
         BlocProvider<DataStatisticsRecentCubit>(
diff --git a/lib/models/artists.dart b/lib/models/artists.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e9eaf5e698f862823478523ffd36ec28f9964dca
--- /dev/null
+++ b/lib/models/artists.dart
@@ -0,0 +1,33 @@
+import 'dart:convert';
+
+class Artist {
+  final int id;
+  final String name;
+  final String mbid;
+
+  const Artist({
+    required this.id,
+    required this.name,
+    required this.mbid,
+  });
+
+  factory Artist.fromJson(Map<String, dynamic> json) {
+    return Artist(
+      id: json['id'] as int,
+      name: json['name'] as String,
+      mbid: (json['mbid'] != null) ? (json['mbid'] as String) : '',
+    );
+  }
+
+  Map<String, Object?>? toJson() {
+    return {
+      'id': this.id,
+      'name': this.name,
+      'mbid': this.mbid,
+    };
+  }
+
+  String toString() {
+    return jsonEncode(this.toJson());
+  }
+}
diff --git a/lib/models/new_artists.dart b/lib/models/new_artists.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d0c4b6a69fab06b76f570cb9f711066147421fde
--- /dev/null
+++ b/lib/models/new_artists.dart
@@ -0,0 +1,61 @@
+import 'dart:convert';
+
+import 'package:scrobbles/models/artists.dart';
+
+class NewArtistData {
+  final DateTime? firstPlayed;
+  final Artist? artist;
+
+  const NewArtistData({
+    required this.firstPlayed,
+    required this.artist,
+  });
+
+  factory NewArtistData.fromJson(Map<String, dynamic>? json) {
+    return NewArtistData(
+      firstPlayed: (json?['firstPlayed'] != null && json?['firstPlayed']['date'] != null)
+          ? DateTime.parse(
+              json?['firstPlayed']['date'],
+            )
+          : null,
+      artist: Artist.fromJson(json?['artist']),
+    );
+  }
+}
+
+class NewArtistsData {
+  final List<NewArtistData> data;
+
+  const NewArtistsData({
+    required this.data,
+  });
+
+  factory NewArtistsData.fromJson(List<dynamic>? json) {
+    List<NewArtistData> list = [];
+
+    json?.forEach((item) {
+      list.add(NewArtistData.fromJson(item));
+    });
+
+    return NewArtistsData(data: list);
+  }
+
+  List<Map<String, dynamic>> toJson() {
+    List<Map<String, dynamic>> list = [];
+
+    this.data.forEach((item) {
+      list.add({
+        'firstPlayed': {
+          'date': item.firstPlayed != null ? item.firstPlayed.toString() : null,
+        },
+        'artist': item.artist?.toJson(),
+      });
+    });
+
+    return list;
+  }
+
+  String toString() {
+    return jsonEncode(this.toJson());
+  }
+}
diff --git a/lib/models/new_tracks.dart b/lib/models/new_tracks.dart
new file mode 100644
index 0000000000000000000000000000000000000000..101c4334df229ba85c56aa03a38ca5477af49c0e
--- /dev/null
+++ b/lib/models/new_tracks.dart
@@ -0,0 +1,61 @@
+import 'dart:convert';
+
+import 'package:scrobbles/models/track.dart';
+
+class NewTrackData {
+  final DateTime? firstPlayed;
+  final Track? track;
+
+  const NewTrackData({
+    required this.firstPlayed,
+    required this.track,
+  });
+
+  factory NewTrackData.fromJson(Map<String, dynamic>? json) {
+    return NewTrackData(
+      firstPlayed: (json?['firstPlayed'] != null && json?['firstPlayed']['date'] != null)
+          ? DateTime.parse(
+              json?['firstPlayed']['date'],
+            )
+          : null,
+      track: Track.fromJson(json?['track']),
+    );
+  }
+}
+
+class NewTracksData {
+  final List<NewTrackData> data;
+
+  const NewTracksData({
+    required this.data,
+  });
+
+  factory NewTracksData.fromJson(List<dynamic>? json) {
+    List<NewTrackData> list = [];
+
+    json?.forEach((item) {
+      list.add(NewTrackData.fromJson(item));
+    });
+
+    return NewTracksData(data: list);
+  }
+
+  List<Map<String, dynamic>> toJson() {
+    List<Map<String, dynamic>> list = [];
+
+    this.data.forEach((item) {
+      list.add({
+        'firstPlayed': {
+          'date': item.firstPlayed != null ? item.firstPlayed.toString() : null,
+        },
+        'track': item.track?.toJson(),
+      });
+    });
+
+    return list;
+  }
+
+  String toString() {
+    return jsonEncode(this.toJson());
+  }
+}
diff --git a/lib/models/track.dart b/lib/models/track.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4630b88d7bfe0abe2ecb27205a40f12d1fddecc7
--- /dev/null
+++ b/lib/models/track.dart
@@ -0,0 +1,39 @@
+import 'dart:convert';
+
+import 'package:scrobbles/models/artists.dart';
+
+class Track {
+  final int id;
+  final String name;
+  final String mbid;
+  final Artist artist;
+
+  const Track({
+    required this.id,
+    required this.name,
+    required this.mbid,
+    required this.artist,
+  });
+
+  factory Track.fromJson(Map<String, dynamic> json) {
+    return Track(
+      id: json['id'] as int,
+      name: json['name'] as String,
+      mbid: (json['mbid'] != null) ? (json['mbid'] as String) : '',
+      artist: Artist.fromJson(json['artist']),
+    );
+  }
+
+  Map<String, Object?>? toJson() {
+    return {
+      'id': this.id,
+      'name': this.name,
+      'mbid': this.mbid,
+      'artist': this.artist.toJson(),
+    };
+  }
+
+  String toString() {
+    return jsonEncode(this.toJson());
+  }
+}
diff --git a/lib/network/scrobbles.dart b/lib/network/scrobbles.dart
index 7f5c6f96f0276d7386147cf6197b34fd29ad1f27..3e58697bf0d9651ab06cf9d8a11c57d01ad00589 100644
--- a/lib/network/scrobbles.dart
+++ b/lib/network/scrobbles.dart
@@ -5,6 +5,8 @@ import 'package:scrobbles/models/counts_by_day.dart';
 import 'package:scrobbles/models/counts_by_hour.dart';
 import 'package:scrobbles/models/discoveries.dart';
 import 'package:scrobbles/models/heatmap.dart';
+import 'package:scrobbles/models/new_artists.dart';
+import 'package:scrobbles/models/new_tracks.dart';
 import 'package:scrobbles/models/statistics_global.dart';
 import 'package:scrobbles/models/statistics_recent.dart';
 import 'package:scrobbles/models/timeline.dart';
@@ -100,4 +102,26 @@ class ScrobblesApi {
       throw Exception('Failed to get data from API.');
     }
   }
+
+  static Future<NewArtistsData> fetchNewArtists(int count) async {
+    final String url = baseUrl + '/data/discoveries/artists/' + count.toString();
+    final response = await http.get(Uri.parse(url));
+
+    if (response.statusCode == 200) {
+      return NewArtistsData.fromJson(jsonDecode(response.body) as List<dynamic>);
+    } else {
+      throw Exception('Failed to get data from API.');
+    }
+  }
+
+  static Future<NewTracksData> fetchNewTracks(int count) async {
+    final String url = baseUrl + '/data/discoveries/tracks/' + count.toString();
+    final response = await http.get(Uri.parse(url));
+
+    if (response.statusCode == 200) {
+      return NewTracksData.fromJson(jsonDecode(response.body) as List<dynamic>);
+    } else {
+      throw Exception('Failed to get data from API.');
+    }
+  }
 }
diff --git a/lib/ui/screens/discoveries.dart b/lib/ui/screens/discoveries.dart
index 7a039c7d5327bfc62679f1929e255fd5bb825b10..c30be6637b78d07536fe9747f953f49d247644d8 100644
--- a/lib/ui/screens/discoveries.dart
+++ b/lib/ui/screens/discoveries.dart
@@ -1,6 +1,8 @@
 import 'package:flutter/material.dart';
 
 import 'package:scrobbles/ui/widgets/cards/discoveries.dart';
+import 'package:scrobbles/ui/widgets/cards/new_artists.dart';
+import 'package:scrobbles/ui/widgets/cards/new_tracks.dart';
 
 class ScreenDiscoveries extends StatelessWidget {
   final Function() notifyParent;
@@ -21,6 +23,10 @@ class ScreenDiscoveries extends StatelessWidget {
           children: <Widget>[
             const SizedBox(height: 8),
             const CardDiscoveries(),
+            const SizedBox(height: 6),
+            const CardNewArtists(),
+            const SizedBox(height: 6),
+            const CardNewTracks(),
             const SizedBox(height: 36),
           ],
         ),
diff --git a/lib/ui/widgets/cards/new_artists.dart b/lib/ui/widgets/cards/new_artists.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d9e898b94a66112dbc51842f983f636f32304940
--- /dev/null
+++ b/lib/ui/widgets/cards/new_artists.dart
@@ -0,0 +1,63 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:scrobbles/cubit/data_new_artists_cubit.dart';
+import 'package:scrobbles/cubit/settings_cubit.dart';
+import 'package:scrobbles/models/new_artists.dart';
+import 'package:scrobbles/network/scrobbles.dart';
+import 'package:scrobbles/ui/widgets/card_content.dart';
+import 'package:scrobbles/ui/widgets/error.dart';
+
+class CardNewArtists extends StatelessWidget {
+  const CardNewArtists({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
+
+    final int count = settings.getNewArtistsCount();
+
+    return BlocBuilder<DataNewArtistsCubit, DataNewArtistsState>(
+      builder: (BuildContext context, DataNewArtistsState state) {
+        return CardContent(
+          color: Theme.of(context).colorScheme.surface,
+          title: 'new_artists_title'.tr(),
+          loader: update(count),
+          content: Column(
+            mainAxisAlignment: MainAxisAlignment.start,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: state.newArtists?.data
+                    .map((newArtist) => Text(newArtist.artist?.name ?? ''))
+                    .toList() ??
+                [],
+          ),
+        );
+      },
+    );
+  }
+
+  Widget update(int count) {
+    final Widget loading = const Text('⏳');
+    final Widget done = const Text('');
+
+    late Future<NewArtistsData> future = ScrobblesApi.fetchNewArtists(count);
+
+    return BlocBuilder<DataNewArtistsCubit, DataNewArtistsState>(
+      builder: (BuildContext context, DataNewArtistsState state) {
+        return FutureBuilder<NewArtistsData>(
+          future: future,
+          builder: (context, snapshot) {
+            if (snapshot.hasError) {
+              return ShowErrorWidget(message: '${snapshot.error}');
+            }
+
+            BlocProvider.of<DataNewArtistsCubit>(context).update(snapshot.data);
+
+            return !snapshot.hasData ? loading : done;
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/cards/new_tracks.dart b/lib/ui/widgets/cards/new_tracks.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d2bcc0baa35f28f3e908276621d61b9234a521eb
--- /dev/null
+++ b/lib/ui/widgets/cards/new_tracks.dart
@@ -0,0 +1,65 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:scrobbles/cubit/data_new_tracks_cubit.dart';
+import 'package:scrobbles/cubit/settings_cubit.dart';
+import 'package:scrobbles/models/new_tracks.dart';
+import 'package:scrobbles/network/scrobbles.dart';
+import 'package:scrobbles/ui/widgets/card_content.dart';
+import 'package:scrobbles/ui/widgets/error.dart';
+
+class CardNewTracks extends StatelessWidget {
+  const CardNewTracks({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
+
+    final int count = settings.getNewTracksCount();
+
+    return BlocBuilder<DataNewTracksCubit, DataNewTracksState>(
+      builder: (BuildContext context, DataNewTracksState state) {
+        return CardContent(
+          color: Theme.of(context).colorScheme.surface,
+          title: 'new_tracks_title'.tr(),
+          loader: update(count),
+          content: Column(
+            mainAxisAlignment: MainAxisAlignment.start,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: state.newTracks?.data
+                    .map((newTrack) => Text((newTrack.track?.artist.name ?? '') +
+                        ' - ' +
+                        (newTrack.track?.name ?? '')))
+                    .toList() ??
+                [],
+          ),
+        );
+      },
+    );
+  }
+
+  Widget update(int count) {
+    final Widget loading = const Text('⏳');
+    final Widget done = const Text('');
+
+    late Future<NewTracksData> future = ScrobblesApi.fetchNewTracks(count);
+
+    return BlocBuilder<DataNewTracksCubit, DataNewTracksState>(
+      builder: (BuildContext context, DataNewTracksState state) {
+        return FutureBuilder<NewTracksData>(
+          future: future,
+          builder: (context, snapshot) {
+            if (snapshot.hasError) {
+              return ShowErrorWidget(message: '${snapshot.error}');
+            }
+
+            BlocProvider.of<DataNewTracksCubit>(context).update(snapshot.data);
+
+            return !snapshot.hasData ? loading : done;
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/settings_form.dart b/lib/ui/widgets/settings_form.dart
index aad22f578a877733d717d2ece111b6ca1fe94b0b..de09c91d03229cc7082e0bc8a7d7709419d4f915 100644
--- a/lib/ui/widgets/settings_form.dart
+++ b/lib/ui/widgets/settings_form.dart
@@ -23,12 +23,16 @@ class _SettingsFormState extends State<SettingsForm> {
   int statisticsRecentDaysCount = DefaultSettings.defaultStatisticsRecentDaysCount;
   int timelineDaysCount = DefaultSettings.defaultTimelineDaysCount;
   int topArtistsDaysCount = DefaultSettings.defaultTopArtistsDaysCount;
+  int newArtistsCount = DefaultSettings.defaultNewArtistsCount;
+  int newTracksCount = DefaultSettings.defaultNewTracksCount;
 
   List<bool> _selectedDiscoveriesDaysCount = [];
   List<bool> _selectedDistributionDaysCount = [];
   List<bool> _selectedStatisticsRecentDaysCount = [];
   List<bool> _selectedTimelineDaysCount = [];
   List<bool> _selectedTopArtistsDaysCount = [];
+  List<bool> _selectedNewArtistsCount = [];
+  List<bool> _selectedNewTracksCount = [];
 
   @override
   void didChangeDependencies() {
@@ -42,17 +46,26 @@ class _SettingsFormState extends State<SettingsForm> {
     statisticsRecentDaysCount = settings.getStatisticsRecentDaysCount();
     timelineDaysCount = settings.getTimelineDaysCount();
     topArtistsDaysCount = settings.getTopArtistsDaysCount();
+    newArtistsCount = settings.getNewArtistsCount();
+    newTracksCount = settings.getNewTracksCount();
 
-    _selectedDiscoveriesDaysCount =
-        DefaultSettings.allowedValues.map((e) => (e == discoveriesDaysCount)).toList();
-    _selectedDistributionDaysCount =
-        DefaultSettings.allowedValues.map((e) => (e == distributionDaysCount)).toList();
-    _selectedStatisticsRecentDaysCount =
-        DefaultSettings.allowedValues.map((e) => (e == statisticsRecentDaysCount)).toList();
+    _selectedDiscoveriesDaysCount = DefaultSettings.allowedDaysCountValues
+        .map((e) => (e == discoveriesDaysCount))
+        .toList();
+    _selectedDistributionDaysCount = DefaultSettings.allowedDaysCountValues
+        .map((e) => (e == distributionDaysCount))
+        .toList();
+    _selectedStatisticsRecentDaysCount = DefaultSettings.allowedDaysCountValues
+        .map((e) => (e == statisticsRecentDaysCount))
+        .toList();
     _selectedTimelineDaysCount =
-        DefaultSettings.allowedValues.map((e) => (e == timelineDaysCount)).toList();
+        DefaultSettings.allowedDaysCountValues.map((e) => (e == timelineDaysCount)).toList();
     _selectedTopArtistsDaysCount =
-        DefaultSettings.allowedValues.map((e) => (e == topArtistsDaysCount)).toList();
+        DefaultSettings.allowedDaysCountValues.map((e) => (e == topArtistsDaysCount)).toList();
+    _selectedNewArtistsCount =
+        DefaultSettings.allowedCountValues.map((e) => (e == newArtistsCount)).toList();
+    _selectedNewTracksCount =
+        DefaultSettings.allowedCountValues.map((e) => (e == newTracksCount)).toList();
 
     super.didChangeDependencies();
   }
@@ -75,6 +88,8 @@ class _SettingsFormState extends State<SettingsForm> {
         statisticsRecentDaysCount: statisticsRecentDaysCount,
         timelineDaysCount: timelineDaysCount,
         topArtistsDaysCount: topArtistsDaysCount,
+        newArtistsCount: newArtistsCount,
+        newTracksCount: newTracksCount,
       );
     }
 
@@ -118,7 +133,7 @@ class _SettingsFormState extends State<SettingsForm> {
             ToggleButtons(
               onPressed: (int index) {
                 setState(() {
-                  statisticsRecentDaysCount = DefaultSettings.allowedValues[index];
+                  statisticsRecentDaysCount = DefaultSettings.allowedDaysCountValues[index];
                   for (int i = 0; i < _selectedStatisticsRecentDaysCount.length; i++) {
                     _selectedStatisticsRecentDaysCount[i] = i == index;
                   }
@@ -128,7 +143,9 @@ class _SettingsFormState extends State<SettingsForm> {
               borderRadius: const BorderRadius.all(Radius.circular(8)),
               constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
               isSelected: _selectedStatisticsRecentDaysCount,
-              children: DefaultSettings.allowedValues.map((e) => Text(e.toString())).toList(),
+              children: DefaultSettings.allowedDaysCountValues
+                  .map((e) => Text(e.toString()))
+                  .toList(),
             ),
           ],
         ),
@@ -142,7 +159,7 @@ class _SettingsFormState extends State<SettingsForm> {
             ToggleButtons(
               onPressed: (int index) {
                 setState(() {
-                  timelineDaysCount = DefaultSettings.allowedValues[index];
+                  timelineDaysCount = DefaultSettings.allowedDaysCountValues[index];
                   for (int i = 0; i < _selectedTimelineDaysCount.length; i++) {
                     _selectedTimelineDaysCount[i] = i == index;
                   }
@@ -152,7 +169,9 @@ class _SettingsFormState extends State<SettingsForm> {
               borderRadius: const BorderRadius.all(Radius.circular(8)),
               constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
               isSelected: _selectedTimelineDaysCount,
-              children: DefaultSettings.allowedValues.map((e) => Text(e.toString())).toList(),
+              children: DefaultSettings.allowedDaysCountValues
+                  .map((e) => Text(e.toString()))
+                  .toList(),
             ),
           ],
         ),
@@ -166,7 +185,7 @@ class _SettingsFormState extends State<SettingsForm> {
             ToggleButtons(
               onPressed: (int index) {
                 setState(() {
-                  topArtistsDaysCount = DefaultSettings.allowedValues[index];
+                  topArtistsDaysCount = DefaultSettings.allowedDaysCountValues[index];
                   for (int i = 0; i < _selectedTopArtistsDaysCount.length; i++) {
                     _selectedTopArtistsDaysCount[i] = i == index;
                   }
@@ -176,7 +195,9 @@ class _SettingsFormState extends State<SettingsForm> {
               borderRadius: const BorderRadius.all(Radius.circular(8)),
               constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
               isSelected: _selectedTopArtistsDaysCount,
-              children: DefaultSettings.allowedValues.map((e) => Text(e.toString())).toList(),
+              children: DefaultSettings.allowedDaysCountValues
+                  .map((e) => Text(e.toString()))
+                  .toList(),
             ),
           ],
         ),
@@ -190,7 +211,7 @@ class _SettingsFormState extends State<SettingsForm> {
             ToggleButtons(
               onPressed: (int index) {
                 setState(() {
-                  discoveriesDaysCount = DefaultSettings.allowedValues[index];
+                  discoveriesDaysCount = DefaultSettings.allowedDaysCountValues[index];
                   for (int i = 0; i < _selectedDiscoveriesDaysCount.length; i++) {
                     _selectedDiscoveriesDaysCount[i] = i == index;
                   }
@@ -200,7 +221,9 @@ class _SettingsFormState extends State<SettingsForm> {
               borderRadius: const BorderRadius.all(Radius.circular(8)),
               constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
               isSelected: _selectedDiscoveriesDaysCount,
-              children: DefaultSettings.allowedValues.map((e) => Text(e.toString())).toList(),
+              children: DefaultSettings.allowedDaysCountValues
+                  .map((e) => Text(e.toString()))
+                  .toList(),
             ),
           ],
         ),
@@ -214,7 +237,7 @@ class _SettingsFormState extends State<SettingsForm> {
             ToggleButtons(
               onPressed: (int index) {
                 setState(() {
-                  distributionDaysCount = DefaultSettings.allowedValues[index];
+                  distributionDaysCount = DefaultSettings.allowedDaysCountValues[index];
                   for (int i = 0; i < _selectedDistributionDaysCount.length; i++) {
                     _selectedDistributionDaysCount[i] = i == index;
                   }
@@ -224,7 +247,62 @@ class _SettingsFormState extends State<SettingsForm> {
               borderRadius: const BorderRadius.all(Radius.circular(8)),
               constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
               isSelected: _selectedDistributionDaysCount,
-              children: DefaultSettings.allowedValues.map((e) => Text(e.toString())).toList(),
+              children: DefaultSettings.allowedDaysCountValues
+                  .map((e) => Text(e.toString()))
+                  .toList(),
+            ),
+          ],
+        ),
+
+        SizedBox(height: 8),
+        AppTitle2(text: tr('settings_title_counts')),
+
+        // New artists count
+        Row(
+          mainAxisAlignment: MainAxisAlignment.end,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            Text('settings_label_new_artists_count').tr(),
+            ToggleButtons(
+              onPressed: (int index) {
+                setState(() {
+                  newArtistsCount = DefaultSettings.allowedCountValues[index];
+                  for (int i = 0; i < _selectedNewArtistsCount.length; i++) {
+                    _selectedNewArtistsCount[i] = i == index;
+                  }
+                });
+                saveSettings();
+              },
+              borderRadius: const BorderRadius.all(Radius.circular(8)),
+              constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
+              isSelected: _selectedNewArtistsCount,
+              children:
+                  DefaultSettings.allowedCountValues.map((e) => Text(e.toString())).toList(),
+            ),
+          ],
+        ),
+
+        // New tracks count
+        Row(
+          mainAxisAlignment: MainAxisAlignment.end,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            Text('settings_label_new_tracks_count').tr(),
+            ToggleButtons(
+              onPressed: (int index) {
+                setState(() {
+                  newTracksCount = DefaultSettings.allowedCountValues[index];
+                  for (int i = 0; i < _selectedNewTracksCount.length; i++) {
+                    _selectedNewTracksCount[i] = i == index;
+                  }
+                });
+                saveSettings();
+              },
+              borderRadius: const BorderRadius.all(Radius.circular(8)),
+              constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
+              isSelected: _selectedNewTracksCount,
+              children:
+                  DefaultSettings.allowedCountValues.map((e) => Text(e.toString())).toList(),
             ),
           ],
         ),
diff --git a/pubspec.yaml b/pubspec.yaml
index 2e058f8862eb87b6a01af482cd28233cd5ec3c3d..bb7e9233bab3fc8a013aed2ed4fa7332bd6651ac 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: Display scrobbles data and charts
 
 publish_to: 'none'
 
-version: 0.0.48+48
+version: 0.0.49+49
 
 environment:
   sdk: '^3.0.0'