diff --git a/android/gradle.properties b/android/gradle.properties
index 135006f9c1386c8757595c43e890e911f732f5a3..85b94f88ee157e1d1b3cec184c8948902443d36f 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.6
-app.versionCode=6
+app.versionName=0.0.7
+app.versionCode=7
diff --git a/assets/translations/en.json b/assets/translations/en.json
index 31c1591ed59c198141087871b3ed62adb9be4c49..179e72fda547299ecd00d8e23f5e484972e8bcbf 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -6,5 +6,7 @@
   "statistics_last_scrobble": "Last scrobble: {datetime}",
   "statistics_selected_period": "On last {daysCount} days:",
   "statistics_recent_scrobbles_count": "Scrobbles: {count}",
-  "statistics_discoveries": "Discoveries: {artistsCount} artists / {tracksCount} tracks"
+  "statistics_discoveries": "Discoveries: {artistsCount} artists / {tracksCount} tracks",
+
+  "timeline_title": "Recent scrobbles ({daysCount} days)"
 }
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index e1594f241cbdbce2d95c48c582aefe5e038900c5..064f98c9200cedb03f3816b00db07589ac1910e5 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -6,5 +6,7 @@
   "statistics_last_scrobble": "Dernière écoute : {datetime}",
   "statistics_selected_period": "Sur les {daysCount} derniers jours:",
   "statistics_recent_scrobbles_count": "Écoutes : {count}",
-  "statistics_discoveries": "Découvertes : {artistsCount} artistes / {tracksCount} morceaux"
+  "statistics_discoveries": "Découvertes : {artistsCount} artistes / {tracksCount} morceaux",
+
+  "timeline_title": "Écoutes récentes ({daysCount} jours)"
 }
diff --git a/fastlane/metadata/android/en-US/changelogs/7.txt b/fastlane/metadata/android/en-US/changelogs/7.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2dbc251e1072618129a60896eda44c63f551bd6a
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/7.txt
@@ -0,0 +1 @@
+Add scrobbles counts main chart.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/7.txt b/fastlane/metadata/android/fr-FR/changelogs/7.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9f2a817ba94b0953732751034190158701bfbd58
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/7.txt
@@ -0,0 +1 @@
+Ajout du graphique principal de compteur d'écoutes.
diff --git a/lib/config/app_colors.dart b/lib/config/app_colors.dart
new file mode 100644
index 0000000000000000000000000000000000000000..a1ca589a1cef364687bbb2ee76e4073ce17ea650
--- /dev/null
+++ b/lib/config/app_colors.dart
@@ -0,0 +1,25 @@
+import 'package:flutter/material.dart';
+
+class AppColors {
+  static const Color primary = contentColorCyan;
+  static const Color menuBackground = Color(0xFF090912);
+  static const Color itemsBackground = Color(0xFF1B2339);
+  static const Color pageBackground = Color(0xFF282E45);
+  static const Color mainTextColor1 = Colors.white;
+  static const Color mainTextColor2 = Colors.white70;
+  static const Color mainTextColor3 = Colors.white38;
+  static const Color mainGridLineColor = Colors.white10;
+  static const Color borderColor = Colors.white54;
+  static const Color gridLinesColor = Color(0x11FFFFFF);
+
+  static const Color contentColorBlack = Colors.black;
+  static const Color contentColorWhite = Colors.white;
+  static const Color contentColorBlue = Color(0xFF2196F3);
+  static const Color contentColorYellow = Color(0xFFFFC300);
+  static const Color contentColorOrange = Color(0xFFFF683B);
+  static const Color contentColorGreen = Color(0xFF3BFF49);
+  static const Color contentColorPurple = Color(0xFF6E1BFF);
+  static const Color contentColorPink = Color(0xFFFF3AF2);
+  static const Color contentColorRed = Color(0xFFE80054);
+  static const Color contentColorCyan = Color(0xFF50E4FF);
+}
diff --git a/lib/models/timeline.dart b/lib/models/timeline.dart
new file mode 100644
index 0000000000000000000000000000000000000000..15042338609249c93bf68f395d11f0bba4c68838
--- /dev/null
+++ b/lib/models/timeline.dart
@@ -0,0 +1,56 @@
+import 'dart:convert';
+
+class TimelineDataValue {
+  final int counts;
+  final int eclecticism;
+
+  const TimelineDataValue({required this.counts, required this.eclecticism});
+
+  factory TimelineDataValue.fromJson(Map<String, dynamic> json) {
+    return TimelineDataValue(
+      counts: json['counts'] as int,
+      eclecticism: json['eclecticism'] as int,
+    );
+  }
+}
+
+class TimelineData {
+  final Map<String, TimelineDataValue> data;
+
+  const TimelineData({
+    required this.data,
+  });
+
+  factory TimelineData.fromJson(Map<String, dynamic> json) {
+    Map<String, TimelineDataValue> data = {};
+
+    json.keys.forEach((date) {
+      TimelineDataValue value = TimelineDataValue(
+        counts: json[date]['counts'] as int,
+        eclecticism: json[date]['eclecticism'] as int,
+      );
+
+      data[date] = value;
+    });
+
+    return TimelineData(data: data);
+  }
+
+  factory TimelineData.createEmpty() {
+    return TimelineData.fromJson({});
+  }
+
+  String toString() {
+    Map<String, Map<String, int>> map = {};
+
+    this.data.keys.forEach((element) {
+      TimelineDataValue? item = this.data[element];
+      map[element] = {
+        'counts': item != null ? item.counts : 0,
+        'eclecticism': item != null ? item.eclecticism : 0,
+      };
+    });
+
+    return jsonEncode(map);
+  }
+}
diff --git a/lib/network/scrobbles_api.dart b/lib/network/scrobbles_api.dart
index 102a8175f7436126cbc1c1e6a8860482ec363b21..64017d096c4c2b6f802b5bef01a5506400ee427d 100644
--- a/lib/network/scrobbles_api.dart
+++ b/lib/network/scrobbles_api.dart
@@ -2,6 +2,7 @@ import 'dart:convert';
 import 'package:http/http.dart' as http;
 
 import '../models/statistics.dart';
+import '../models/timeline.dart';
 
 class ScrobblesApi {
   static String baseUrl = 'https://scrobble.harrault.fr';
@@ -15,4 +16,15 @@ class ScrobblesApi {
       throw Exception('Failed to get data from API.');
     }
   }
+
+  static Future<TimelineData> fetchTimeline(int daysCount) async {
+    final String url = baseUrl + '/data/' + daysCount.toString() + '/timeline';
+    final response = await http.get(Uri.parse(url));
+
+    if (response.statusCode == 200) {
+      return TimelineData.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
+    } else {
+      throw Exception('Failed to get data from API.');
+    }
+  }
 }
diff --git a/lib/ui/screens/main_screen.dart b/lib/ui/screens/main_screen.dart
index 94275cada3765bcf94b20b710fec33ad35a632a9..17f0fb5a39dad07eae8f664e4385abd39fc163d9 100644
--- a/lib/ui/screens/main_screen.dart
+++ b/lib/ui/screens/main_screen.dart
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
 
 import '../widgets/header.dart';
 import '../widgets/main_screen/statistics_card.dart';
+import '../widgets/main_screen/timeline_card.dart';
 
 class MainScreen extends StatelessWidget {
   const MainScreen({super.key});
@@ -16,6 +17,8 @@ class MainScreen extends StatelessWidget {
         children: <Widget>[
           const Header(text: 'app_name'),
           const StatisticsCard(),
+          const SizedBox(height: 8),
+          const ChartTimelineCard(),
           const SizedBox(height: 36),
         ],
       ),
diff --git a/lib/ui/widgets/main_screen/timeline_card.dart b/lib/ui/widgets/main_screen/timeline_card.dart
new file mode 100644
index 0000000000000000000000000000000000000000..bd3d14a8fc6f86452534d98ea0191aa2ac585198
--- /dev/null
+++ b/lib/ui/widgets/main_screen/timeline_card.dart
@@ -0,0 +1,48 @@
+import 'dart:convert';
+
+import 'package:flutter/material.dart';
+
+import '../../../models/timeline.dart';
+import '../../../network/scrobbles_api.dart';
+import '../../../ui/widgets/error.dart';
+import '../../../ui/widgets/main_screen/timeline_content.dart';
+
+class ChartTimelineCard extends StatelessWidget {
+  const ChartTimelineCard({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    final int daysCount = 14;
+    late Future<TimelineData> futureTimeline = ScrobblesApi.fetchTimeline(daysCount);
+
+    return FutureBuilder<TimelineData>(
+      future: futureTimeline,
+      builder: (context, snapshot) {
+        if (snapshot.hasError) {
+          return ShowErrorWidget(message: '${snapshot.error}');
+        }
+
+        return Card(
+          elevation: 2,
+          shadowColor: Theme.of(context).colorScheme.shadow,
+          color: Theme.of(context).colorScheme.primary,
+          shape: const RoundedRectangleBorder(
+            borderRadius: BorderRadius.all(
+              Radius.circular(12),
+            ),
+          ),
+          child: Padding(
+            padding: const EdgeInsets.all(12.0),
+            child: ChartTimelineCardContent(
+              daysCount: daysCount,
+              chartData: snapshot.hasData
+                  ? TimelineData.fromJson(jsonDecode(snapshot.data.toString()))
+                  : TimelineData.createEmpty(),
+              isLoading: !snapshot.hasData,
+            ),
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/main_screen/timeline_chart_counts.dart b/lib/ui/widgets/main_screen/timeline_chart_counts.dart
new file mode 100644
index 0000000000000000000000000000000000000000..409d7dc19712e72c3a66a947146146ef3c4fd5ca
--- /dev/null
+++ b/lib/ui/widgets/main_screen/timeline_chart_counts.dart
@@ -0,0 +1,193 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:fl_chart/fl_chart.dart';
+
+import '../../../config/app_colors.dart';
+import '../../../models/timeline.dart';
+import '../../../utils/color_extensions.dart';
+
+class ChartTimelineCounts extends StatelessWidget {
+  final TimelineData chartData;
+
+  const ChartTimelineCounts({super.key, required this.chartData});
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      height: 150.0,
+      child: LayoutBuilder(builder: (context, constraints) {
+        final double maxWidth = constraints.maxWidth;
+        final int barsCount = this.chartData.data.keys.length;
+        final double barWidth = 0.7 * (maxWidth / barsCount);
+
+        return BarChart(
+          BarChartData(
+            barGroups: getDataCounts(barWidth),
+            backgroundColor: Theme.of(context).colorScheme.onBackground,
+            borderData: getBorderData(),
+            gridData: getGridData(),
+            titlesData: getTitlesData(),
+            barTouchData: getBarTouchData(),
+            maxY: getNextRoundNumber(getMaxCountsValue(), 50),
+          ),
+        );
+      }),
+    );
+  }
+
+  double getMaxCountsValue() {
+    double maxValue = 0;
+
+    this.chartData.data.keys.forEach((key) {
+      TimelineDataValue? value = this.chartData.data[key];
+      if (value != null) {
+        double counts = value.counts.toDouble();
+        if (counts > maxValue) {
+          maxValue = counts;
+        }
+      }
+    });
+
+    return maxValue;
+  }
+
+  double getNextRoundNumber(double number, int scale) {
+    return scale * ((number ~/ scale).toInt() + 1);
+  }
+
+  List<BarChartGroupData> getDataCounts(double barWidth) {
+    List<BarChartGroupData> data = [];
+
+    this.chartData.data.keys.forEach((key) {
+      TimelineDataValue? value = this.chartData.data[key];
+      if (value != null) {
+        final int date = DateTime.parse(key).millisecondsSinceEpoch;
+        final double counts = value.counts.toDouble();
+
+        data.add(BarChartGroupData(
+          x: date,
+          barRods: [
+            BarChartRodData(
+              toY: counts,
+              color: AppColors.contentColorOrange,
+              width: barWidth,
+              borderRadius: BorderRadius.all(Radius.zero),
+              borderSide: BorderSide(
+                color: AppColors.contentColorOrange.darken(20),
+              ),
+            ),
+          ],
+        ));
+      }
+    });
+
+    return data;
+  }
+
+  FlBorderData getBorderData() {
+    return FlBorderData(
+      show: true,
+      border: Border.all(
+        color: AppColors.borderColor,
+        width: 2,
+      ),
+    );
+  }
+
+  FlGridData getGridData() {
+    return const FlGridData(
+      show: true,
+    );
+  }
+
+  FlTitlesData getTitlesData() {
+    const AxisTitles none = const AxisTitles(
+      sideTitles: SideTitles(showTitles: false),
+    );
+
+    final AxisTitles verticalTitles = AxisTitles(
+      sideTitles: SideTitles(
+        showTitles: true,
+        reservedSize: 30,
+        getTitlesWidget: getVerticalTitlesWidget,
+      ),
+    );
+    final AxisTitles horizontalTitles = AxisTitles(
+      sideTitles: SideTitles(
+        showTitles: true,
+        reservedSize: 20,
+        getTitlesWidget: getHorizontalTitlesWidget,
+      ),
+    );
+
+    return FlTitlesData(
+      show: true,
+      bottomTitles: horizontalTitles,
+      leftTitles: none,
+      topTitles: none,
+      rightTitles: verticalTitles,
+    );
+  }
+
+  Widget getVerticalTitlesWidget(double value, TitleMeta meta) {
+    return SideTitleWidget(
+      axisSide: meta.axisSide,
+      space: 4,
+      child: Text(
+        value.toInt().toString(),
+        style: const TextStyle(
+          color: AppColors.mainTextColor1,
+          fontSize: 12,
+        ),
+      ),
+    );
+  }
+
+  Widget getHorizontalTitlesWidget(double value, TitleMeta meta) {
+    final DateFormat formatter = DateFormat('dd/MM');
+
+    final DateTime date = DateTime.fromMillisecondsSinceEpoch(value.toInt());
+    final String text = formatter.format(date);
+
+    return SideTitleWidget(
+      axisSide: meta.axisSide,
+      space: 4,
+      child: RotationTransition(
+        turns: new AlwaysStoppedAnimation(-30 / 360),
+        child: Text(
+          text,
+          style: const TextStyle(
+            color: AppColors.mainTextColor1,
+            fontSize: 11,
+          ),
+        ),
+      ),
+    );
+  }
+
+  BarTouchData getBarTouchData() {
+    return BarTouchData(
+      enabled: true,
+      touchTooltipData: BarTouchTooltipData(
+        tooltipBgColor: Colors.transparent,
+        tooltipPadding: EdgeInsets.zero,
+        tooltipMargin: 2,
+        getTooltipItem: (
+          BarChartGroupData group,
+          int groupIndex,
+          BarChartRodData rod,
+          int rodIndex,
+        ) {
+          return BarTooltipItem(
+            rod.toY.round().toString(),
+            const TextStyle(
+              color: AppColors.mainTextColor2,
+              fontWeight: FontWeight.bold,
+              fontSize: 10,
+            ),
+          );
+        },
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/main_screen/timeline_content.dart b/lib/ui/widgets/main_screen/timeline_content.dart
new file mode 100644
index 0000000000000000000000000000000000000000..747a752ae9c2d1fa7f645ddb415887c13ffe6c6b
--- /dev/null
+++ b/lib/ui/widgets/main_screen/timeline_content.dart
@@ -0,0 +1,49 @@
+import 'dart:convert';
+
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+import '../../../models/timeline.dart';
+import 'timeline_chart_counts.dart';
+
+class ChartTimelineCardContent extends StatelessWidget {
+  final int daysCount;
+  final TimelineData chartData;
+  final bool isLoading;
+
+  const ChartTimelineCardContent(
+      {super.key, required this.daysCount, required this.chartData, required this.isLoading});
+
+  @override
+  Widget build(BuildContext context) {
+    final TextTheme textTheme = Theme.of(context).primaryTextTheme;
+    final String placeholder = '⏳';
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: <Widget>[
+        Text(
+          'timeline_title',
+          style: textTheme.titleLarge!.apply(fontWeightDelta: 2),
+        ).tr(
+          namedArgs: {
+            'daysCount': this.daysCount.toString(),
+          },
+        ),
+        const SizedBox(height: 8),
+        this.isLoading
+            ? Text(placeholder)
+            : Column(
+                mainAxisAlignment: MainAxisAlignment.center,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                children: [
+                  ChartTimelineCounts(
+                    chartData: TimelineData.fromJson(jsonDecode(this.chartData.toString())),
+                  ),
+                ],
+              ),
+      ],
+    );
+  }
+}
diff --git a/lib/utils/color_extensions.dart b/lib/utils/color_extensions.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4e55e338f0d3ed98b233d1ef887b7b3e17e29d97
--- /dev/null
+++ b/lib/utils/color_extensions.dart
@@ -0,0 +1,33 @@
+import 'dart:ui';
+
+extension ColorExtension on Color {
+  Color darken([int percent = 40]) {
+    assert(1 <= percent && percent <= 100);
+    final value = 1 - percent / 100;
+    return Color.fromARGB(
+      alpha,
+      (red * value).round(),
+      (green * value).round(),
+      (blue * value).round(),
+    );
+  }
+
+  Color lighten([int percent = 40]) {
+    assert(1 <= percent && percent <= 100);
+    final value = percent / 100;
+    return Color.fromARGB(
+      alpha,
+      (red + ((255 - red) * value)).round(),
+      (green + ((255 - green) * value)).round(),
+      (blue + ((255 - blue) * value)).round(),
+    );
+  }
+
+  Color avg(Color other) {
+    final red = (this.red + other.red) ~/ 2;
+    final green = (this.green + other.green) ~/ 2;
+    final blue = (this.blue + other.blue) ~/ 2;
+    final alpha = (this.alpha + other.alpha) ~/ 2;
+    return Color.fromARGB(alpha, red, green, blue);
+  }
+}
diff --git a/pubspec.lock b/pubspec.lock
index b999423b57d2df0826c5e29ad20d24a920e6bd85..6952c80f4084d5c3cf81e39ae9fab6f9d59bebb9 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -57,6 +57,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "0.0.2"
+  equatable:
+    dependency: transitive
+    description:
+      name: equatable
+      sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.5"
   ffi:
     dependency: transitive
     description:
@@ -73,6 +81,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "7.0.0"
+  fl_chart:
+    dependency: "direct main"
+    description:
+      name: fl_chart
+      sha256: "6b9eb2b3017241d05c482c01f668dd05cc909ec9a0114fdd49acd958ff2432fa"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.64.0"
   flutter:
     dependency: "direct main"
     description: flutter
diff --git a/pubspec.yaml b/pubspec.yaml
index 3443b82105e3ebc8fb98e60444b5695ef31fa726..2439c6dec5fed740a8901704764de77dda3cfe25 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: Display scrobbles data and charts
 
 publish_to: 'none'
 
-version: 0.0.6+6
+version: 0.0.7+7
 
 environment:
   sdk: '^3.0.0'
@@ -14,6 +14,7 @@ dependencies:
 
   easy_localization: ^3.0.1
   http: ^1.1.0
+  fl_chart: ^0.64.0
 
 flutter:
   uses-material-design: false