diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5152928dd41a382ec940e6c70f01b2a577ce1967
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,29 @@
+stages:
+  - test
+  - build
+  - deploy
+
+test:flutter:
+  stage: test
+  image: cirrusci/flutter
+  script:
+    - flutter test
+
+build:web-main:
+  stage: build
+  image: cirrusci/flutter
+  script:
+    - flutter build web --release --base-href '/article_flutter_riverpod/'
+  artifacts:
+    paths:
+      - build/web
+
+pages:
+  stage: deploy
+  script:
+    - cp -r build/web public
+  artifacts:
+    paths:
+      - public
+  only:
+    - main
\ No newline at end of file
diff --git a/README.md b/README.md
index 828170c94b7c371dca773f2617fbf3553b0c1415..ce1ef8a18c5dea8bbac554858aeb33d4b69c529d 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
 # Riverpod par la pratique
 
-* [Découverte des bases](docs/01_decouverte_des_bases.md)
\ No newline at end of file
+* [Découverte des bases](docs/01_decouverte_des_bases.md)
+* [Intégration avec Flutter](docs/02_integration_avec_flutter.md)
\ No newline at end of file
diff --git a/docs/01_decouverte_des_bases.md b/docs/01_decouverte_des_bases.md
index 99c984b452a154ba9b4f17bc3427390fbd66abdd..a91cc364988d2deefb407966b728c28a96c48f2b 100644
--- a/docs/01_decouverte_des_bases.md
+++ b/docs/01_decouverte_des_bases.md
@@ -1,6 +1,7 @@
 # Riverpod par la pratique : découverte des bases
 
 Cet article a pour objectif de vous faire découvrir pas à pas la bibliothèque Riverpod à partir d'exemples d'utilisation.
+Le code source est disponible sur le [GitLab Ippon](https://gitlab.ippon.fr/adbonnin/article_flutter_riverpod/-/tree/main/test/article_01).
 
 ## Il était une fois la gestion d’états
 
@@ -21,7 +22,7 @@ Cet article fait référence à la bibliothèque Provider sous ces termes unique
 Dès son installation, Riverpod se distingue de ses concurrentes par son découpage en plusieurs bibliothèques :
 
 - [`riverpod`](https://pub.dev/packages/riverpod) contient le code principale, sans aucune adhérence.
-- [`riverpod_flutter`](https://pub.dev/packages/flutter_riverpod) contient le code spécifique pour le framework Flutter.
+- [`flutter_riverpod`](https://pub.dev/packages/flutter_riverpod) contient le code spécifique pour le framework Flutter.
 - [`hooks_riverpod`](https://pub.dev/packages/hooks_riverpod) contient le code spécifique pour la bibliothèque [`flutter_hooks`](https://pub.dev/packages/flutter_hooks).
 
 La bibliothèque `flutter_riverpod` sera utilisée pour aborder l'ensemble des fondamentaux de Riverpod.
diff --git a/docs/02_integration_avec_flutter.md b/docs/02_integration_avec_flutter.md
new file mode 100644
index 0000000000000000000000000000000000000000..ff77cd5977b44c2a3592ecd056e1463c87786642
--- /dev/null
+++ b/docs/02_integration_avec_flutter.md
@@ -0,0 +1,331 @@
+# Riverpod par la pratique : Intégration avec Flutter
+
+Cet article à pour objectif de vous faire découvrir l'intégration de Riverpod dans une application Flutter.
+Il fait suite au précédent article sur la découverte des bases et s'appuie pour sur ses notions pour en ajouter de nouvelles.
+Le code source est disponible sur le [GitLab Ippon](https://gitlab.ippon.fr/adbonnin/article_flutter_riverpod/-/tree/main/lib/article_02) et les exemples sur la [GitLab page](http://adbonnin.pages-gitlab.ippon.fr/article_flutter_riverpod/#/) associée.
+
+## Intégration dans une application
+
+Dans Flutter, tout est widget.
+En suivant ce principe, Riverpod s'adapte à Flutter avec le widget `ProviderScope` dont la responsabilité est de partager ses états aux widgets enfants.
+Plusieurs manières permettent d'accéder à ces états, le widget `Consumer` étant la solution la moins intrusive : 
+
+[_source : consumer_example.dart_](https://gitlab.ippon.fr/adbonnin/article_flutter_riverpod/-/blob/main/lib/article_02/consumer_example.dart)
+
+```dart
+final helloProvider = Provider<String>((ref) => 'Hello world'); // <1>
+
+class IntegrationExample extends StatelessWidget {
+  const IntegrationExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return const ProviderScope( // <2>
+      child: MyExample(),
+    );
+  }
+}
+
+class MyExample extends StatelessWidget {
+  const MyExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Consumer( // <3>
+      builder: (_, WidgetRef ref, __) => Text(
+        ref.watch(helloProvider), // <4>
+        textDirection: TextDirection.ltr,
+      ),
+    );
+  }
+}
+```
+
+[![consumer](images/consumer.png)](http://adbonnin.pages-gitlab.ippon.fr/article_flutter_riverpod/#/consumer)
+
+Un `Provider` est défini pour retourner `'Hello world'` `<1>`.
+Les états sont disponibles pour les widgets enfants à partir du parent `ProviderScope` `<2>`.
+La méthode `builder` du `Consumer` `<3>` fournit en paramètre un `WidgetRef` qui permet de surveiller le provider et afficher son état `<4>`.
+
+Le `ProviderScope` vient encapsuler dans un widget le `ProviderContainer` pour le rendre accessible aux widgets enfants par l'intermédiaire d'un `WidgetRef`.
+De la même manière que le `ProviderRef`, le `WidgetRef` est une façade pour le `ProviderContainer` et le fonctionnement attendu des méthodes `read` et `watch` est identique.
+
+L'utilisation de la méthode `watch` indique que le widget sera reconstruit à chaque changement de l'état.
+Étant donné que l'état du `Provider` `<1>` conservera toujours la même valeur, la méthode `read` aurait eu le même comportement que la méthode `watch` `<4>`.
+Ce choix est motivé par la [documentation officielle](https://riverpod.dev/docs/concepts/reading/#using-refread-to-obtain-the-state-of-a-provider) qui favorise le fonctionnement réactif de la méthode `watch` par rapport à la méthode `read`.
+
+D'un point de vue conceptuel, à chaque fois qu'un widget utilise un `Provider` il en dévient dépendant.
+Cette dépendance ne pose pas de problème sur le court terme mais peut s'avérer coûteuse sur le long terme.
+A partir du moment où ces widgets sont utilisés il faut tenir compte de l'état des `Provider`s dont ils dépendent.
+Cette préoccupation est particulièrement présente à l'écriture des tests où chaque `Provider` doit être correctement initialisé.
+
+Le widget `Consumer` est une manière simple d'accéder au `WidgetRef` mais vient alourdir l'écriture de la méthode `build` avec un widget supplémentaire.
+Pour des cas plus complexes, Riverpod dispose de widgets spécifiques.
+
+## StatelessWidget et ConsumerWidget
+
+L'autre solution proposée par `Riverpod` pour accéder au `WidgetRef` est de remplacer à la déclaration la classe étendue.
+La classe `ConsumerWidget` vient remplacer `StatelessWidget` pour les widgets sans états :
+
+[_source : stateless_example.dart_](https://gitlab.ippon.fr/adbonnin/article_flutter_riverpod/-/blob/main/lib/article_02/stateless_example.dart)
+
+```dart
+final countServiceProvider = StateNotifierProvider<CountService, int>((ref) => CountService(42)); // <1>
+
+class CountService extends StateNotifier<int> { // <2>
+  CountService(int firstValue) : super(firstValue);
+
+  void increment() { // <3>
+    state++;
+  }
+}
+
+class StatelessExample extends StatelessWidget {
+  const StatelessExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return const ProviderScope(
+      child: Counter(),
+    );
+  }
+}
+
+class Counter extends ConsumerWidget { // <4>
+  const Counter({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) { // <5>
+    final currentValue = ref.watch(countServiceProvider); // <6>
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        Text("Current value: $currentValue"), // <7>
+        HSpace.m,
+        ElevatedButton(
+          onPressed: () => _onIncrement(ref), // <8>
+          child: const Text("Increment"),
+        ),
+      ],
+    );
+  }
+
+  void _onIncrement(WidgetRef ref) {
+    ref.read(countServiceProvider.notifier).increment(); // <9>
+  }
+}
+```
+
+[![stateless](images/stateless.png)](http://adbonnin.pages-gitlab.ippon.fr/article_flutter_riverpod/#/stateless)
+
+Un `StateNotifierProvider` est déclaré `<1>` pour le service `CountService` `<2>`.
+Ce service est un `StateNotifier` dont le state est un nombre qui peut être incrémenté en appelant la méthode `increment` `<3>`.
+La classe `ConsumerWidget` remplace `StatelessWidget` `<4>` et ajoute le paramètre `WidgetRef` au niveau de la méthode `build` `<5>`.
+Le `WidgetRef` est utilisé de la même manière qu'avec le `Consumer`, les modifications de l'état sont écoutées `<6>` pour être affichées `<7>`.
+Le même `WidgetRef` est ensuite passé en paramètre de la méthode appelée lors d'un clique sur le bouton `<8>`.
+Lors de cette méthode, la lecture du `notifier` présent dans le `countServiceProvider` donne accés au service pour appeler la méthode `increment`.
+
+Remplacer la classe étendue par le `Widget` est une solution qui peut se réléver contraignante voir ridibitoire pour certains développeurs.
+Cependant, ce choix d'implémentation simplifie l'intégration de Riverpod en donnant accès directement accès au `WidgetRef` depuis la méthode `build`.
+Comme pour le `BuildContext`, ce `WidgetRef` est passé aux méthodes qui ont besoin d'accéder aux états.
+
+## StatefulWidget et ConsumerStatefulWidget
+
+Le `ConsumerWidget` venant remplacer le `StatelessWidget`, c'est tout naturellement que le `StatefulWidget` dispose de sa propre implémentation :
+
+[_source : stateful_example.dart_](https://gitlab.ippon.fr/adbonnin/article_flutter_riverpod/-/blob/main/lib/article_02/stateful_example.dart)
+
+```dart
+final countServiceProvider = StateNotifierProvider<CountService, int>((ref) => CountService(42)); // <1>
+
+class CountService extends StateNotifier<int> {
+  CountService(int firstValue) : super(firstValue);
+
+  void increment() {
+    state++;
+  }
+}
+
+class StatefulExample extends StatelessWidget {
+  const StatefulExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return const ProviderScope(
+      child: Counter(),
+    );
+  }
+}
+
+class Counter extends ConsumerStatefulWidget { // <2>
+  const Counter({Key? key}) : super(key: key);
+
+  @override
+  ConsumerState<Counter> createState() => _CounterState(); // <3>
+}
+
+class _CounterState extends ConsumerState<Counter> { // <4>
+  late int firstValue;
+
+  @override
+  void initState() {
+    super.initState();
+    firstValue = ref.read(countServiceProvider); // <5>
+  }
+
+  @override
+  Widget build(BuildContext context) { // <6>
+    final currentValue = ref.watch(countServiceProvider); // <7>
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        Text("First value: $firstValue"), // <8>
+        HSpace.s,
+        Text("Current value: $currentValue"),
+        HSpace.m,
+        ElevatedButton(
+          onPressed: _onIncrement,
+          child: const Text("Increment"),
+        ),
+      ],
+    );
+  }
+
+  void _onIncrement() {
+    ref.read(countServiceProvider.notifier).increment(); // <9>
+  }
+}
+```
+
+[![stateful](images/stateful.png)](http://adbonnin.pages-gitlab.ippon.fr/article_flutter_riverpod/#/stateful)
+
+Le service et le provider associé sont identiques à l'exemple précédent `<1>`.
+Au niveau du widget, la classe `ConsumerStatefulWidget` remplace `StatefulWidget` `<2>`.
+Au niveau du state, la classe `ConsumerState` remplace `ConsumerState` à la déclaration `<4>` et à la création `<3>`.
+Contrairement au `ConsumerWidget`, la signature de la méthode `build` reste identique `<6>` car le `WidgetRef` est devenu une propriété.
+La première valeur du service est lue à l'initialisation du widget `<5>` puis ses modifications sont écoutées `<7>` pour être affichées `<8>`.
+Le `WidgetRef` en propriété est utilisé pour lire le service et incrémenter l'état.
+
+A la différence du `StatelessWidget`, le `WidgetRef` est directement accessible avec la propriété `ref`.
+Ce choix d'implémentation donne accés aux états de n'importe où dans le widget en conservant un code lisible ; le `WidgetRef` n'étant plus passé de méthode en méthode.
+
+Jusqu'à présent, les `Provider`s étaient surveillés avec la méthode `watch`, dans le `builder` du `Consumer` ou dans la méthode `build` des widgets.
+Dans les cas spécifiques où la surveillance est inutile le `Provider` est simplement lu avec la méthode `read`.
+C'est par exemple le cas pour récupérer ponctuellement un état `<7>` ou appeler une fonction d'un `notifier` `<11>`.
+
+## Un lien de parenté
+
+Le widget `ProviderScope` est un conteneur qui peut avoir en descendance un autre `ProviderScope` pour former un lien de parenté :
+
+[_source : parent_example.dart_](https://gitlab.ippon.fr/adbonnin/article_flutter_riverpod/-/blob/main/lib/article_02/parent_example.dart)
+
+```dart
+final countServiceProvider = StateNotifierProvider<CountService, int>((ref) => CountService(42)); // <1>
+
+class CountService extends StateNotifier<int> {
+  CountService(int firstValue) : super(firstValue);
+
+  void increment() {
+    state++;
+  }
+}
+
+final randomProvider = Provider<int>((ref) => Random().nextInt(10)); // <2>
+
+final multiplyByRandomProvider = Provider( // <3>
+      (ref) => ref.watch(countServiceProvider) * ref.watch(randomProvider),
+  dependencies: [
+    countServiceProvider,
+    randomProvider,
+  ],
+);
+
+class ParentExample extends StatelessWidget {
+  const ParentExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return ProviderScope( // <4>
+      child: Column(
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          const Counter(), // <5>
+          HSpace.xl,
+          ProviderScope( // <6>
+            overrides: [
+              countServiceProvider.overrideWithValue(CountService(13)), // <7>
+            ],
+            child: const Counter(), // <8>
+          ),
+        ],
+      ),
+    );
+  }
+}
+
+class Counter extends ConsumerStatefulWidget {
+  const Counter({Key? key}) : super(key: key);
+
+  @override
+  ConsumerState<Counter> createState() => _CounterState();
+}
+
+class _CounterState extends ConsumerState<Counter> {
+  late int firstValue;
+
+  @override
+  void initState() {
+    super.initState();
+    firstValue = ref.read(countServiceProvider); // <9>
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final currentValue = ref.watch(countServiceProvider); // <10>
+    final random = ref.watch(randomProvider);
+    final multiplyByTwo = ref.watch(multiplyByRandomProvider);
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        Text("First value: $firstValue"),
+        HSpace.s,
+        Text("Current value: $currentValue"),
+        HSpace.s,
+        Text("Multiplied by $random: $multiplyByTwo"),
+        HSpace.m,
+        ElevatedButton(
+          onPressed: _onIncrement,
+          child: const Text("Increment"),
+        )
+      ],
+    );
+  }
+
+  void _onIncrement() {
+    ref.read(countServiceProvider.notifier).increment(); // <11>
+  }
+}
+```
+
+[![parent_provider_scope](images/parent_provider_scope.png)](http://adbonnin.pages-gitlab.ippon.fr/article_flutter_riverpod/#/parent-providerscope)
+
+Le service et le provider associé sont identiques à l'exemple précédent `<1>`.
+Un chiffre aléatoire est retourné par le `Provider` `randomProvider` `<2>`.
+Le `Provider` `multiplyByRandomProvider` `<3>` vient écouter le provider `countServiceProvider` et retourne sa valeur multipliée le `randomProvider`.
+Un premier `ProviderScope` est déclaré `<4>` avec un `Counter` associé `<5>`. 
+Un second `ProviderScope` est déclaré `<6>` en temps que widget enfant du précédent avec également un `Counter` associé `<8>`.
+Ce second `ProviderScope` vient surcharger la valeur du `counterServiceProvider` `<7>`.
+Comme précédemment, le widget `Counter` vient lire `<9>`, surveiller `<10>` et incrémenter `<11>` le `counterServiceProvider`.
+
+Les deux widgets `Counter`s partagent le même état du `Provider` `randomProvider` `<2>`.
+Ce n'est qu'à partir du moment où le `ProviderScope` surcharge le `countServiceProvider` `<7>` que chacun dispose de sa propre valeur.
+Le provider `multiplyByRandomProvider` dépendant de `countServiceProvider` dispose également de son propre état.
+Cette dépendance a été indiqué lors de la déclaration du `multiplyByRandomProvider` `<3>` pour que Riverpod en ai conscience.
+Il en résulte deux `Counter` qui interagissent avec des états indépendants avec un multiplicateur commun.
+
+## L'aventure continue
+
+Maintenant que toutes les bases sont posées vous devriez être en mesure d'utiliser Riverpod dans votre application.
diff --git a/docs/images/cependant.gif b/docs/images/cependant.gif
new file mode 100644
index 0000000000000000000000000000000000000000..087182b075c631eab8f525afcb24caa6e0b08bde
Binary files /dev/null and b/docs/images/cependant.gif differ
diff --git a/docs/images/consumer.png b/docs/images/consumer.png
new file mode 100644
index 0000000000000000000000000000000000000000..1a8799ded8d2c14c71c12fe21a11622a3c389f6d
Binary files /dev/null and b/docs/images/consumer.png differ
diff --git a/docs/images/parent_provider_scope.png b/docs/images/parent_provider_scope.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ea571cbef4cf670dfcf8a2214cb5655ee74c1d5
Binary files /dev/null and b/docs/images/parent_provider_scope.png differ
diff --git a/docs/images/stateful.png b/docs/images/stateful.png
new file mode 100644
index 0000000000000000000000000000000000000000..93502060d5dad4bb6169f782dcde0a2a95f99d7a
Binary files /dev/null and b/docs/images/stateful.png differ
diff --git a/docs/images/stateless.png b/docs/images/stateless.png
new file mode 100644
index 0000000000000000000000000000000000000000..e878f8ece1cd143919f972af7d1da0451941da20
Binary files /dev/null and b/docs/images/stateless.png differ
diff --git a/lib/article_02/consumer_example.dart b/lib/article_02/consumer_example.dart
new file mode 100644
index 0000000000000000000000000000000000000000..a161eca296a1e44cf56869242d223bf772eefe15
--- /dev/null
+++ b/lib/article_02/consumer_example.dart
@@ -0,0 +1,29 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+
+final helloProvider = Provider<String>((ref) => 'Hello world'); // <1>
+
+class ConsumerExample extends StatelessWidget {
+  const ConsumerExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return const ProviderScope( // <2>
+      child: MyExample(),
+    );
+  }
+}
+
+class MyExample extends StatelessWidget {
+  const MyExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Consumer( // <3>
+      builder: (_, WidgetRef ref, __) => Text(
+        ref.watch(helloProvider), // <4>
+        textDirection: TextDirection.ltr,
+      ),
+    );
+  }
+}
diff --git a/lib/article_02/parent_example.dart b/lib/article_02/parent_example.dart
new file mode 100644
index 0000000000000000000000000000000000000000..19b327450c0b8c7b863acad29cad05a82a74a278
--- /dev/null
+++ b/lib/article_02/parent_example.dart
@@ -0,0 +1,92 @@
+import 'dart:math';
+
+import 'package:article_flutter_riverpod/widgets/space.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+
+final countServiceProvider = StateNotifierProvider<CountService, int>((ref) => CountService(42)); // <1>
+
+class CountService extends StateNotifier<int> {
+  CountService(int firstValue) : super(firstValue);
+
+  void increment() {
+    state++;
+  }
+}
+
+final randomProvider = Provider<int>((ref) => Random().nextInt(10)); // <2>
+
+final multiplyByRandomProvider = Provider( // <3>
+  (ref) => ref.watch(countServiceProvider) * ref.watch(randomProvider),
+  dependencies: [
+    countServiceProvider,
+    randomProvider,
+  ],
+);
+
+class ParentExample extends StatelessWidget {
+  const ParentExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return ProviderScope( // <4>
+      child: Column(
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          const Counter(), // <5>
+          HSpace.xl,
+          ProviderScope( // <6>
+            overrides: [
+              countServiceProvider.overrideWithValue(CountService(13)), // <7>
+            ],
+            child: const Counter(), // <8>
+          ),
+        ],
+      ),
+    );
+  }
+}
+
+class Counter extends ConsumerStatefulWidget {
+  const Counter({Key? key}) : super(key: key);
+
+  @override
+  ConsumerState<Counter> createState() => _CounterState();
+}
+
+class _CounterState extends ConsumerState<Counter> {
+  late int firstValue;
+
+  @override
+  void initState() {
+    super.initState();
+    firstValue = ref.read(countServiceProvider); // <9>
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final currentValue = ref.watch(countServiceProvider); // <10>
+    final random = ref.watch(randomProvider);
+    final multiplyByRandom = ref.watch(multiplyByRandomProvider);
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        Text("First value: $firstValue"),
+        HSpace.s,
+        Text("Current value: $currentValue"),
+        HSpace.s,
+        Text("Multiplied by $random: $multiplyByRandom"),
+        HSpace.m,
+        ElevatedButton(
+          onPressed: _onIncrement,
+          child: const Text("Increment"),
+        )
+      ],
+    );
+  }
+
+  void _onIncrement() {
+    ref.read(countServiceProvider.notifier).increment(); // <11>
+  }
+}
diff --git a/lib/article_02/stateful_example.dart b/lib/article_02/stateful_example.dart
new file mode 100644
index 0000000000000000000000000000000000000000..0f7a917f994f3f0489f0f92de76f54c31f3f0957
--- /dev/null
+++ b/lib/article_02/stateful_example.dart
@@ -0,0 +1,64 @@
+import 'package:article_flutter_riverpod/widgets/space.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+
+final countServiceProvider = StateNotifierProvider<CountService, int>((ref) => CountService(42)); // <1>
+
+class CountService extends StateNotifier<int> {
+  CountService(int firstValue) : super(firstValue);
+
+  void increment() {
+    state++;
+  }
+}
+
+class StatefulExample extends StatelessWidget {
+  const StatefulExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return const ProviderScope(
+      child: Counter(),
+    );
+  }
+}
+
+class Counter extends ConsumerStatefulWidget { // <2>
+  const Counter({Key? key}) : super(key: key);
+
+  @override
+  ConsumerState<Counter> createState() => _CounterState(); // <3>
+}
+
+class _CounterState extends ConsumerState<Counter> { // <4>
+  late int firstValue;
+
+  @override
+  void initState() {
+    super.initState();
+    firstValue = ref.read(countServiceProvider); // <5>
+  }
+
+  @override
+  Widget build(BuildContext context) { // <6>
+    final currentValue = ref.watch(countServiceProvider); // <7>
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        Text("First value: $firstValue"), // <8>
+        HSpace.s,
+        Text("Current value: $currentValue"),
+        HSpace.m,
+        ElevatedButton(
+          onPressed: _onIncrement,
+          child: const Text("Increment"),
+        ),
+      ],
+    );
+  }
+
+  void _onIncrement() {
+    ref.read(countServiceProvider.notifier).increment(); // <9>
+  }
+}
diff --git a/lib/article_02/stateless_example.dart b/lib/article_02/stateless_example.dart
new file mode 100644
index 0000000000000000000000000000000000000000..01208e87853d84096bb07e57a7c91583f3498ceb
--- /dev/null
+++ b/lib/article_02/stateless_example.dart
@@ -0,0 +1,49 @@
+import 'package:article_flutter_riverpod/widgets/space.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+
+final countServiceProvider = StateNotifierProvider<CountService, int>((ref) => CountService(42)); // <1>
+
+class CountService extends StateNotifier<int> { // <2>
+  CountService(int firstValue) : super(firstValue);
+
+  void increment() { // <3>
+    state++;
+  }
+}
+
+class StatelessExample extends StatelessWidget {
+  const StatelessExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return const ProviderScope(
+      child: Counter(),
+    );
+  }
+}
+
+class Counter extends ConsumerWidget { // <4>
+  const Counter({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) { // <5>
+    final currentValue = ref.watch(countServiceProvider); // <6>
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        Text("Current value: $currentValue"), // <7>
+        HSpace.m,
+        ElevatedButton(
+          onPressed: () => _onIncrement(ref), // <8>
+          child: const Text("Increment"),
+        ),
+      ],
+    );
+  }
+
+  void _onIncrement(WidgetRef ref) {
+    ref.read(countServiceProvider.notifier).increment(); // <9>
+  }
+}
diff --git a/lib/example.dart b/lib/example.dart
new file mode 100644
index 0000000000000000000000000000000000000000..85c4d23031e0400fd1614e15e57095e8bbe2c98c
--- /dev/null
+++ b/lib/example.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+
+class Example {
+  const Example({
+    required this.title,
+    required this.icon,
+    required this.path,
+    required this.builder,
+  });
+
+  final String title;
+  final IconData icon;
+  final String path;
+  final WidgetBuilder builder;
+}
+
+class ExampleContainer extends StatelessWidget {
+  const ExampleContainer(
+    this.example, {
+    Key? key,
+  }) : super(key: key);
+
+  final Example example;
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: Text(example.title),
+      ),
+      body: Center(
+        child: SingleChildScrollView(
+          child: example.builder(context),
+        ),
+      ),
+    );
+  }
+}
diff --git a/lib/main.dart b/lib/main.dart
index 202509be15d8afab8cc0096ea1b9610bd3832dae..d4a19fef476ef41e4a700568cd16cd03b44d7bdd 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,115 +1,100 @@
+import 'package:article_flutter_riverpod/example.dart';
+import 'package:article_flutter_riverpod/article_02/consumer_example.dart';
+import 'package:article_flutter_riverpod/article_02/parent_example.dart';
+import 'package:article_flutter_riverpod/article_02/stateful_example.dart';
+import 'package:article_flutter_riverpod/article_02/stateless_example.dart';
 import 'package:flutter/material.dart';
+import 'package:go_router/go_router.dart';
+
+final examples = [
+  Example(
+    title: 'Consumer',
+    icon: Icons.eco,
+    path: 'consumer',
+    builder: (_) => const ConsumerExample(),
+  ),
+  Example(
+    title: 'Stateless',
+    icon: Icons.remove_circle_outline,
+    path: 'stateless',
+    builder: (_) => const StatelessExample(),
+  ),
+  Example(
+    title: 'Stateful',
+    icon: Icons.add_circle_outline,
+    path: 'stateful',
+    builder: (_) => const StatefulExample(),
+  ),
+  Example(
+    title: 'Parent ProviderScope',
+    icon: Icons.child_care,
+    path: 'parent-providerscope',
+    builder: (_) => const ParentExample(),
+  ),
+];
 
 void main() {
-  runApp(const MyApp());
+  runApp(ArticleApp());
 }
 
-class MyApp extends StatelessWidget {
-  const MyApp({Key? key}) : super(key: key);
+class ArticleApp extends StatelessWidget {
+  ArticleApp({Key? key}) : super(key: key);
+
+  final _router = GoRouter(routes: [
+    GoRoute(
+      path: '/',
+      builder: (_, __) => const HomePage(),
+      routes: [
+        for (Example example in examples) //
+          GoRoute(
+            path: example.path,
+            builder: (_, __) => ExampleContainer(example),
+          )
+      ],
+    ),
+  ]);
 
-  // This widget is the root of your application.
   @override
   Widget build(BuildContext context) {
-    return MaterialApp(
-      title: 'Flutter Demo',
+    return MaterialApp.router(
+      routeInformationProvider: _router.routeInformationProvider,
+      routeInformationParser: _router.routeInformationParser,
+      routerDelegate: _router.routerDelegate,
+      title: 'Flutter par la pratique',
       theme: ThemeData(
-        // This is the theme of your application.
-        //
-        // Try running your application with "flutter run". You'll see the
-        // application has a blue toolbar. Then, without quitting the app, try
-        // changing the primarySwatch below to Colors.green and then invoke
-        // "hot reload" (press "r" in the console where you ran "flutter run",
-        // or simply save your changes to "hot reload" in a Flutter IDE).
-        // Notice that the counter didn't reset back to zero; the application
-        // is not restarted.
         primarySwatch: Colors.blue,
       ),
-      home: const MyHomePage(title: 'Flutter Demo Home Page'),
     );
   }
 }
 
-class MyHomePage extends StatefulWidget {
-  const MyHomePage({Key? key, required this.title}) : super(key: key);
-
-  // This widget is the home page of your application. It is stateful, meaning
-  // that it has a State object (defined below) that contains fields that affect
-  // how it looks.
-
-  // This class is the configuration for the state. It holds the values (in this
-  // case the title) provided by the parent (in this case the App widget) and
-  // used by the build method of the State. Fields in a Widget subclass are
-  // always marked "final".
-
-  final String title;
-
-  @override
-  State<MyHomePage> createState() => _MyHomePageState();
-}
-
-class _MyHomePageState extends State<MyHomePage> {
-  int _counter = 0;
-
-  void _incrementCounter() {
-    setState(() {
-      // This call to setState tells the Flutter framework that something has
-      // changed in this State, which causes it to rerun the build method below
-      // so that the display can reflect the updated values. If we changed
-      // _counter without calling setState(), then the build method would not be
-      // called again, and so nothing would appear to happen.
-      _counter++;
-    });
-  }
+class HomePage extends StatelessWidget {
+  const HomePage({Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
-    // This method is rerun every time setState is called, for instance as done
-    // by the _incrementCounter method above.
-    //
-    // The Flutter framework has been optimized to make rerunning build methods
-    // fast, so that you can just rebuild anything that needs updating rather
-    // than having to individually change instances of widgets.
     return Scaffold(
       appBar: AppBar(
-        // Here we take the value from the MyHomePage object that was created by
-        // the App.build method, and use it to set our appbar title.
-        title: Text(widget.title),
+        title: const Text('Flutter par la pratique'),
+      ),
+      body: ListView.builder(
+        itemBuilder: _buildItem,
+        itemCount: examples.length,
       ),
-      body: Center(
-        // Center is a layout widget. It takes a single child and positions it
-        // in the middle of the parent.
-        child: Column(
-          // Column is also a layout widget. It takes a list of children and
-          // arranges them vertically. By default, it sizes itself to fit its
-          // children horizontally, and tries to be as tall as its parent.
-          //
-          // Invoke "debug painting" (press "p" in the console, choose the
-          // "Toggle Debug Paint" action from the Flutter Inspector in Android
-          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
-          // to see the wireframe for each widget.
-          //
-          // Column has various properties to control how it sizes itself and
-          // how it positions its children. Here we use mainAxisAlignment to
-          // center the children vertically; the main axis here is the vertical
-          // axis because Columns are vertical (the cross axis would be
-          // horizontal).
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            const Text(
-              'You have pushed the button this many times:',
-            ),
-            Text(
-              '$_counter',
-              style: Theme.of(context).textTheme.headline4,
-            ),
-          ],
-        ),
+    );
+  }
+
+  Widget _buildItem(BuildContext context, int index) {
+    final example = examples[index];
+
+    return ListTile(
+      leading: Icon(
+        example.icon,
+        color: Theme.of(context).primaryColor,
       ),
-      floatingActionButton: FloatingActionButton(
-        onPressed: _incrementCounter,
-        tooltip: 'Increment',
-        child: const Icon(Icons.add),
-      ), // This trailing comma makes auto-formatting nicer for build methods.
+      title: Text(example.title),
+      trailing: const Icon(Icons.chevron_right),
+      onTap: () => context.push('/${example.path}'),
     );
   }
 }
diff --git a/lib/styles.dart b/lib/styles.dart
new file mode 100644
index 0000000000000000000000000000000000000000..5b02ea4bbabe8507af9a7403309f74d5af9cf8e3
--- /dev/null
+++ b/lib/styles.dart
@@ -0,0 +1,6 @@
+class Insets {
+  static const double s = 4;
+  static const double m = 8;
+  static const double l = 16;
+  static const double xl = 32;
+}
diff --git a/lib/widgets/space.dart b/lib/widgets/space.dart
new file mode 100644
index 0000000000000000000000000000000000000000..cb311a05073346bf9c57929c8df5e0e1d8a00f0f
--- /dev/null
+++ b/lib/widgets/space.dart
@@ -0,0 +1,18 @@
+import 'package:article_flutter_riverpod/styles.dart';
+import 'package:flutter/material.dart';
+
+class HSpace extends StatelessWidget {
+  const HSpace(this.size, {Key? key}) : super(key: key);
+
+  static const s = HSpace(Insets.s);
+  static const m = HSpace(Insets.m);
+  static const l = HSpace(Insets.l);
+  static const xl = HSpace(Insets.xl);
+
+  final double size;
+
+  @override
+  Widget build(BuildContext context) {
+    return SizedBox(height: size);
+  }
+}
diff --git a/pubspec.lock b/pubspec.lock
index 26b1c4186a7b9ac2016c763aa5f7b9bf33a0ff75..34870fccd56a3161c123d0c070a4b018cc3a2377 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -81,6 +81,25 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_web_plugins:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  go_router:
+    dependency: "direct main"
+    description:
+      name: go_router
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "4.3.0"
+  js:
+    dependency: transitive
+    description:
+      name: js
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.6.4"
   lints:
     dependency: transitive
     description:
@@ -88,6 +107,13 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.0.0"
+  logging:
+    dependency: transitive
+    description:
+      name: logging
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.2"
   matcher:
     dependency: transitive
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 3e2cba0fa566bf04e0469ca5da0ccd9d5d38e558..83a50ea3bffd6808c4813209dc38f83b2f9aa86f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -35,6 +35,7 @@ dependencies:
   # Use with the CupertinoIcons class for iOS style icons.
   cupertino_icons: ^1.0.2
   flutter_riverpod: ^1.0.3
+  go_router: ^4.3.0
 
 dev_dependencies:
   flutter_test: