diff --git a/android/gradle.properties b/android/gradle.properties
index 9b5bace2138ec06078e8d1ada235d80aff083846..604fc088e204d265443088fe8d1680c63a2b132f 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.37
-app.versionCode=37
+app.versionName=0.0.38
+app.versionCode=38
diff --git a/fastlane/metadata/android/en-US/changelogs/38.txt b/fastlane/metadata/android/en-US/changelogs/38.txt
new file mode 100644
index 0000000000000000000000000000000000000000..17fb8070f086b476f31c3bba9c443881523d67d0
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/38.txt
@@ -0,0 +1 @@
+Add top artists streamline chart.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/38.txt b/fastlane/metadata/android/fr-FR/changelogs/38.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6197059481114f4b3188e922c33b4cb638ccafcb
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/38.txt
@@ -0,0 +1 @@
+Ajout graphique d'évolution du "top artistes".
diff --git a/lib/models/topartists.dart b/lib/models/topartists.dart
index 6c2719047ed1f8f5f05bc51e9aa9decb12b09fca..a53f60e4c6eb4d1e2b48c77d00fc47fa8c408b04 100644
--- a/lib/models/topartists.dart
+++ b/lib/models/topartists.dart
@@ -14,15 +14,46 @@ class TopArtistsDataValue {
   }
 }
 
+class TopArtistsStreamDataValue {
+  final String artistName;
+  final double value;
+
+  const TopArtistsStreamDataValue({
+    required this.artistName,
+    required this.value,
+  });
+
+  factory TopArtistsStreamDataValue.fromJson(Map<String, dynamic>? json) {
+    return TopArtistsStreamDataValue(
+      artistName: json?['artistName'] as String,
+      value: json?['value'] as double,
+    );
+  }
+
+  Map<String, dynamic>? toJson() {
+    return {
+      artistName: value,
+    };
+  }
+
+  @override
+  String toString() {
+    return jsonEncode(this.toJson());
+  }
+}
+
 class TopArtistsData {
   final List<TopArtistsDataValue> topArtists;
+  final Map<String, List<TopArtistsStreamDataValue>> topArtistsStream;
 
   const TopArtistsData({
     required this.topArtists,
+    required this.topArtistsStream,
   });
 
   factory TopArtistsData.fromJson(Map<String, dynamic>? json) {
     List<TopArtistsDataValue> topArtists = [];
+    Map<String, List<TopArtistsStreamDataValue>> topArtistsStream = {};
 
     json?['top-artists'].forEach((element) {
       TopArtistsDataValue value = TopArtistsDataValue(
@@ -33,13 +64,39 @@ class TopArtistsData {
       topArtists.add(value);
     });
 
+    json?['top-artists-stream-by-date'].keys.forEach((date) {
+      if (json['top-artists-stream-by-date'][date] is Map<String, dynamic>) {
+        Map<String, dynamic> content = json['top-artists-stream-by-date'][date];
+
+        List<TopArtistsStreamDataValue> items = [];
+        content.forEach((String artistName, dynamic rawValue) {
+          double value = 0.0;
+          if (rawValue is double) {
+            value = rawValue;
+          } else if (rawValue is int) {
+            value = rawValue.toDouble();
+          }
+          TopArtistsStreamDataValue item = TopArtistsStreamDataValue(
+            artistName: artistName,
+            value: value,
+          );
+
+          items.add(item);
+        });
+
+        topArtistsStream[date] = items;
+      }
+    });
+
     return TopArtistsData(
       topArtists: topArtists,
+      topArtistsStream: topArtistsStream,
     );
   }
 
   Map<String, Object?>? toJson() {
     List<Map<String, Object>> listArtists = [];
+    Map<String, List<Map<String, double>>> artistsStreamMap = {};
 
     this.topArtists.forEach((TopArtistsDataValue? item) {
       listArtists.add({
@@ -48,8 +105,20 @@ class TopArtistsData {
       });
     });
 
+    this.topArtistsStream.keys.forEach((dateAsString) {
+      List<TopArtistsStreamDataValue>? items = this.topArtistsStream[dateAsString];
+      List<Map<String, double>> values = [];
+      items?.forEach((item) {
+        values.add({
+          item.artistName: item.value,
+        });
+      });
+      artistsStreamMap[dateAsString] = values;
+    });
+
     return {
       'top-artists': listArtists,
+      'top-artists-stream-by-date': artistsStreamMap,
     };
   }
 
diff --git a/lib/ui/widgets/abstracts/custom_bar_chart.dart b/lib/ui/widgets/abstracts/custom_bar_chart.dart
index e986c842dd802db83041ac07d754b2732a82a5a3..d80acd1d653949f76eb09321fdea4dc1bef457b3 100644
--- a/lib/ui/widgets/abstracts/custom_bar_chart.dart
+++ b/lib/ui/widgets/abstracts/custom_bar_chart.dart
@@ -11,7 +11,7 @@ class CustomBarChart extends StatelessWidget {
   final double chartHeight = 150.0;
   final double verticalTicksInterval = 10;
   final String verticalAxisTitleSuffix = '';
-  final double titleFontSize = 10;
+  final double titleFontSize = 9;
 
   @override
   Widget build(BuildContext context) {
diff --git a/lib/ui/widgets/abstracts/custom_line_chart.dart b/lib/ui/widgets/abstracts/custom_line_chart.dart
index e91e553da59f3b94bc64fc1755db3b22c5cddb11..e0362d84aacc86f3c373525eeffb670acbf725f7 100644
--- a/lib/ui/widgets/abstracts/custom_line_chart.dart
+++ b/lib/ui/widgets/abstracts/custom_line_chart.dart
@@ -7,7 +7,7 @@ class CustomLineChart extends StatelessWidget {
   const CustomLineChart({super.key});
 
   final double chartHeight = 150.0;
-  final double titleFontSize = 10;
+  final double titleFontSize = 9;
 
   @override
   Widget build(BuildContext context) {
diff --git a/lib/ui/widgets/cards/top_artists.dart b/lib/ui/widgets/cards/top_artists.dart
index 24a85857d5c7e0bbd57223e282a6fc19413c5fca..c528e431b73a8588bc6df7e442e76c41d66f5538 100644
--- a/lib/ui/widgets/cards/top_artists.dart
+++ b/lib/ui/widgets/cards/top_artists.dart
@@ -8,6 +8,7 @@ import 'package:scrobbles/models/topartists.dart';
 import 'package:scrobbles/network/scrobbles.dart';
 import 'package:scrobbles/ui/widgets/card_content.dart';
 import 'package:scrobbles/ui/widgets/charts/top_artists.dart';
+import 'package:scrobbles/ui/widgets/charts/top_artists_stream.dart';
 import 'package:scrobbles/ui/widgets/error.dart';
 
 class CardTopArtists extends StatelessWidget {
@@ -21,6 +22,8 @@ class CardTopArtists extends StatelessWidget {
 
     return BlocBuilder<DataTopArtistsCubit, DataTopArtistsState>(
       builder: (BuildContext context, DataTopArtistsState state) {
+        TopArtistsData artistsData = state.topArtists ?? TopArtistsData.fromJson({});
+
         return CardContent(
           color: Theme.of(context).colorScheme.surface,
           title: 'top_artists_title'.tr(
@@ -29,8 +32,18 @@ class CardTopArtists extends StatelessWidget {
             },
           ),
           loader: updateTopArtists(daysCount),
-          content: ChartTopArtists(
-            chartData: TopArtistsData.fromJson(state.topArtists?.toJson()),
+          content: Column(
+            mainAxisSize: MainAxisSize.min,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              ChartTopArtists(
+                chartData: artistsData,
+              ),
+              const SizedBox(height: 8),
+              ChartTopArtistsStream(
+                chartData: artistsData,
+              ),
+            ],
           ),
         );
       },
diff --git a/lib/ui/widgets/charts/top_artists_stream.dart b/lib/ui/widgets/charts/top_artists_stream.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4a5fdf645f2a9d0aec01116981e7fab6d21617ca
--- /dev/null
+++ b/lib/ui/widgets/charts/top_artists_stream.dart
@@ -0,0 +1,224 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:fl_chart/fl_chart.dart';
+
+import 'package:scrobbles/config/app_colors.dart';
+import 'package:scrobbles/models/topartists.dart';
+import 'package:scrobbles/ui/widgets/abstracts/custom_line_chart.dart';
+import 'package:scrobbles/utils/color_extensions.dart';
+
+class ChartTopArtistsStream extends CustomLineChart {
+  final TopArtistsData chartData;
+
+  const ChartTopArtistsStream({super.key, required this.chartData});
+
+  final double verticalTicksInterval = 10;
+
+  @override
+  Widget build(BuildContext context) {
+    final horizontalScale = getHorizontalScale();
+
+    if (this.chartData.topArtistsStream.keys.isEmpty) {
+      return SizedBox(
+        height: this.chartHeight,
+      );
+    }
+
+    return Container(
+      height: this.chartHeight,
+      child: LineChart(
+        LineChartData(
+          lineBarsData: getDataStreamLine(),
+          betweenBarsData: getBetweenBarsData(),
+          borderData: getBorderData(),
+          gridData: getGridData(),
+          titlesData: getTitlesData(),
+          lineTouchData: const LineTouchData(enabled: false),
+          minX: horizontalScale['min'],
+          maxX: horizontalScale['max'],
+          maxY: getNextRoundNumber(getMaxVerticalValue(), this.verticalTicksInterval),
+          minY: 0,
+        ),
+        duration: const Duration(milliseconds: 250),
+      ),
+    );
+  }
+
+  double getNextRoundNumber(double number, double scale) {
+    return scale * ((number ~/ scale).toInt() + 1);
+  }
+
+  FlGridData getGridData() {
+    return const FlGridData(
+      show: true,
+      drawHorizontalLine: true,
+      drawVerticalLine: false,
+    );
+  }
+
+  double getMaxVerticalValue() {
+    double maxValue = 0;
+
+    this.chartData.topArtistsStream.keys.forEach((dateAsString) {
+      double totalValue = 0.0;
+      List<TopArtistsStreamDataValue> artists =
+          this.chartData.topArtistsStream[dateAsString] ?? [];
+
+      artists.forEach((artist) {
+        final double value = artist.value;
+        totalValue = totalValue + value;
+      });
+
+      if (totalValue > maxValue) {
+        maxValue = totalValue;
+      }
+    });
+
+    return maxValue;
+  }
+
+  Map<String, double> getHorizontalScale() {
+    double minDateAsDouble = double.maxFinite;
+    double maxDateAsDouble = -double.maxFinite;
+
+    this.chartData.topArtistsStream.keys.forEach((dateAsString) {
+      final double date = DateTime.parse(dateAsString).millisecondsSinceEpoch.toDouble();
+
+      if (date < minDateAsDouble) {
+        minDateAsDouble = date;
+      }
+      if (date > maxDateAsDouble) {
+        maxDateAsDouble = date;
+      }
+    });
+
+    return {
+      'min': minDateAsDouble,
+      'max': maxDateAsDouble,
+    };
+  }
+
+  Color getColorIndex(int index) {
+    const List<int> hexValues = [
+      0x8dd3c7,
+      0xffffb3,
+      0xbebada,
+      0xfb8072,
+      0x80b1d3,
+      0xfdb462,
+      0xb3de69,
+      0xfccde5,
+      0xd9d9d9,
+      0xbc80bd,
+      0xccebc5,
+      0xffed6f,
+    ];
+
+    return Color(hexValues[index % hexValues.length] + 0xff000000);
+  }
+
+  List<LineChartBarData> getDataStreamLine() {
+    int artistsCount =
+        this.chartData.topArtistsStream[this.chartData.topArtistsStream.keys.first]?.length ??
+            0;
+
+    List<LineChartBarData> lines = [];
+
+    LineChartBarData getZeroHorizontalLine() {
+      final baseColor = getColorIndex(0);
+      final borderColor = baseColor.darken(20);
+
+      List<FlSpot> spots = [];
+
+      this.chartData.topArtistsStream.keys.forEach((dateAsString) {
+        final double date = DateTime.parse(dateAsString).millisecondsSinceEpoch.toDouble();
+        spots.add(FlSpot(date, 0));
+      });
+
+      return LineChartBarData(
+        color: borderColor,
+        dotData: const FlDotData(show: false),
+        spots: spots,
+      );
+    }
+
+    // First horizontal "zero" line
+    lines.add(getZeroHorizontalLine());
+
+    LineChartBarData getLinesFromIndex(int index) {
+      final baseColor = getColorIndex(index);
+      final borderColor = baseColor.darken(20);
+
+      List<FlSpot> spots = [];
+
+      this.chartData.topArtistsStream.keys.forEach((dateAsString) {
+        final double date = DateTime.parse(dateAsString).millisecondsSinceEpoch.toDouble();
+
+        List<TopArtistsStreamDataValue> artists =
+            this.chartData.topArtistsStream[dateAsString] ?? [];
+
+        double value = 0;
+        for (int i = 0; i <= index; i++) {
+          value = value + artists[i].value;
+        }
+
+        spots.add(FlSpot(date, value));
+      });
+
+      return LineChartBarData(
+        isCurved: true,
+        curveSmoothness: 0.25,
+        color: borderColor,
+        dotData: const FlDotData(show: false),
+        spots: spots,
+      );
+    }
+
+    Iterable<int>.generate(artistsCount)
+        .toList()
+        .map((index) => lines.add(getLinesFromIndex(index)))
+        .toList();
+
+    return lines;
+  }
+
+  List<BetweenBarsData> getBetweenBarsData() {
+    int artistsCount =
+        this.chartData.topArtistsStream[this.chartData.topArtistsStream.keys.first]?.length ??
+            0;
+
+    return Iterable<int>.generate(artistsCount)
+        .toList()
+        .map((index) => BetweenBarsData(
+              fromIndex: index,
+              toIndex: index + 1,
+              color: getColorIndex(index),
+            ))
+        .toList();
+  }
+
+  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: Padding(
+        padding: EdgeInsets.only(right: 10),
+        child: RotationTransition(
+          turns: new AlwaysStoppedAnimation(-30 / 360),
+          child: Text(
+            text,
+            style: TextStyle(
+              color: AppColors.mainTextColor1,
+              fontSize: this.titleFontSize,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/error.dart b/lib/ui/widgets/error.dart
index e65f242fd0b657ce06ee235ea8f574689bf7089f..d09c290104cba7331606c555d8206b999d778d19 100644
--- a/lib/ui/widgets/error.dart
+++ b/lib/ui/widgets/error.dart
@@ -8,6 +8,8 @@ class ShowErrorWidget extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
+    print(message);
+
     return Text(
       '⚠️ ' + tr(message),
       textAlign: TextAlign.start,
diff --git a/pubspec.yaml b/pubspec.yaml
index 0b954c9dfa9074b5161fd90a6505122d00503f64..106d606c7adf6ee9a94665ccb769851cd0363382 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: Display scrobbles data and charts
 
 publish_to: 'none'
 
-version: 0.0.37+37
+version: 0.0.38+38
 
 environment:
   sdk: '^3.0.0'