<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kokou AGBAVON</title>
    <description>The latest articles on DEV Community by Kokou AGBAVON (@bienvenuelisis).</description>
    <link>https://dev.to/bienvenuelisis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F493429%2F64f8faa5-43a1-4d8e-99ab-9ee8c05d6eb9.jpeg</url>
      <title>DEV Community: Kokou AGBAVON</title>
      <link>https://dev.to/bienvenuelisis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bienvenuelisis"/>
    <language>en</language>
    <item>
      <title>Behind every widget, there are an element and almost always a render object.</title>
      <dc:creator>Kokou AGBAVON</dc:creator>
      <pubDate>Tue, 19 Sep 2023 08:30:00 +0000</pubDate>
      <link>https://dev.to/bienvenuelisis/behind-every-widget-there-are-an-element-and-almost-always-a-render-object-5248</link>
      <guid>https://dev.to/bienvenuelisis/behind-every-widget-there-are-an-element-and-almost-always-a-render-object-5248</guid>
      <description>&lt;p&gt;DISCLAIMER: This is a sneak peek of what I learned on my Journey to Dive deep into the Flutter Framework. Everything said here was found on the web and in the Flutter framework project on GitHub. If a concept is incorrectly explained, feel free to mention it kindly in the comments section. To dive deeper into all the concepts introduced here, refer to the sources section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Widget: the central tower of a Flutter application.
&lt;/h2&gt;

&lt;p&gt;Everything in Flutter is a Widget; it’s the first amendment you must adopt on your journey to becoming a qualified Flutter developer. Widgets help us describe the user interface of our application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Widgets tree
&lt;/h3&gt;

&lt;p&gt;Every Flutter app is, from some perspective, primarily a tree of widgets. The simplicity of its APIs and the variety of its catalogue make widgets the main element of the framework's attractiveness. From the primary widget in the main file to the last icon, each element that appears on the screen is linked by a tree structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wqWsuqBR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s09fi86j8kluw5rszdto.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wqWsuqBR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s09fi86j8kluw5rszdto.gif" alt="Animation showing Flutter widgets arborescence" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  To be stateful or not? That's the question.
&lt;/h3&gt;

&lt;p&gt;StatelessWidget is used for part of the user interface that relies only on the properties passed to its constructor. Conversely, StatefulWidget is used for interfaces that can change dynamically or depend on some internal data (aka state).&lt;/p&gt;

&lt;p&gt;Talking about StatefulWidget, let's have a quick reminder of the life cycle of a StatefulWidget.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gGm23rLc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2cstdk1dp8jr1dlwxe4u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gGm23rLc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2cstdk1dp8jr1dlwxe4u.png" alt="StatefullWidget lifecycle" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;createState: Create the state of the Widget. This method is called whenever a StatefulWidget is being inserted at a location in the widgets tree.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;initState: Perform the widget state initialization. This method is called after the widget is inserted into the widgets tree.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;didChangeDependencies: Called to notify that at least one of the widget's state dependencies has changed. This method always triggers the rebuild of the widget. It is therefore the ideal place to carry out operations that are too expensive to be included in the body of the build method; and which will be executed at each rebuild.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;build: Responsible for building the user interface given a particular location (BuildContext).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this stage, the Widget is built for the first time. Two methods can trigger a rebuild of the user interface represented by this widget.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;setState: This powerful trick helps us rebuild our user interface, to reflect our new state. Internally it notifies the widget that its state object has changed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;didUpdateWidget: This method is called when the widget configuration (e.g. class properties) changes. It helps associate (under certain circumstances) the new widget with the same State object.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A widget's life ends when it is removed from the widget tree, and its resources released.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;deactivate: This method is called when the widget is removed from the tree. At this step, the widget can either be reinserted in the tree at another location or removed forever.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;activate: This method is called before a widget is reintroduced in the widget tree after its removal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dispose: It's the last stage. The widget won't be reinserted in the thee, so its resources can be safely released.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Under the hood of a Widget.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ST6Kyqge--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rkmy3mfq1oprad7nt5gf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ST6Kyqge--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rkmy3mfq1oprad7nt5gf.jpg" alt="Under the hood of a widget there is an Element" width="500" height="666"&gt;&lt;/a&gt;&lt;br&gt;
The second thing you learn the day you want to dig a little deep under the hood of the framework is that a Widget mainly describes the configuration of an Element. If you take a look at this Element, it is described as the instantiation of a Widget at a particular location in the tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Element: the essential companion of every Widget.
&lt;/h2&gt;

&lt;p&gt;An Element is the companion of every widget. It’s responsible for how the view description we provide with our widget is painted and mounted (in our widget tree). It keeps track of where widgets are located in the tree, alongside other widgets.&lt;/p&gt;

&lt;p&gt;As we know, widgets are immutable. So when a widget changes (meaning its properties values changed and a rebuild was triggered), there are two cases :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The new widget has the same runtime type and key as the old one: in this case, the element remains associated with the new widget.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Otherwise, the element is removed from our tree, and a new element is created and associated with the new widget. This element can now be mounted in our tree and appear on the screen.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our Element extends a class that we are more familiar with, BuildContext.&lt;/p&gt;

&lt;h2&gt;
  
  
  BuildContext: the widget location handler.
&lt;/h2&gt;

&lt;p&gt;He is soberly described as a handler of the location of a widget in the widget tree. In other words, he helps the widget figure out where it is located in the tree of widgets.&lt;/p&gt;

&lt;p&gt;It is an abstract class that exposes useful methods and properties (mounted, size., …) about our widget. Each widget has its own BuildContext.&lt;br&gt;
Because it handles the location of a widget in the tree, the BuildContext value associated with a Widget can change over time to reflect the Widget's new location in the tree.&lt;/p&gt;

&lt;p&gt;You may have already encountered the warning, that tries to prevent you from accessing the context after an an asynchronous operation. The only way to check if a context is still associated with a widget (i.e. the widget is still mounted in the tree) is to check the mounted property value.&lt;/p&gt;

&lt;h2&gt;
  
  
  RenderObject : the unsung heroes.
&lt;/h2&gt;

&lt;p&gt;We have stated recently that Element(s) were responsible for rendering Widgets. We omitted to specify that this task is delegated to RenderObject(s). The name of the Component speaks for itself.&lt;/p&gt;

&lt;p&gt;To complete this task, the RenderObject component implements layout and painting protocols. RenderObject associated with the Widget is created when it's been inserted in the tree (the createRenderObject method is called to achieve this).&lt;br&gt;
After the object is created, and attached to a slot in the tree, it calls successively three methods :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The performLayout method helps compute the layout of the widget using constraints information provided by the parent widget.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The paint method provides a visual appearance to the widget given a PaintContext (a place to perform draw operations) and an Offset.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The describeSemanticsConfiguration method helps report semantics associated with this object. It’s generally used for accessibility purposes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After this operation, the Widget appears on the screen. Another method can be called later: updateRenderObject. He is responsible for updating the render object when the associated widget description changes. This method will eventually call the three precited methods, depending on what values that changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  So many trees
&lt;/h2&gt;

&lt;p&gt;So as we stated, there are three trees in every Flutter application :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The Widget Tree: Contains configurations and descriptions of Elements. In fact, for us as developers, it helps us describe how our application interface, must be rendered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Element Tree: Handles lifecycles and arranges widgets into a hierarchy. It’s responsible for placing our widget into a location in the Widget tree. It also associates a rendering object with each Widget that needs it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The RenderObject Tree: Contains information about widget layouts, and sizing and is responsible for painting.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RS340QM1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3hwvmlnvu3ueuvxrf7ds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RS340QM1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3hwvmlnvu3ueuvxrf7ds.png" alt="The three tree in Flutter" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What if I told you, there are more than three trees? Let's see that next time.&lt;/p&gt;

&lt;p&gt;In the next blog post, we will dive into Element and explore its lifecycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sources.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://hackernoon.com/a-deep-dive-into-how-flutter-works-under-the-hood-w02u37pz"&gt;A Deep Dive into How Flutter Works ‘Under the Hood’ | HackerNoon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/surf-dev/flutter-under-the-hood-binding-2b0ea65e5314"&gt;Flutter Under the Hood: Binding | by Mikhail Zotyev | Surf (medium.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@mbixjkee1392/flutter-under-the-hood-owners-2ec741d45bea"&gt;Flutter Under the Hood: Owners | by Mikhail Zotyev | Medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?app=desktop&amp;amp;v=cq34RWXegM8"&gt;How to build a RenderObject - YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/flutter/flutter"&gt;Flutter Framework - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>contentwriting</category>
      <category>google</category>
    </item>
    <item>
      <title>Arrête d’être un·e junior·e</title>
      <dc:creator>Kokou AGBAVON</dc:creator>
      <pubDate>Mon, 24 Jul 2023 02:06:57 +0000</pubDate>
      <link>https://dev.to/bienvenuelisis/arrete-detre-une-juniore-72o</link>
      <guid>https://dev.to/bienvenuelisis/arrete-detre-une-juniore-72o</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Cet article est une traduction d’un article originellement publié sous le nom de &lt;a href="https://kentcdodds.com/blog/stop-being-a-junior"&gt;&lt;strong&gt;Stop being a junior&lt;/strong&gt;&lt;/a&gt; par &lt;a href="https://kentcdodds.com/"&gt;Kent C. Odds&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es tu un·e développeur·se junior·e ? Si ta réponse est oui, comment tu sais ? Es ce que parce ton titre dans ton travail actuel c’est : &lt;em&gt;Développeur·se Junior·e&lt;/em&gt; ? Ou bien est ce parce que tes collègues font le travail le plus intéressant et tu es souvent cantonné·e aux tâches les plus répétitives ou à résoudre les bugs les plus simples ? Ou simplement tu estimes que tu n’as pas encore assez &lt;em&gt;rouler ta bosse&lt;/em&gt; pour pouvoir te débarrasser définitivement de l’appellation &lt;em&gt;Junior·e&lt;/em&gt; ?&lt;/p&gt;

&lt;p&gt;Peu importe ton positionnement actuel, j’aimerais te dire d’arrêter d’être un·e junior·e. &lt;strong&gt;Arrête maintenant.&lt;/strong&gt; J’ai discuté avec beaucoup de personnes qui commence leur conversation avec moi en disant &lt;em&gt;“Je viens juste de commencer…”&lt;/em&gt; ou &lt;em&gt;“Je suis juste un&lt;/em&gt;·e &lt;em&gt;junior&lt;/em&gt;·e_, …”&lt;em&gt;; ce à quoi je réponds _“C’est génial. Bienvenue dans le monde du développement logiciel.”&lt;/em&gt;, pour après découvrir qu’elles travaillent comme développeur·se·s d’applications depuis plus d’un an et demi. C’est quelque chose qui me surprend. Et cela arrive si souvent que j’ai décidé d’écrire un article de blog sur comment se sortir de cet éternelle posture de junior·e et commencer par agir positivement pour sa carrière.&lt;/p&gt;

&lt;h2&gt;
  
  
  La tech évolue à une grande vitesse
&lt;/h2&gt;

&lt;p&gt;C’est très important de prime abord de dire ceci :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Il n’y a aucune durée minimum que vous devez passer à être un·e développeur·se junior·e avant de pouvoir prétendre à passer ce cap.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si vous avez déjà entendu ou lu un nombre d’années, sachez que c’est faux.&lt;/p&gt;

&lt;p&gt;Une des choses que j’aime le plus dans notre industrie, c’est qu’elle évolue rapidement. Avec à chaque instant une émergence de nouvelles technologies et une amélioration constante de l’existant, cela ne prend pas beaucoup de temps à un·e développeur·se qui se maintient informé·e des avancements dans son domaine, d’atteindre un niveau de connaissance qui rivalise avec ses pair·e·s qui ont plusieurs décennies d’expérience.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Md-DF7jZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.pexels.com/photos/13301268/pexels-photo-13301268.jpeg%3Fauto%3Dcompress%26cs%3Dtinysrgb%26w%3D1260%26h%3D750%26dpr%3D2" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Md-DF7jZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.pexels.com/photos/13301268/pexels-photo-13301268.jpeg%3Fauto%3Dcompress%26cs%3Dtinysrgb%26w%3D1260%26h%3D750%26dpr%3D2" alt="Monter le Kilimandjaro" width="800" height="955"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imaginez que le développement logiciel ce soit une montée d'une colline avec un pourcentage de pente constant. Monter la colline depuis la base c'est avoir de l'expérience. Mais les nouveaux développeur·se·s ne commencent pas l'ascension par la base ; ils rejoignent les développeur·se·s expérimenté·e·s là où il·elle·s se trouvent actuellement. Ainsi il ne leur faut pas longtemps pour être dans le rythme ; peu importe depuis combien de temps les autres ont commencé la montée. Oui vous manquerez un peu d'expérience ; vous trébucherez un peu plus. Mais &lt;em&gt;la nouvelle expérience&lt;/em&gt; vous l'acquérez ensemble. Mon analaogie n'est pas parfaite, mais je pense qu'elle est instructive.&lt;/p&gt;

&lt;p&gt;Bien entendu, il faut reconnaître que les personnes avec des décennies d'expérience possèdent une longueur d'avance sur les autres ; il n'y a pas que des avantages, mais il y en a. Les personnes expérimentées apprennent mieux et plus rapidement les nouveaux outils, bien souvent parce que souvent c'est des anciennes choses que les nouvelles sont tirées (&lt;em&gt;c'est au bout de l'ancienne corde qu'on tisse la nouvelle&lt;/em&gt;) ; bien que pas toujours, et être capable de désapprendre est également une aptitude à cultiver. Les développeur·se·s avec du vécu, repèrent plus facilement les problèmes potentiels dans le code, avant qu'ils ne soient critiques parce qu'il·elle·s compris au fil du temps comment les choses marchent dans cet écosystème, et qu'il·elle·s comprennent mieux les contraintes.&lt;/p&gt;

&lt;p&gt;Cela dit, les développeur·se·s avec de l'expérience sont également plus réticent·e·s à essayer les nouveaux outils ou technologies, et à l'inverser être plus &lt;em&gt;accroché·e·s à leur manière de faire les choses&lt;/em&gt;. La routine ou l'habitude de faire les choses d'une certaine manière peut les amener à faire l'impasse sur de nouvelles fonctionnalités dans les langages et outils. Cela peut leur faire rater la migration vers des changements majeurs dans l'écosystème.&lt;/p&gt;

&lt;p&gt;Ce que j'essaie de dire ici c'est que le rythme effréné auquel les changements interviennent dans l'industrie du développement logiciel :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Donne à tout un chacun l'opportunité de devenir un·e expert·e dans certaines technologies assez rapidement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Et si cette personne est capable de tempérer raisonnablement son enthousiasme avec une compréhension pragmatique des avantages de son manque d'expérience, elle peut avoir un puissant impact dans son travail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mon expérience personnelle
&lt;/h2&gt;

&lt;p&gt;Pendant mes études à l’université je faisais des stages en entreprise. Cela m’a permis d’appréhender le domaine dans lequel j’allais évoluer avant même d’être en capacité d’y travailler à plein temps. Donc lorsque j’ai obtenu mes diplômes, j’avais déjà pendant plus d’une année et demi, travaillé comme développeur d’applications à mi temps.&lt;/p&gt;

&lt;p&gt;Après l’obtention de mon diplôme, j’ai été embauché en tant qu'ingénieur logiciel en plein temps. Dans mon entreprise, j’avais du mal à me départir de mon statut de junior. Malgré que le fait que toute mon expérience se résumait à ces 18 mois, où je travaillais à mi temps tout en continuant mes études, j’avais l’impression de connaître aussi bien notre architecture logicielle que mes collègues, et cela me semblait injuste d’être cantonné à faire les tâches les moins prioritaires.&lt;/p&gt;

&lt;p&gt;Je voyais les tâches avec un challenge architecturelle élevée confié aux développeur·se·s expérimenté·e·s et je voulais également pouvoir être en charge de quelques unes. Toutefois, vu que j’étais encore en période de transition d’&lt;em&gt;étudiant stagiaire&lt;/em&gt; à employé à plein temps, j’avais le sentiment que tout le monde me considérait dans l’entreprise d’une certaine façon un peu comme &lt;em&gt;le stagiaire&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Peut être que j’aurais dû énoncé un peu plus clairement mes objectifs et ambitions, mais à ce moment j’ai décidé que la seule voix pour avoir plus de responsabilités était de changer de compagnie ; une compagnie où les gens ne me verraient pas comme &lt;em&gt;le stagiaire&lt;/em&gt;, mais juste comme un collègue.&lt;/p&gt;

&lt;p&gt;Et c’est ce que j’ai fait. 4 mois après être passé en plein temps, j’ai été recruté par une autre compagnie qui m’offrait une revalorisation salariale (plus de 50%) et 20% de mon temps, je travaillais sur l’architecture de notre code source. C’était indescriptible. Personne ne me voyait plus comme un stagiaire. Dans les faits, j’étais à un cheveu de devenir architecte logiciel dans une entreprise valorisée à plus de 250 millions de dollars, et cela seulement 4 mois après mon diplôme universitaire.&lt;/p&gt;

&lt;p&gt;Cela a été un pari gagnant pour eux également. Quand j’ai rejoint la société, elle était engagée dans une migration majeure de leur outil de développement pour le frontend. J’ai joué un rôle clé dans cette migration et c’était à la fin un succès retentissant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comment arrêter d’être un·e junior·e ?
&lt;/h2&gt;

&lt;p&gt;Au lieu de réfléchir à comment arrêter d’être quelque chose, pense plutôt à comment faire pour commencer à être quelque chose d’autre.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Que font les développeurs seniors dans ton entreprise ? Fais ça au lieu de faire ce que les développeurs juniors font. Et voilà.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Il est évident que ton entreprise fais plus confiance aux seniors et tu n’as pas envie d’outrepasser tes prérogatives ; mais sois volontaire pour prendre part dans la résolution des tâches plus complexes. Ne serait qu’en demandant à prendre part aux réunions. Prends des notes des zones d’incompréhensions, et pose des questions plus tard. Dans les prochaines réunions, tu pourras contribuer plus activement, et apporter des suggestions. Continues de travailler sur les sujets évoqués dans les réunions à la fin de celles ci.&lt;/p&gt;

&lt;p&gt;Évite d’être autoritaire ou impétueux. Vous pouvez acquérir beaucoup de connaissances rapidement, mais soyez conscient qu'acquérir de l’expérience limite l’utilité de ces connaissances. Donc sois respectueux de tes collègues. Trouves les personnes qui accepteront de prendre le temps de répondre à tes questions, et qui te permettront de combler le gap de ton inexpérience à mesure que tu gagnes en compétence.&lt;/p&gt;

&lt;p&gt;Utilise à ton avantage le rythme effréné de renouvellement de l’écosystème de la tech et fais toi le porte voix des nouvelles fonctionnalités dans les langages et outils de développement lors des échanges entre toi et tes collègues, quand le cadre s’y prête. Si aucun cadre n’est prévu pour échanger autour de la tech avec tes collègues, sois en l’initiateur.&lt;/p&gt;

&lt;p&gt;Sois volontaire pour animer des sessions de Talk lors des rencontres organisées dans les communautés locales de développeurs. Propose toi pour parler des sujets qui te passionnent lors des conférences.&lt;/p&gt;

&lt;p&gt;Parle de tes accomplissements, des tâches auxquelles tu as participé et décris quelle était ta contribution ; cela prouvera que tu contribues au delà de ta sphère de &lt;em&gt;simple junior&lt;/em&gt;·e. Fais leur penser : &lt;em&gt;“Ce dev est seulement un&lt;/em&gt;·e &lt;em&gt;junior&lt;/em&gt;·e_, et il_·elle &lt;em&gt;fait ça ? C’est peut-être pas un·e junior·e après tout.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Fais comprendre à ton manager tes ambitions, tes objectifs et tes attentes en tant que développeur·se. Tu dois exposer clairement et assez tôt à ton·ta responsable, tes objectifs et ton souhait de monter en grade. Il·elle pourra à son tour exprimer les attentes qu’il·elle a envers toi, afin d’être en mesure de te promouvoir à ce rôle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continue, jusqu’à atteindre ton objectif
&lt;/h2&gt;

&lt;p&gt;Je n’aime pas la phrase &lt;em&gt;“Fais semblant, jusqu’à ce que cela ne devienne réel.”&lt;/em&gt;, mais le résultat recherché y es. L’idée est d’agir au niveau où vous souhaitez être considéré·e, et éventuellement cela deviendra évident que vous êtes réellement à ce niveau.&lt;/p&gt;

&lt;p&gt;J’ai senti que je devais quitter l’entreprise avec laquelle j’étais pour atteindre le niveau auquel j’aspirais. J’aurais probablement pu y arriver avec l’entreprise dans laquelle j’étais déjà, si j’avais été plus patient. L’expérience y aurait été différente sûrement si je n’avais pas d’abord été recruté comme étudiant stagiaire. Ceci dit, parfois, si vous ne pouvez tout simplement pas enlever le costume de &lt;em&gt;junior·e&lt;/em&gt; là où vous êtes actuellement, vous devez envisager de chercher une autre opportunité.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;J’espère que cet article ne dénigre pas la quantité de travail que cela demande de gagner de l’expérience et d’avoir de l’impact dans cet industrie. Pour autant, mon objectif principal est d’inspirer mes compaires à élever leurs ambitions et leurs exigences. Vous êtes capable de plus que vous ne pensez. Je vous le promet.&lt;/p&gt;

&lt;p&gt;Vous n’avez plus besoin d’être un·e junior·e. C’est le moment de monter en grade.&lt;/p&gt;

&lt;p&gt;Bonne chance.&lt;/p&gt;

</description>
      <category>career</category>
      <category>junior</category>
      <category>advice</category>
      <category>teaching</category>
    </item>
    <item>
      <title>Will ChatGPT replace StackOverflow?</title>
      <dc:creator>Kokou AGBAVON</dc:creator>
      <pubDate>Mon, 05 Dec 2022 07:30:00 +0000</pubDate>
      <link>https://dev.to/bienvenuelisis/will-chatgpt-replace-stackoverflow-2h6g</link>
      <guid>https://dev.to/bienvenuelisis/will-chatgpt-replace-stackoverflow-2h6g</guid>
      <description>&lt;p&gt;If you are a developer, you already know StackOverflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  StackOverflow
&lt;/h3&gt;

&lt;p&gt;The site that lets you find best practices for implementing certain features, or the solution to that obscure bug that only happens at 4 am on full moon days. Its takeover by Prosus for 1.8 billion dollars had made people cringe, but it is clear that so far no functionality or change that would degrade the user experience. has not been added.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI &amp;amp; GPT-3
&lt;/h3&gt;

&lt;p&gt;But, you may be less familiar with OpenAI and GPT-3. OpenAI is an AI research lab, which created GPT, an autoregressive language model that uses deep learning to produce human-like text. GPT-3 (the third iteration of GPT) can absorb billions of references, articles, images and data on different topics and then re-serve them in a form very close to human language.&lt;/p&gt;

&lt;p&gt;Several services like Dall-E (a generator of images from text in English) have already been unveiled, the result each time being quite impressive.&lt;/p&gt;

&lt;h3&gt;
  
  
  GPT-Chat
&lt;/h3&gt;

&lt;p&gt;The latest service launched by OpenAI is GPT-Chat: accessible free of charge, it provides an answer to any type of question, in any field. The answers are each time precise and very detailed, as would be those of an expert in the field.&lt;/p&gt;

&lt;p&gt;So when you ask GPT-Chat, how to browse an array of keys &amp;amp; values in JavaScript, here is its answer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwayr561tley3vx37gap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwayr561tley3vx37gap.png" alt="Browse an array of keys &amp;amp; values in JavaScript" width="800" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With a supporting example and explanation, the AI tells you the best solution to this common problem in JavaScript. The icing on the cake completes with a second solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hg4ha9xvx6u61e2r6o0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hg4ha9xvx6u61e2r6o0.png" alt="Use instead Object.entries" width="725" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison GPT-Chat &amp;amp; StackOverflow
&lt;/h3&gt;

&lt;p&gt;So why not systematically use it because unlike StackOverFlow, where you can sometimes be overwhelmed by the number of responses and differing opinions, GPT-Chat offers a complete, detailed solution, with more time running between the answer and the question. After entering your question, a few seconds are enough for the AI to offer you an answer; no need to navigate between several pages, and you have the possibility of directly copying the codes offered.&lt;/p&gt;

&lt;p&gt;At the moment I see 3 main downsides to wider adoption:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Greater rigor in typed text.
&lt;/h3&gt;

&lt;p&gt;With GPT-Chat, you have to be precise. Because with one word, the answer changes completely. Let's ask the same question as before, but omitting a pronoun.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhyhl2z8pi6csojl01ri8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhyhl2z8pi6csojl01ri8.png" alt="A missed pronoun changes all. The solution only matches Javascript values arrays." width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To find you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First question: How to iterate over a keys and values array in Javascript?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second question: How to iterate over keys and values array in Javascript?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The proposed solution is valid only for simple arrays, consisting of a uniform list of elements, and with a little analysis, one can find inconsistency in it, even if the proposition is valid and will not throw exceptions.&lt;/p&gt;

&lt;p&gt;Thanks to search engines, this situation is less frequent, because very often they redirect us to the right solution even in the event of a typo, or convoluted sentences.&lt;/p&gt;

&lt;h3&gt;
  
  
  2 - A less human explanation.
&lt;/h3&gt;

&lt;p&gt;Consider the question with the most votes on StackOverflow.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why are operations on a sorted array faster than those on an unsorted array?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is the answer from GPTChat.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxs2zn2a4ecemu0kh44b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxs2zn2a4ecemu0kh44b.png" alt="COncise but verbous and a little mechanic/scientific from GPTChat" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This answer is correct, but nothing more. If we understand the answer, it means that we didn't need to ask the question.&lt;/p&gt;

&lt;p&gt;Comparing with the answer on StackOverflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpou82lb8i046cuf07wyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpou82lb8i046cuf07wyb.png" alt="Answer with context explanationation" width="742" height="1025"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Supporting image, the interlocutor first takes the time to pose the general context, with non-technical terms, before gradually bringing the subject back to the initial and final question to deepen the reflection.&lt;/p&gt;

&lt;p&gt;Not all answers on StackOverFlow are (and do not need) to be so qualitative and well-detailed. But this example illustrates the interpretation of the question and can modify the way of answering.&lt;/p&gt;

&lt;p&gt;The biggest difference is that the AI ​​is not able to determine the level of understanding of the interlocutor to adapt its response. It will probably explain in the same way and with the same terms, the theory of relativity; it does not matter if the interlocutor is a professor/researcher in physics, a student in physics, or a college student who wishes to document himself.&lt;/p&gt;

&lt;h3&gt;
  
  
  3 - Community, debate &amp;amp; contradictions.
&lt;/h3&gt;

&lt;p&gt;Like it or not, StackOverFlow's greatest strength is its community. The platform is created and operates in such a way as to encourage and encourage the contribution of the greatest number.&lt;/p&gt;

&lt;p&gt;On particular themes, the solution depends on many parameters. And this is where the multiple answers, the different opinions and the confrontation are useful because they allow the visitor to situate himself and choose by taking into account all the advantages and constraints of each solution.&lt;/p&gt;

&lt;p&gt;The other strong point of StackOverFlow is peer validation. A solution proven and tested by thousands of other developers offers a greater guarantee.&lt;/p&gt;

&lt;h3&gt;
  
  
  Different use cases.
&lt;/h3&gt;

&lt;p&gt;StackOverFlow will never be dethroned.&lt;/p&gt;

&lt;p&gt;Like Copilot, Intellisense, and advanced IDEs, GPTChat (even if it is not limited only to code) is only one more tool, in the increasingly rich palette of tools of the developer. Like any self-learning model, it will learn and self-correct and improve over time.&lt;/p&gt;

&lt;p&gt;StackOverFlow, or the GitHub Issues, will always be the best place for the trickier questions that require a less impersonal explanation, or more community endorsement.&lt;/p&gt;

&lt;p&gt;But next time, instead of waiting for the &lt;strong&gt;magic answer&lt;/strong&gt; on StackOverFlow for an hour, or days for &lt;em&gt;relatively simple questions&lt;/em&gt; (How do I trigger HookConsumerWidget rebuild in Flutter?), ask to &lt;a href="https://chat.openai.com/" rel="noopener noreferrer"&gt;GPT-Chat&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fwua30i0r95objbjocq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fwua30i0r95objbjocq.png" alt="It will offer you the beginning of a solution." width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>Jekyll Blog to Flutter News Application : Part 2 - Data modeling.</title>
      <dc:creator>Kokou AGBAVON</dc:creator>
      <pubDate>Mon, 28 Mar 2022 16:30:13 +0000</pubDate>
      <link>https://dev.to/bienvenuelisis/jekyll-blog-to-flutter-news-application-part-2-data-modeling-8o5</link>
      <guid>https://dev.to/bienvenuelisis/jekyll-blog-to-flutter-news-application-part-2-data-modeling-8o5</guid>
      <description>&lt;p&gt;This is the second article of our series : &lt;a href="https://blog.theresilient.dev/series/blog-to-flutter-app"&gt;Blog Website to Flutter News Application&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the last article we have configured our jekyll blog website to serve all contents throw a single API endpoint.&lt;/p&gt;

&lt;p&gt;As said already, at this stage we will assume that you have a fully hosted and functional jekyll project. Otherwise, you can clone this preconfigured &lt;a href="https://github.com/bienvenuelisis/mundana-theme-jekyll-to-flutter-news-app"&gt;repo&lt;/a&gt;. If you want to run it on your computer, you need to complete &lt;a href="https://jekyllrb.com/docs/installation/"&gt;Jekyll installation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data modeling.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  a.  Create your flutter application.
&lt;/h3&gt;

&lt;p&gt;So, obviousely, we need to create a new flutter application. Just run the&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;flutter create [project]&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 script (be sure to use a recent version of the flutter sdk).&lt;/p&gt;
&lt;h3&gt;
  
  
  b. Create &amp;amp; Generate Models for Jekyll Posts API.
&lt;/h3&gt;

&lt;p&gt;There are many ways to communicate with a Restful API in Flutter. &lt;/p&gt;

&lt;p&gt;First we need to create the models classes representation of our json objects. In order to speed up this part, we will use the &lt;a href="https://pub.dev/packages/json_to_model"&gt;json_to_model package&lt;/a&gt; which allows to generate model classes from JSON files. So all we need is to follow the installation instructions and create a &lt;em&gt;jsons&lt;/em&gt; directory at the Flutter project root. &lt;/p&gt;

&lt;p&gt;This directory will contain 5 files: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📃 &lt;em&gt;blog.json&lt;/em&gt; :
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "homepage": "",
    "version": "",
    "name": "",
    "description": "",
    "logo": "",
    "last_update": "@datetime",
    "expired": false,
    "favicon": "",
    "url": "",
    "disqus": "",
    "email": "",
    "paginate": "",
    "posts": "$[]article"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;📃 &lt;em&gt;article.json&lt;/em&gt; :
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "id": "",
    "slug": "",
    "url": "",
    "title": "",
    "date": "",
    "image": "",
    "featured": false,
    "premium": false,
    "sticky": false,
    "author": "$author",
    "read_time": "",
    "date_iso": "@datetime",
    "date_fr": "$date_article",
    "date_en": "$date_article",
    "category_main": "",
    "categories": [""],
    "tags": [""],
    "next": "$article_related",
    "previous": "$article_related",
    "comments": "",
    "summary": "",
    "content": ""
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;📃 &lt;em&gt;article-related.json&lt;/em&gt; :
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "id": "",
    "slug": "",
    "url": "",
    "title": "",
    "image": "",
    "author": "$author",
    "read_time": "",
    "date_fr": "",
    "date_en": "",
    "category_main": "",
    "tags": [""],
    "type": "@enum:post"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;📃 &lt;em&gt;author.json&lt;/em&gt; :
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "name": "",
    "avatar": "",
    "display_name": "",
    "gravatar": "",
    "email": "",
    "site": "",
    "twitter": "",
    "social": "",
    "instagram": "",
    "bio": ""
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;📃 &lt;em&gt;date-article.json&lt;/em&gt; :
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "day": "",
    "month": "",
    "year": "",
    "complete": ""
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After this, execute the command &lt;code&gt;flutter pub run json_to_model&lt;/code&gt;. A directory named &lt;em&gt;models&lt;/em&gt; with all models classes will be created. The most useful part of each classes, is the &lt;code&gt;fromJson&lt;/code&gt; method generated which we will use to convert JSON to model object.&lt;/p&gt;

&lt;p&gt;This is an example of the method body for the article model :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;factory Article.fromJson(Map&amp;lt;String,dynamic&amp;gt; json) =&amp;gt; Article(
    id: json['id'].toString(),
    slug: json['slug'].toString(),
    url: json['url'].toString(),
    title: json['title'].toString(),
    date: json['date'].toString(),
    image: json['image'].toString(),
    featured: json['featured'] as bool,
    premium: json['premium'] as bool,
    sticky: json['sticky'] as bool,
    author: Author.fromJson(json['author'] as Map&amp;lt;String, dynamic&amp;gt;),
    readTime: json['read_time'].toString(),
    dateIso: DateTime.parse(json['date_iso'] as String),
    dateFr: DateArticle.fromJson(json['date_fr'] as Map&amp;lt;String, dynamic&amp;gt;),
    dateEn: DateArticle.fromJson(json['date_en'] as Map&amp;lt;String, dynamic&amp;gt;),
    categoryMain: json['category_main'].toString(),
    categories: (json['categories'] as List? ?? []).map((e) =&amp;gt; e as String).toList(),
    tags: (json['tags'] as List? ?? []).map((e) =&amp;gt; e as String).toList(),
    next: ArticleRelated.fromJson(json['next'] as Map&amp;lt;String, dynamic&amp;gt;),
    previous: ArticleRelated.fromJson(json['previous'] as Map&amp;lt;String, dynamic&amp;gt;),
    comments: json['comments'].toString(),
    summary: json['summary'].toString(),
    content: json['content'].toString()
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  c. Setup basic UI layout.
&lt;/h3&gt;

&lt;p&gt;At this stage, we only created some interfaces and used fake data to make them look attractive : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Splash screen : first application page which appears until application loaded successfully.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ru_fHP-6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1648427832769/dzp0eM56z.jpg" alt="splash.jpg" width="480" height="1066"&gt;
&lt;/li&gt;
&lt;li&gt;Home page : Divided into two parts (featured posts and others posts sorted by most recent).
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--53TZEgFr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1648427711399/hIibXIfqw.jpg" alt="home.jpg" width="480" height="480"&gt;
&lt;/li&gt;
&lt;li&gt;All articles subdivided by category.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hhteCaWH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1648427855914/PrqbFFgKQ.jpg" alt="pages_2.jpg" width="480" height="480"&gt;
&lt;/li&gt;
&lt;li&gt;Favorited, To Read Later articles and Settings pages.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i4GnNWbu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1648484566716/DNLCTrA2L.jpg" alt="settings.jpg" width="720" height="720"&gt;
&lt;/li&gt;
&lt;li&gt;Article Page.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mFuqXzMA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1648428405064/5f95kj2rP.jpg" alt="article.jpg" width="480" height="1066"&gt;
&lt;/li&gt;
&lt;li&gt;Search Page.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6p5OPYF---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1648427911301/Wc6j0vYMa.jpg" alt="search.jpg" width="480" height="273"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No fear, I will provide my code implementation of these different pages and features at the end of the article. You will be free to modify and adapt it according to your needs.&lt;/p&gt;

&lt;p&gt;Our app UI layout is ready. So let's rock it ! We need to make it communicate with our Jekyll Posts API endpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  d. Add Jekyll JSON API integration.
&lt;/h3&gt;

&lt;p&gt;We have our models; so let's them operate with the API.&lt;/p&gt;

&lt;p&gt;Let's explain how our application works. After launching the app, we send a GET request to our blog posts API endpoint. Next, we parse our response body to a blog object that contains all of our posts. Then we display the content to the user. This is simple.&lt;/p&gt;

&lt;p&gt;In Flutter we need the &lt;a href="https://pub.dev/packages/http"&gt;http package&lt;/a&gt; to perform this operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; var request = await http.get(
    Uri.parse("https://myawesomejekyllblog.com/api"),
    headers: {"Accept": "Application/json"},
 );

 Blog blog = Blog.fromJson(jsonDecode(request.body));

 List&amp;lt;Article&amp;gt; myPosts = blog.posts;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It was simple wasn't it? With these three lines, and no network or data parsing error, we have all the contents of our blog.&lt;/p&gt;

&lt;p&gt;Now that we have our data, we need a bridge that allows us to pass this data to our widgets. It must also, depending on the states of the data (the image of the article is loaded, this article is in the favourites, etc.) or the events (click on an article, the user is no longer connected to a network , ...) perform specific actions (consult the content of an article, reload the rest of the articles in the list, ...).&lt;/p&gt;

&lt;p&gt;This in Flutter is called state management. The next chapter in &lt;a href="https://blog.theresilient.dev/series/blog-to-flutter-app"&gt;our series&lt;/a&gt; will try to cover this great area (with a specific plugin, Riverpod).&lt;/p&gt;

&lt;p&gt;In the meantime, you can clone the &lt;a href="https://github.com/bienvenuelisis/mundana-theme-jekyll-to-flutter-news-app"&gt;Jekyll blog&lt;/a&gt;, and &lt;a href="https://github.com/bienvenuelisis/jekylltoflutter"&gt;the Flutter project&lt;/a&gt; if you want to dig into the code a bit.&lt;/p&gt;

&lt;p&gt;So, what's your thoughts at this step ?&lt;/p&gt;

</description>
      <category>blog</category>
      <category>flutter</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Jekyll Blog to Flutter News Application : Part 1 - Introduction.</title>
      <dc:creator>Kokou AGBAVON</dc:creator>
      <pubDate>Tue, 15 Mar 2022 06:07:37 +0000</pubDate>
      <link>https://dev.to/bienvenuelisis/jekyll-blog-to-flutter-news-application-part-1-introduction-4che</link>
      <guid>https://dev.to/bienvenuelisis/jekyll-blog-to-flutter-news-application-part-1-introduction-4che</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Like the title indicates, in this series of articles, we will reach into the steps for convert an existing Jekyll Blog Website to a fully functional Flutter Mobile app. I will do my best to be as clear as possible, but some passages may be blurry because I am at the same time improving my English.&lt;/p&gt;

&lt;p&gt;So let's began.&lt;/p&gt;

&lt;p&gt;The content of these articles will be divide into three main parts.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Jekyll blogging website and GitHub pages.&lt;/li&gt;
&lt;li&gt;Communication between the application and the website via Jekyll JSON Posts API.&lt;/li&gt;
&lt;li&gt;User interface and features of the Flutter mobile app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I will not dwell on some topics, such as setting up Github Pages or customizing a Jekyll blog, because that is not the purpose of this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Jekyll Blogging and GitHub Pages.
&lt;/h3&gt;

&lt;p&gt;Jekyll + &lt;a href="https://pages.github.com/"&gt;GitHub Pages&lt;/a&gt; is one of the best couples to quickly set up a blog without significant financial investment. I started blogging with Jekyll without knowing a single Ruby syntax. I cloned a repository and started customizations.&lt;/p&gt;

&lt;p&gt;For those who use other blogging / CMS platforms, I will soon write other articles covering the same path, but starting from Wordpress, GetPublii...&lt;br&gt;
In the rest of the article we will assume that you already have a Jekyll blog hosted online or locally. &lt;/p&gt;

&lt;p&gt;If you don't have a Jekyll blog, but you want to follow the tutorial till the end, just clone a free template from &lt;a href="https://bootstrapstarter.com/categories/jekyll/"&gt;Bootstrap Starter&lt;/a&gt;. You will &lt;a href="https://jekyllrb.com/"&gt;customize it&lt;/a&gt; later. I particularly like &lt;a href="https://github.com/wowthemesnet/mediumish-theme-jekyll"&gt;Mediumish&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;At this step, i assume that you have a forked a Jekyll blog on GitHub. To host your pages with GitHub just go to your repo settings, section GitHub pages. You can activate hosting there and even setup custom domain name. By default GitHub associate your blog page to your github account (&lt;strong&gt;[username].github.io&lt;/strong&gt;). &lt;/p&gt;

&lt;p&gt;You are not limited to GitHub ; if you prefere GitLab, you can use instead &lt;a href="https://about.gitlab.com/stages-devops-lifecycle/pages/"&gt;GitLab Pages&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Communication between the application and the website via Jekyll JSON Posts API.
&lt;/h3&gt;

&lt;p&gt;The best way to make a mobile app communicate with a web service is to create a RESTful API. As with the Jekyll blog, the content is generated once when changes are detected, we do not need to configure a web service. All we need is a JSON endpoint which at all times contains all the blog information such as all the articles and other useful data.&lt;/p&gt;

&lt;p&gt;To achieve this, we need to have a little knowledge of how the Jekyll template works and the layout architecture. We also need to deepen our knowledge of Liquid filters.&lt;/p&gt;

&lt;p&gt;For this tutorial we will use this model :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
layout: null
permalink: /api/
#So your API will be accessible at &amp;lt;mydomain&amp;gt;/api
# newline_to_br - replace each newline (\n) with html break
# replace - replace each occurrence e.g. {{ 'foofoo' | replace:'foo','bar' }} #=&amp;gt; 'barbar'
# prepend - prepend a string e.g. {{ 'bar' | prepend:'foo' }} #=&amp;gt; 'foobar'
# append - append a string e.g. {{ 'foo' | append:'bar' }} #=&amp;gt; 'foobar'

---


{
    "homepage" : "{{ site.baseurl }}",
    "version"  : "1",
    "last_update" : "{{ site.time | date_to_xmlschema }}",
    "name": {{ site.name | smartify | jsonify}},
    "description": "{{ site.description }}",
    "logo": "{{ site.logo }}",
    "expired": false,
    "favicon": "{{ site.favicon }}",
    "url": "{{ site.baseurl }}",
    "disqus": "{{ site.disqus }}",
    "email": "{{ site.email }}",
    "paginate": "{{ site.paginate }}",
    "authors": {{ site.authors | jsonify}},
    "posts" : [{% for post in site.posts %}
        {
        "id":"{{post.id | slugify: "latin"}}",
        "slug":"{{post.title | slugify}}",
        "url":"{{site.baseurl}}{{post.url}}",
        "media":"MEDIA_NAME",
        "title":"{{post.title}}",
        "featured":{%if post.featured == nil || post.featured == '' %}false{% else %}{{post.featured}}{% endif %},
        "premium":{%if post.premium == nil || post.premium == '' %}false{% else %}{{post.premium}}{% endif %},
        "date":"{{post.date}}",
        "image":"{{ site.baseurl }}/{{post.image}}",
        "author":{{site.authors[post.author] | jsonify}},
        "read_time":"{{post.content | number_of_words | divided_by:180 }}",
        "date_iso":"{{ post.date | date_to_xmlschema }}",
        "date_en"     : {
            "day"   : "{{ post.date | date: "%d" }}",
            "month" : "{{ post.date | date: "%B" }}",
            "year"  : "{{ post.date | date: "%Y" }}",
            "complete"  : "{{ post.date | date: "%B, %d %Y" }}"
         },
         "date_fr"     : {
            "day"   : "{{ post.date | date: "%d" }}",
            "month" : {% assign m = post.date | date: "%-m" %}{% case m %}{% when '1' %}"Janvier"{% when '2' %}"Février"{% when '3' %}"Mars"{% when '4' %}"Avril"{% when '5' %}"Mai"{% when '6' %}"Juin"{% when '7' %}"Juillet"{% when '8' %}"Août"{% when '9' %}"Septembre"{% when '10' %}"Octobre"{% when '11' %}"Novembre"{% when '12' %}"Décembre"{% endcase %},
            "year"  : "{{ post.date | date: "%Y" }}",
            "complete"  : "{{ post.date | date: "%d" }} {% assign m = post.date | date: "%-m" %}{% case m %}{% when '1' %}Janvier{% when '2' %}Février{% when '3' %}Mars{% when '4' %}Avril{% when '5' %}Mai{% when '6' %}Juin{% when '7' %}Juillet{% when '8' %}Août{% when '9' %}Septembre{% when '10' %}Octobre{% when '11' %}Novembre{% when '12' %}Décembre{% endcase %} {{ post.date | date: "%Y" }}"
         },
        "category_main" : "{{post.categories | first }}",
        "categories" : {{post.categories | jsonify }},
        "tags" : {{post.tags | jsonify }},
        {%if post.next == nil %}"next" : {}, {% else %}"next" : {
            "id":"{{post.next.id | slugify: "latin"}}",
            "slug":"{{post.next.title | slugify}}",
            "url":"{{site.url}}{{post.next.url}}",
            "title":"{{post.next.title}}",
            "image":"{{site.baseurl}}/{{post.next.image}}",
            "author":{{site.authors[post.next.author] | jsonify}},
            "read_time":"{{post.next.content | number_of_words | divided_by:180 }}",
           "date_iso":"{{ post.next.date | date_to_xmlschema }}",
            "date_fr"     : "{{ post.next.date | date: "%B, %d %Y" }}",
             "date_en"     : "{{ post.next.date | date: "%d" }} {% assign m = post.next.date | date: "%-m" %}{% case m %}{% when '1' %}Janvier{% when '2' %}Février{% when '3' %}Mars{% when '4' %}Avril{% when '5' %}Mai{% when '6' %}Juin{% when '7' %}Juillet{% when '8' %}Août{% when '9' %}Septembre{% when '10' %}Octobre{% when '11' %}Novembre{% when '12' %}Décembre{% endcase %} {{ post.next.date | date: "%Y" }}",
            "category_main" : "{{post.next.categories | first }}",
            "type":"{{post.next.layout}}",
            "tags" : {{post.next.tags | jsonify }}
        }, {% endif %}
        {%if post.previous == nil %}"previous" : {}, {% else %}"previous" : {
            "id":"{{post.previous.id | slugify: "latin"}}",
            "slug":"{{post.previous.title | slugify}}",
            "url":"{{site.url}}{{post.previous.url}}",
            "title":"{{post.previous.title}}",
            "image":"{{site.baseurl}}/{{post.previous.image}}",
            "author":{{site.authors[post.previous.author] | jsonify}},
            "read_time":"{{post.previous.content | number_of_words | divided_by:180 }}",
           "date_iso":"{{ post.previous.date | date_to_xmlschema }}",
            "date_fr"     : "{{ post.previous.date | date: "%B, %d %Y" }}",
             "date_en"     : "{{ post.previous.date | date: "%d" }} {% assign m = post.previous.date | date: "%-m" %}{% case m %}{% when '1' %}Janvier{% when '2' %}Février{% when '3' %}Mars{% when '4' %}Avril{% when '5' %}Mai{% when '6' %}Juin{% when '7' %}Juillet{% when '8' %}Août{% when '9' %}Septembre{% when '10' %}Octobre{% when '11' %}Novembre{% when '12' %}Décembre{% endcase %} {{ post.previous.date | date: "%Y" }}",
            "category_main" : "{{post.previous.categories | first }}",
            "type":"{{post.previous.layout}}",
            "tags" : {{post.previous.tags | jsonify }}
        }, {% endif %}
        "comments"   : "",
        "summary":{{post.excerpt | smartify | jsonify }},    
        "content":{{post.content | jsonify }}
    } {% unless forloop.last %},{% endunless %}
    {% endfor %}
    ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So basically, this API returns blog information (logo, homepage, email, pagination, authors ...), saved in the Jekyll configuration file (_config.yml).&lt;br&gt;
Some information may seem unnecessary or redundant, such as the link to the homepage or the name of the blog. But they can be useful when you want to convert multiple blogs into one app.&lt;/p&gt;

&lt;p&gt;The most important thing then is to get all the articles. This is done with this syntax &lt;code&gt;{% for post in site.posts %}&lt;/code&gt;, which goes through all the articles. &lt;br&gt;
Apart from the basic information like the title, the URL, the date of the article, the image, the category, the tags, the summary and the content, we also collect some information which will be useful later:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;premium&lt;/em&gt; field will be used to Configure Google Ads service.&lt;/li&gt;
&lt;li&gt;*The previous * and * next * fields contain information on other articles related to this article.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;disqus&lt;/em&gt; field will helps us setup comments section with Disqus platform.&lt;/li&gt;
&lt;li&gt;Fields formatted like &lt;em&gt;date_lang&lt;/em&gt; are useful for internalization in a simplier way. You can also do it, in Flutter with &lt;em&gt;date_iso&lt;/em&gt; field and throw package like &lt;a href="https://pub.dev/packages/intl"&gt;intl&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;⚠️ You can name this file as you see fit, but it must obligatorily end with the &lt;code&gt;.json&lt;/code&gt; extension to force Jekyll engine to render it as a JSON file and not as a HTML one. I named mine simply as &lt;a href="https://gist.github.com/bienvenuelisis/8fb776b80eafc89a86369ee2cbb286a6"&gt;&lt;strong&gt;posts_api.json&lt;/strong&gt;&lt;/a&gt;. This is &lt;a href="https://bienvenuelisis.github.io/noir-meilleur-jekyll/api/"&gt;how it looks&lt;/a&gt;  when the API is implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. User interface and features of the Flutter mobile app.
&lt;/h3&gt;

&lt;p&gt;So based solely on the number of stars on GitHub, Flutter is one of the most popular mobile app development platforms in recent years.&lt;/p&gt;

&lt;p&gt;Flutter 2 was announced &lt;em&gt;recently&lt;/em&gt; and offers some very interesting features, so we will be using this version. To follow and understand the features that will be used in this part, you don't need to be a Flutter expert. One year ago, I had never written Dart code.&lt;/p&gt;

&lt;p&gt;So, here are the features we will develop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jekyll JSON API Modeling &amp;amp; Integration.&lt;/li&gt;
&lt;li&gt;Link the app to a specific domain name (this is for those who have setup a custom domain for their blog).&lt;/li&gt;
&lt;li&gt;Limit app data usage (with caching &amp;amp; image backup).&lt;/li&gt;
&lt;li&gt;Offline mode.&lt;/li&gt;
&lt;li&gt;Integration of Google Ads &amp;amp; Facebook Network Audience.&lt;/li&gt;
&lt;li&gt;State management with Riverpod.&lt;/li&gt;
&lt;li&gt;Night Mode.&lt;/li&gt;
&lt;li&gt;Comments section with Disqus.&lt;/li&gt;
&lt;li&gt;Internationalization.&lt;/li&gt;
&lt;li&gt;Push Notifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A single article cannot cover all of these features and implementations. This tutorial will therefore be divided into several parts with the complete implementation of at least one feature per part.&lt;/p&gt;

&lt;p&gt;So see you in the next chapter of this &lt;a href="https://blog.theresilient.dev/series/blog-to-flutter-app"&gt;series&lt;/a&gt; to learn how to :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create our flutter application.&lt;/li&gt;
&lt;li&gt;Setup models according to our Jekyll Blog Posts API.&lt;/li&gt;
&lt;li&gt;Connect our models with the hosted API.&lt;/li&gt;
&lt;li&gt;Dynamize our interfaces by connecting it with the data received from the API.&lt;/li&gt;
&lt;li&gt;Manage our application states with Riverpod.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As already said, this is my first technical write. So feel free to reach me if something is not clear and to give advice so that future articles will be even more useful and understandable.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>jekyll</category>
      <category>firstpost</category>
      <category>blog</category>
    </item>
  </channel>
</rss>
