<?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: Xavier Dubois 🇫🇷</title>
    <description>The latest articles on DEV Community by Xavier Dubois 🇫🇷 (@juyn).</description>
    <link>https://dev.to/juyn</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%2F192495%2F0a95c149-71df-41f6-955d-f4677ca45321.jpg</url>
      <title>DEV Community: Xavier Dubois 🇫🇷</title>
      <link>https://dev.to/juyn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/juyn"/>
    <language>en</language>
    <item>
      <title>How to create a MVP ?</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Wed, 07 Jun 2023 10:16:33 +0000</pubDate>
      <link>https://dev.to/juyn/how-to-create-a-mvp--n7a</link>
      <guid>https://dev.to/juyn/how-to-create-a-mvp--n7a</guid>
      <description>&lt;p&gt;I made a small infographic to help startup and new comers to create an MVP.&lt;br&gt;
Please tell me what you think about it !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fXLU5c5K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.themoonfactory.fr/how-to-create-a-MVP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fXLU5c5K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.themoonfactory.fr/how-to-create-a-MVP.png" alt="How to create a MVP" width="800" height="1700"&gt;&lt;/a&gt; &lt;/p&gt;

</description>
      <category>startup</category>
      <category>howto</category>
      <category>infografic</category>
      <category>development</category>
    </item>
    <item>
      <title>How can I help you ?</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Wed, 31 May 2023 08:00:16 +0000</pubDate>
      <link>https://dev.to/juyn/how-can-i-help-you--62n</link>
      <guid>https://dev.to/juyn/how-can-i-help-you--62n</guid>
      <description>&lt;p&gt;Hello dear beginners !&lt;/p&gt;

&lt;p&gt;I want to get back to my previous love: helping you learning, make the good choices and grow as a healthy dev !&lt;/p&gt;

&lt;p&gt;But I wonder HOW can I help you the best ?&lt;br&gt;
Do you need articles ? Videos ? a newsletter with weekly tips and advices ?&lt;/p&gt;

&lt;p&gt;Please, tell me what &lt;strong&gt;you&lt;/strong&gt; think is the most valuable thing a 15+ XP dev/CTO/architect can do to help you !&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>beginners</category>
      <category>career</category>
      <category>programming</category>
    </item>
    <item>
      <title>A CMS with Stackbit, Netlify and NextJS</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Fri, 21 Apr 2023 13:46:55 +0000</pubDate>
      <link>https://dev.to/juyn/a-cms-with-stackbit-netlify-and-nextjs-14f1</link>
      <guid>https://dev.to/juyn/a-cms-with-stackbit-netlify-and-nextjs-14f1</guid>
      <description>&lt;p&gt;French version:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/juyn" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EuaKgFdQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--cuYije7C--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/192495/0a95c149-71df-41f6-955d-f4677ca45321.jpg" alt="juyn"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/juyn/un-cms-avec-stackbit-netlify-and-nextjs-22bd" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Un CMS avec Stackbit, Netlify et NextJS&lt;/h2&gt;
      &lt;h3&gt;Xavier Dubois 🇫🇷 ・ Apr 21 ・ 5 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#jamstack&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cms&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#nextjs&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Creating, hosting, and maintaining a CMS is not always an easy task.&lt;br&gt;
We have a wide range of alternatives, each with its strengths and weaknesses.&lt;/p&gt;

&lt;p&gt;Over the years and through various projects, I have implemented many of them: Wordpress, 100% custom CMS, Headless CMS with Contentful, Strapi... but I have never managed to meet all the criteria I was looking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplicity&lt;/li&gt;
&lt;li&gt;Quick setup&lt;/li&gt;
&lt;li&gt;Low hosting cost (or even none, completely free!)&lt;/li&gt;
&lt;li&gt;Performant&lt;/li&gt;
&lt;li&gt;100% customizable (there's nothing more frustrating than not being able to break free from the framework, right?)&lt;/li&gt;
&lt;li&gt;With a custom domain&lt;/li&gt;
&lt;li&gt;Retaining ownership of my data (hello Contentful!)&lt;/li&gt;
&lt;li&gt;GDPR compliant&lt;/li&gt;
&lt;li&gt;Easily integrating lambdas for form processing&lt;/li&gt;
&lt;li&gt;I know, it seems demanding, but I'm used to custom development and I like offering my clients a no-compromise solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I quickly became interested in JamStack, as it seemed that many of my criteria were met, but I hadn't yet figured out how to manage it professionally.&lt;/p&gt;
&lt;h2&gt;
  
  
  Understanding JamStack Architecture
&lt;/h2&gt;

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

&lt;p&gt;The term "Jamstack" is an acronym for JavaScript, APIs, and Markup.&lt;br&gt;
The main advantage of this architecture is that it eliminates the need for servers, which provides us with more security, performance, and easier content updates.&lt;/p&gt;

&lt;p&gt;Thanks to static content generation, we don't even have to manage a database. Everything is versioned by Git, simplifying backup and history strategies, and even allowing us to precisely identify who made a change.&lt;/p&gt;
&lt;h2&gt;
  
  
  Stackbit
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ub_7hQIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djkrz9megvr571sp9yxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ub_7hQIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djkrz9megvr571sp9yxg.png" alt="Stackbit logo" width="608" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stackbit is a SaaS service that facilitates the rapid creation of Jamstack sites, directly versioned on our Git repository.&lt;/p&gt;

&lt;p&gt;The major asset of this service lies in its content management interface. The Stackbit Studio offers the ability to build a user interface intuitively while providing deep customization of elements. This allows editorial teams to manage content autonomously.&lt;/p&gt;

&lt;p&gt;In addition, it offers a lot of customization, directly from the IDE and allows for easy tailoring.&lt;/p&gt;
&lt;h2&gt;
  
  
  Netlify
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mzhDGnt7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ywgf9lz0jnkydo24pi5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mzhDGnt7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ywgf9lz0jnkydo24pi5.png" alt="Netlify Logo" width="512" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, Stackbit is capable of hosting the CMS, either with a custom domain or via a Stackbit subdomain.&lt;br&gt;
However, I find their pricing too high ($90/month at the time of writing this article), and you must subscribe to the paid plan to benefit from a custom domain (among other things).&lt;/p&gt;

&lt;p&gt;I also needed to have control over certain Netlify elements, such as functions.&lt;/p&gt;

&lt;p&gt;Stackbit allows, in the site configuration, to choose whether it should manage hosting or not.&lt;br&gt;
I configured my project on Netlify to automatically publish any commits to the "main" branch of my CMS.&lt;br&gt;
And, since Netlify allows for a free custom domain, I was able to change the APEX of my site in seconds.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up the stack
&lt;/h2&gt;

&lt;p&gt;Creating the NextJS project is extremely simple and fast. I chose to let Stackbit do it.&lt;br&gt;
I just had to choose the technology I wanted to use and a base theme.&lt;br&gt;
Stackbit stored the project on my GitHub and automatically deployed the site to one of its Netlify instances.&lt;/p&gt;

&lt;p&gt;In a matter of seconds, I had the following stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A NextJS project&lt;/li&gt;
&lt;li&gt;A static site with my pages and data stored in Markdown&lt;/li&gt;
&lt;li&gt;A content editing interface directly on Stackbit&lt;/li&gt;
&lt;li&gt;A versioned project&lt;/li&gt;
&lt;li&gt;A site visible online on a Netlify subdomain&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Configuring Netlify
&lt;/h2&gt;

&lt;p&gt;As I want to host the site on a Netlify that I have complete control over, I added the project to my Netlify account and configured it.&lt;br&gt;
Here too, it's really fast!&lt;br&gt;
So, from the Netlify interface:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Import an existing project from a Git repository&lt;/li&gt;
&lt;li&gt;Connect to your Git provider&lt;/li&gt;
&lt;li&gt;Choose your project&lt;/li&gt;
&lt;li&gt;Configure it as follows:
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hNVMAhd6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u9x1gr6jn9qrqufm2bhd.png" alt="Netlify configuration" width="800" height="788"&gt;
&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;NETLIFY_NEXT_PLUGIN_SKIP&lt;/code&gt; environment variable set to &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Deploy&lt;/li&gt;
&lt;li&gt;Configure a custom domain if necessary&lt;/li&gt;
&lt;li&gt;Configure Stackbit not to manage hosting directly in the Studio settings&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Customization
&lt;/h2&gt;

&lt;p&gt;Now that we have an initialized and hosted project, we need to be able to customize it to check all the boxes.&lt;/p&gt;

&lt;p&gt;For this, Stackbit, once again, makes it easy for us.&lt;br&gt;
The site structure is based on pages composed of sections (blocks).&lt;br&gt;
Each page is based on a layout (a predefined set of sections).&lt;/p&gt;

&lt;p&gt;We will focus on creating a Section, more specifically creating the error section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jaD4MEDr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ju7hwyp9h2o7sakplj1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jaD4MEDr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ju7hwyp9h2o7sakplj1z.png" alt="Interface Stackbit pour la section ErrorSection" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the CMS, I need to give the editorial team control over the text on the 404 page.&lt;br&gt;
The module, very simple, thus allows to define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The page title&lt;/li&gt;
&lt;li&gt;The H1&lt;/li&gt;
&lt;li&gt;The H2&lt;/li&gt;
&lt;li&gt;The descriptive text&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this, we first need to create the YAML configuration file,  &lt;code&gt;.stackbit/models/ErrorSection.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Error Section&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ErrorSection&lt;/span&gt;
&lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Section&lt;/span&gt;
&lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sectionComponent&lt;/span&gt;
&lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;title&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Title&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;subtitle&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Subtitle&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then we create the NextJS component (simplified here to its maximum):&lt;br&gt;
&lt;code&gt;src/components/sections/ErrorSection/index.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as React from 'react';
import Picto from "../../atoms/Picto/Picto";

export default function ErrorSection(props) {
    return (
        &amp;lt;div className="container p-64 flex flex-col md:flex-row items-center justify-center px-5 text-gray-700"&amp;gt;
            &amp;lt;div className="max-w-md"&amp;gt;
                &amp;lt;div className="text-5xl font-dark font-bold"&amp;gt;{ props.title }&amp;lt;/div&amp;gt;
                &amp;lt;p
                    className="text-2xl md:text-3xl font-light leading-normal"&amp;gt; { props.subtitle }&amp;lt;/p&amp;gt;
                &amp;lt;p className="mb-8"&amp;gt;{ props.text}&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div className="max-w-lg"&amp;gt;
                &amp;lt;Picto
                    className={"cat"}
                    icon="cat"
                /&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to add the section to the components registry:&lt;br&gt;
&lt;code&gt;src/components/components-registry.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const components = {
    // ...

    'ErrorSection': dynamic(() =&amp;gt; import('./sections/ErrorSection'))
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it, our section is now visible in our sections library:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qcsKS_IR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cjf5347vyls3y9kbs9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qcsKS_IR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cjf5347vyls3y9kbs9g.png" alt="ErrorSection in Stackbit Studio" width="287" height="760"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a page
&lt;/h2&gt;

&lt;p&gt;We will now create the "not found" page from the Stackbit interface and add our section. The following file will be generated.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;content/pages/page-not-found.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PageLayout&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Found"&lt;/span&gt;
&lt;span class="na"&gt;sections&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ErrorSection&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;404'&lt;/span&gt;
    &lt;span class="na"&gt;subtitle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...Page&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;found'&lt;/span&gt;
    &lt;span class="na"&gt;button&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Home'&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;We&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;are&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sorry,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;it&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;seems&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;you&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;are&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trying&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;access&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;page&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;that&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;does&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exist&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;longer&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;available'&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we have created a 404 page, we might as well tell Netlify to use it.&lt;br&gt;
To do this, add the following block to the &lt;code&gt;netlify.toml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[redirects]]
   from = "/*"
   to = "/page-not-found"
   status = 404
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Going further****
&lt;/h2&gt;

&lt;p&gt;And since we're using the NextJS framework, we can do pretty much anything we want.&lt;br&gt;
If you want to have internationalization, install the &lt;code&gt;next-i18next&lt;/code&gt; or &lt;code&gt;react-intl&lt;/code&gt; packages (even though I believe Stackbit has a simpler built-in approach).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c_egaAes--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media0.giphy.com/media/3o7btNa0RUYa5E7iiQ/200w.gif%3Fcid%3D6c09b9524ne7jc21b361tkb1idulr3qdawi4r4bf9nkmao8s%26rid%3D200w.gif%26ct%3Dg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c_egaAes--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media0.giphy.com/media/3o7btNa0RUYa5E7iiQ/200w.gif%3Fcid%3D6c09b9524ne7jc21b361tkb1idulr3qdawi4r4bf9nkmao8s%26rid%3D200w.gif%26ct%3Dg" alt="Easy as that gif" width="200" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>cms</category>
      <category>nextjs</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>Un CMS avec Stackbit, Netlify et NextJS</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Fri, 21 Apr 2023 13:12:35 +0000</pubDate>
      <link>https://dev.to/juyn/un-cms-avec-stackbit-netlify-and-nextjs-22bd</link>
      <guid>https://dev.to/juyn/un-cms-avec-stackbit-netlify-and-nextjs-22bd</guid>
      <description>&lt;p&gt;English version&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/juyn" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EuaKgFdQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--cuYije7C--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/192495/0a95c149-71df-41f6-955d-f4677ca45321.jpg" alt="juyn"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/juyn/a-cms-with-stackbit-netlify-and-nextjs-14f1" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;A CMS with Stackbit, Netlify and NextJS&lt;/h2&gt;
      &lt;h3&gt;Xavier Dubois 🇫🇷 ・ Apr 21 ・ 5 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cms&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#nextjs&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#jamstack&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Créer, héberger et maintenir un CMS n'est pas toujours une chose facile.&lt;br&gt;
Nous avons à notre disposition un grand nombre d'alternatives avec leurs points forts et leurs points faibles.&lt;/p&gt;

&lt;p&gt;J'ai, au fil des années et des projets, implémenté pas mal d'entre eux. Wordpress, CMS 100% custom, Headless CMS avec Contentful, Strapi ... mais je n'ai jamais réussi à réunir tous les critères que je cherchais :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplicité&lt;/li&gt;
&lt;li&gt;Rapidité de mise en place&lt;/li&gt;
&lt;li&gt;Faible coût d'hébergement (voire aucun, totalement gratuit !)&lt;/li&gt;
&lt;li&gt;Performant&lt;/li&gt;
&lt;li&gt;100% personnalisable (il n'y a rien de plus frustrant que de ne pas pouvoir sortir du cadre, non ?)&lt;/li&gt;
&lt;li&gt;Avec un domaine personnalisé&lt;/li&gt;
&lt;li&gt;En gardant la propriété de mes données (coucou Contentful !)&lt;/li&gt;
&lt;li&gt;Respectant le RGPD&lt;/li&gt;
&lt;li&gt;Pouvant intégrer facilement des lambdas pour traiter les formulaires&lt;/li&gt;
&lt;li&gt;Je sais, cela semble exigeant, mais je suis habitué au développement sur-mesure, et j'aime offrir à mes clients une solution sans concessions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Très rapidement, je me suis intéressé à la JamStack, il me semblait que beaucoup de mes critères étaient respectés, mais je n'avais pas encore trouvé comment gérer cela de manière professionnelle.&lt;/p&gt;
&lt;h2&gt;
  
  
  Comprendre l'architecture JamStack
&lt;/h2&gt;

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

&lt;p&gt;Le terme "Jamstack" est un acronyme pour JavaScript, APIs et Markup.&lt;br&gt;
Le gros avantage de cette architecture est de se passer de serveurs, ce qui nous offre davantage de sécurité, de performance et facilite la mise à jour du contenu.&lt;/p&gt;

&lt;p&gt;Grâce à la génération de contenu statique, nous n'avons même pas de base de données à gérer. Tout est versionné par Git, simplifiant aussi la stratégie de backup, d'historique et nous permet même d'identifier précisément qui est à l'origine d'une modification.&lt;/p&gt;
&lt;h2&gt;
  
  
  Stackbit
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ub_7hQIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djkrz9megvr571sp9yxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ub_7hQIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djkrz9megvr571sp9yxg.png" alt="Stackbit logo" width="608" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stackbit est un service SaaS qui facilite la création rapide de sites Jamstack, directement versionnés sur notre dépôt Git.&lt;/p&gt;

&lt;p&gt;L'atout majeur de ce service réside dans son interface de gestion de contenu. Le Studio Stackbit offre la possibilité de construire une interface utilisateur de manière intuitive, tout en offrant une personnalisation approfondie des éléments. Cela permet aux équipes de rédaction de gérer le contenu en toute autonomie.&lt;/p&gt;

&lt;p&gt;En outre, il offre énormément de personnalisation, directement depuis l'IDE et permet d'aller vers le sur-mesure très facilement.&lt;/p&gt;
&lt;h2&gt;
  
  
  Netlify
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mzhDGnt7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ywgf9lz0jnkydo24pi5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mzhDGnt7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ywgf9lz0jnkydo24pi5.png" alt="Netlify Logo" width="512" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Par défaut, Stackbit est capable d'héberger le CMS, que ce soit avec un nom de domaine personnalisé ou via un sous-domaine stackbit.&lt;br&gt;
Néanmoins, je trouve leur tarification bien trop élevée (90 $/mois à l'heure où j'écris cet article) et il faut souscrire à l'offre payante pour bénéficier d'un nom de domaine personnalisé (entre autres).&lt;/p&gt;

&lt;p&gt;Aussi, j'avais besoin d'avoir la main sur certains éléments Netlify, comme les fonctions.&lt;/p&gt;

&lt;p&gt;Stackbit permet, dans la configuration du site, de choisir s'il doit gérer, ou non, l'hébergement.&lt;br&gt;
J'ai donc configuré mon projet sur Netlify pour qu'il publie automatiquement tout commit sur la branche "main" de mon CMS.&lt;br&gt;
Et, comme Netlify permet d'avoir un domaine personnalisé gratuitement, j'ai pu modifier l'APEX de mon site en quelques secondes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Mise en place de la stack
&lt;/h2&gt;

&lt;p&gt;La création du projet NextJS est ultra simple et rapide. J'ai fait le choix de laisser Stackbit le faire.&lt;br&gt;
J'ai juste eu à choisir la techno que je souhaitais utiliser ainsi qu'un thème de base.&lt;br&gt;
Stackbit a stocké le projet sur mon GitHub et a déployé automatiquement le site sur une de ses instances Netlify.&lt;/p&gt;

&lt;p&gt;En quelques secondes, je me retrouve avec la stack suivante :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Un projet NextJS&lt;/li&gt;
&lt;li&gt;Un site statique avec mes pages et données stockées en Markdown&lt;/li&gt;
&lt;li&gt;Une interface d'édition de contenu directement sur Stackbit&lt;/li&gt;
&lt;li&gt;Un projet versionné&lt;/li&gt;
&lt;li&gt;Un site visible en ligne sur un sous domaine netlify&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Configuration de Netlify
&lt;/h2&gt;

&lt;p&gt;Comme je souhaite héberger le site sur un Netlify sur lequel j'ai totalement la main, j'ai ajouté le projet sur mon compte Netlify et je l'ai configuré.&lt;br&gt;
Ici aussi, c'est vraiment rapide !&lt;br&gt;
Ainsi, depuis l'interface Netlify:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Importez un projet existant à partir d'un dépôt Git&lt;/li&gt;
&lt;li&gt;Connectez-vous à votre fournisseur Git&lt;/li&gt;
&lt;li&gt;Choisissez votre projet&lt;/li&gt;
&lt;li&gt;Configurez-le comme ci-dessous:
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hNVMAhd6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u9x1gr6jn9qrqufm2bhd.png" alt="Netlify configuration" width="800" height="788"&gt;
&lt;/li&gt;
&lt;li&gt;Ajoutez la variable d'environnement &lt;code&gt;NETLIFY_NEXT_PLUGIN_SKIP&lt;/code&gt; définie sur &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Déployez&lt;/li&gt;
&lt;li&gt;Configurez un nom de domaine personnalisé si nécessaire&lt;/li&gt;
&lt;li&gt;Configurez Stackbit pour ne pas gérer l'hébergement directement dans les paramètres du Studio&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Personnalisation
&lt;/h2&gt;

&lt;p&gt;Maintenant que nous avons un projet initialisé et hébergé, nous devons être en mesure de le personnaliser pour cocher toutes les cases.&lt;/p&gt;

&lt;p&gt;Pour cela, Stackbit, encore une fois, nous rend la chose aisée.&lt;br&gt;
La structure du site repose sur des pages constituées de sections (blocs).&lt;br&gt;
Chaque page est basée sur un layout (un ensemble de sections prédéfini).&lt;/p&gt;

&lt;p&gt;Nous allons ici nous intéresser à la création de Section, plus précisément à la création de la section d'erreur.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jaD4MEDr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ju7hwyp9h2o7sakplj1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jaD4MEDr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ju7hwyp9h2o7sakplj1z.png" alt="Interface Stackbit pour la section ErrorSection" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dans le cadre du CMS, j'ai besoin de donner la main à l'équipe de rédaction sur le texte de la page 404.&lt;br&gt;
Le module, très simple, permet donc de définir :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Le titre de la page&lt;/li&gt;
&lt;li&gt;Le H1&lt;/li&gt;
&lt;li&gt;Le H2&lt;/li&gt;
&lt;li&gt;Le texte déscriptif&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour cela, nous devons d'abord créer le fichier YAML de configuration, &lt;code&gt;.stackbit/models/ErrorSection.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Error Section&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ErrorSection&lt;/span&gt;
&lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Section&lt;/span&gt;
&lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sectionComponent&lt;/span&gt;
&lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;title&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Title&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;subtitle&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Subtitle&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Puis nous créons le component NextJS (simplifié ici à son maximum):&lt;br&gt;
&lt;code&gt;src/components/sections/ErrorSection/index.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as React from 'react';
import Picto from "../../atoms/Picto/Picto";

export default function ErrorSection(props) {
    return (
        &amp;lt;div className="container p-64 flex flex-col md:flex-row items-center justify-center px-5 text-gray-700"&amp;gt;
            &amp;lt;div className="max-w-md"&amp;gt;
                &amp;lt;div className="text-5xl font-dark font-bold"&amp;gt;{ props.title }&amp;lt;/div&amp;gt;
                &amp;lt;p
                    className="text-2xl md:text-3xl font-light leading-normal"&amp;gt; { props.subtitle }&amp;lt;/p&amp;gt;
                &amp;lt;p className="mb-8"&amp;gt;{ props.text}&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div className="max-w-lg"&amp;gt;
                &amp;lt;Picto
                    className={"cat"}
                    icon="cat"
                /&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enfin, nous devons ajouter la section au registre de composants:&lt;br&gt;
&lt;code&gt;src/components/components-registry.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const components = {
    // ...

    'ErrorSection': dynamic(() =&amp;gt; import('./sections/ErrorSection'))
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et c'est fait, notre section est maintenant visible dans notre bibliothèque de sections :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qcsKS_IR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cjf5347vyls3y9kbs9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qcsKS_IR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cjf5347vyls3y9kbs9g.png" alt="ErrorSection in Stackbit Studio" width="287" height="760"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Créer une page
&lt;/h2&gt;

&lt;p&gt;Nous allons maintenant créer la page "not found" depuis l'interface Stackbit et y ajouter notre section. Le fichier suivant sera généré.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;content/pages/page-not-found.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PageLayout&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Found"&lt;/span&gt;
&lt;span class="na"&gt;sections&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ErrorSection&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;404'&lt;/span&gt;
    &lt;span class="na"&gt;subtitle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...Page&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;non&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trouvée'&lt;/span&gt;
    &lt;span class="na"&gt;button&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Accueil'&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Nous&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sommes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;désolé,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;apparement&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;vous&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;essayez&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;consulter&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;une&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;page&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;qui&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;n’existe&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pas&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ou&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;n’est&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;plus&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;disponible'&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Puisque nous avons créé une page 404, autant indiquer à Netlify de l'utiliser.&lt;br&gt;
Pour cela, il faut ajouter le bloc suivant au fichier &lt;code&gt;netlify.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[redirects]]
   from = "/*"
   to = "/page-not-found"
   status = 404
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Aller plus loin
&lt;/h2&gt;

&lt;p&gt;Et comme nous utilisons le framework NextJS, nous pouvons faire à peu près tout ce que nous voulons.&lt;br&gt;
Si vous souhaitez avoir de l'internationalisation, installez les packages &lt;code&gt;next-i18next&lt;/code&gt; ou &lt;code&gt;react-intl&lt;/code&gt; (même si je crois que Stackbit a une approche plus simple built-in).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c_egaAes--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media0.giphy.com/media/3o7btNa0RUYa5E7iiQ/200w.gif%3Fcid%3D6c09b9524ne7jc21b361tkb1idulr3qdawi4r4bf9nkmao8s%26rid%3D200w.gif%26ct%3Dg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c_egaAes--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media0.giphy.com/media/3o7btNa0RUYa5E7iiQ/200w.gif%3Fcid%3D6c09b9524ne7jc21b361tkb1idulr3qdawi4r4bf9nkmao8s%26rid%3D200w.gif%26ct%3Dg" alt="Easy as that gif" width="200" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>jamstack</category>
      <category>cms</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Benevolent code review</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Wed, 09 Mar 2022 23:45:09 +0000</pubDate>
      <link>https://dev.to/juyn/benevolent-code-review-1ean</link>
      <guid>https://dev.to/juyn/benevolent-code-review-1ean</guid>
      <description>&lt;p&gt;Doing a code review is an exercise that seems fairly uncomplicated at first glance. After all, it's just reading code and pointing out anything we think isn't right, right?&lt;/p&gt;

&lt;p&gt;But we often forget that very often we find ourselves on the other side of the mirror and that it is our code that is being audited. It is the fruit of our labor that is the center of attention of our peers.&lt;br&gt;
And, depending on the level of benevolence of our colleagues, the exercise can suddenly become much less comfortable!&lt;/p&gt;

&lt;p&gt;The word is out (well, you already had it in the title of the article!): we are of course going to talk about benevolence, mainly in the field of code review.&lt;br&gt;
Why mainly? Quite simply because in my opinion benevolence should be the basis of any interaction with our colleagues on a daily basis, regardless of the context!&lt;/p&gt;

&lt;p&gt;Let's start by listing our personas, they will be our guinea pigs throughout this article.&lt;br&gt;
We have:&lt;br&gt;
Junior, our junior who has 2 years of XP in the code. He has just left school and is very very motivated&lt;br&gt;
Chrichri, our lead dev, an old timer with 15 years of XP&lt;br&gt;
Our senior dev team, the no-names. The brute force of our team&lt;/p&gt;

&lt;h2&gt;
  
  
  Captain Obvious
&lt;/h2&gt;

&lt;p&gt;We are going to start by pointing out what should be obvious, what should be one of the first things that our engineering schools teach us.&lt;br&gt;
This evidence is a truth that must be accepted as quickly as possible in order to successfully experience the exercise of code review.&lt;/p&gt;

&lt;p&gt;Come on, enough suspense: “We are not our code”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2F3o7btW7VDxqrhJEnqE%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2F3o7btW7VDxqrhJEnqE%2Fgiphy.gif" alt="Ah !"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It may sound silly, but it's true. If so yes.&lt;br&gt;
Our code is the result of a combination of circumstances, it depends on (and this is a non-exhaustive list!):&lt;br&gt;
Our knowledge at the time T when we wrote it&lt;br&gt;
Context (Was the environment noisy? Did we have a 3-year-old child in our legs because we have all been confined for months?)&lt;br&gt;
The time we had to allocate to this feature (we see you project managers)&lt;br&gt;
From the existing codebase&lt;br&gt;
The quality of the coffee at our disposal (or tea, or beer)&lt;/p&gt;

&lt;p&gt;There is also another argument that I find essential in favor of the dissociation of the man and the artist (well, of the coder and his code what): we are much more thing in life than a simple piece of code, and even if having the stamp of our colleagues is a real pleasure for the ego, it is important to keep a distance and put things into perspective.&lt;/p&gt;

&lt;h2&gt;
  
  
  I am a benevolent reviewer
&lt;/h2&gt;

&lt;p&gt;Take into account the level of XP&lt;br&gt;
The code written by our friend Junior should not be evaluated under the same spectrum as that written by Chrichri. We cannot have the same level of requirement simply because they do not have the same technical background.&lt;/p&gt;

&lt;p&gt;Our comments must therefore reflect this distinction.&lt;br&gt;
Be careful, I'm not saying that on the pretext that a junior dev wrote the code so you have to let everything pass. No, I'm saying we can approach things differently.&lt;/p&gt;

&lt;p&gt;Chrichri will undoubtedly be able to welcome a comment that is straightforward, with little context, and that goes straight to the point, like the example below. This does not prevent precision and benevolence, just we can afford to develop the message less.&lt;/p&gt;

&lt;p&gt;On the other hand, when Junior wrote the same code then we can surely take the time to detail our approach. Explain to him the interest of using a translation file for his character strings, for example.&lt;/p&gt;

&lt;h3&gt;
  
  
  The imperative you shall not use
&lt;/h3&gt;

&lt;p&gt;You have seen it on the examples above I used the conditional to express my comments.&lt;br&gt;
The reason is that 90% of the time my comments are suggestions, not orders.&lt;br&gt;
Of course, if I see a bug then I would use a different wording to clearly convey the imperative side of the change, but this is the only case where I will allow myself that.&lt;/p&gt;

&lt;p&gt;The comment that we put is above all there to help our valiant developer to initiate a reflection, even a discussion, and I am absolutely convinced that it is impossible if we give orders!&lt;/p&gt;

&lt;p&gt;And then, I don't know about you, but I will very very quickly be annoyed if my dev friends spend their time telling me what to do and how to do it ;-)&lt;/p&gt;

&lt;h3&gt;
  
  
  Source?
&lt;/h3&gt;

&lt;p&gt;Let's put ourselves in situations:&lt;br&gt;
Junior, our beloved junior, submitted a PR regarding a feature that generates statistics for a country on the 1st of every month.&lt;br&gt;
He wrote a “getStatsForPastMonth” method which takes the ID of a country and a date as parameters.&lt;br&gt;
The prototype is therefore the following (sorry for the less technical among you):&lt;br&gt;
public function getStatsForPastMonth(int $countryId, DateTime $fromDate)&lt;/p&gt;

&lt;p&gt;In the review, of course Chrichri will ask him why he felt the need to integrate the second parameter, since the business specification indicates that we work on a fixed date.&lt;/p&gt;

&lt;p&gt;Junior replies that he did this to make it possible to write unit and functional tests that are repeatable regardless of the day the test is run (let's all take a moment to congratulate Junior for integrating tests and thinking about their reproducibility!).&lt;/p&gt;

&lt;p&gt;Chrichri therefore finds himself here with a choice. He can respond to the choice:&lt;/p&gt;

&lt;p&gt;“You shouldn't change your method to make testing easier. You have to remove the $fromDate parameter and mock the date instead”&lt;br&gt;
“You shouldn't change your method to make testing easier, that's really not good practice. You should use a mock instead. Here is a link to the library I have in mind and an example I have already written on such a project. On the other hand, you will have to modify the way in which you instantiate such a variable because it will not be compatible”&lt;/p&gt;

&lt;p&gt;In your opinion, which choice will allow Junior to improve his skills and correct his code with the least amount of back and forth possible?&lt;br&gt;
The question was quickly answered, especially since it took Chrichri a few more minutes at most, and saved Junior hours of migraine!&lt;/p&gt;

&lt;p&gt;I have voluntarily taken the example of Junior here because it is easier, but nothing prevents us from having this kind of feedback with all the developers of course. The goal of a code review is to help others progress and not just to ensure the quality of the code base.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't be so negative!
&lt;/h3&gt;

&lt;p&gt;It's harder to compliment than to criticize, and that's a shame.&lt;br&gt;
This paragraph will be very short. It boils down to telling you that I love you. And that you shouldn't hesitate to tell your colleagues, especially during a code review.&lt;/p&gt;

&lt;p&gt;Let him know that you find his implementation super cool or that you learned something. It boosts the ego and it is as good for the one who wrote the comment as for the one who will read it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Love yourself, damn it!
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fblog.codacy.com%2Fwp-content%2Fuploads%2F2015%2F04%2F6a424-07lfxgwbienqvig5h.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fblog.codacy.com%2Fwp-content%2Fuploads%2F2015%2F04%2F6a424-07lfxgwbienqvig5h.gif" alt="thumbs up"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm a happy developer
&lt;/h2&gt;

&lt;p&gt;Now let's try to ask ourselves how, as developers, we can better experience code reviews.&lt;/p&gt;

&lt;h3&gt;
  
  
  We are never better served than by ourselves!
&lt;/h3&gt;

&lt;p&gt;I have a reputation for being lacking in rigor. Not necessarily in my code, but often in the sidelines (document, swagger annotations, typos …) and that made me dread code reviews.&lt;br&gt;
Then I was given a great piece of advice: take the time to do my own code review.&lt;/p&gt;

&lt;p&gt;I take about ten minutes to read my code, but not in my IDE, no, directly on Github or Gitlab. It allows me to change perspective and spot mistakes much more easily.&lt;br&gt;
And, generally, this proofreading allows me to save a lot of time that I would have lost processing feedback (and feeding my impostor syndrome to the detriment of my ego).&lt;/p&gt;

&lt;h3&gt;
  
  
  Make life easier for the reviewer
&lt;/h3&gt;

&lt;p&gt;There's nothing like being in a bad mood starting a code review than having no idea what it's about, having to look up the ticket on Jira and then having to figure out how to make that damn piece of code work on your own. !&lt;/p&gt;

&lt;p&gt;Always take the time when writing a PR to think about how our peers will be able to work effectively.&lt;br&gt;
So take the time to include a description containing the essentials to understand the business and be able to test the code functionally.&lt;br&gt;
It's not about order&lt;br&gt;
I know, I've said it before. And no, I'm not rambling.&lt;/p&gt;

&lt;p&gt;The reviewer has made a lot of feedback, preferably with a benevolent tone (but he may not have read this article!) and you tell yourself that, indeed, a lot of his feedback is well-founded.&lt;br&gt;
But, and we all know it, the life of a developer is not only governed by our desire to do well. There is a reality of projects, deadlines, ticket estimates… in short, we don't always have time to do everything.&lt;br&gt;
Or maybe you think not, his comment telling you that you should rather name your variable $foo when $bar suits you perfectly is not justified.&lt;/p&gt;

&lt;p&gt;If you are in this situation then I have a very, very important thing to tell you. This is a secret that has been too well kept until now.&lt;br&gt;
You have the right to say no. Yes yes, you read correctly. It is completely ok to say no to a return on a PR.&lt;/p&gt;

&lt;p&gt;Of course, I do not advise you to answer a "no" as an answer but on the contrary to accept this invitation to the discussion by explaining, briefly, why you think that it is a mistake, or why you think your way is better.&lt;/p&gt;

&lt;p&gt;On the other hand, if your only argument is the time that the fix will take you, then you have to be careful. Putting it off often means never fixing it. I can only advise you too much to talk to your project manager to find the time you need. After all, project managers are empathetic, benevolent beings who only think about your well-being and your happiness, so everything should be fine. But that is a topic!&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask for help
&lt;/h2&gt;

&lt;p&gt;Whether you are a junior or not, you have to know how to ask for help, and this applies perfectly to benevolent code review.&lt;br&gt;
If the return seems insurmountable to you or you have no idea how to do what you are asked to do, then do not hesitate to ask for help. It can be a point for the person who gave you the feedback to explain to you what he has in mind or downright a pair-programming session to help you implement it.&lt;/p&gt;

&lt;p&gt;You can also request that the review be done directly in pair-programming. Very often, this saves a lot of time and makes the exercise much more humane.&lt;/p&gt;

&lt;p&gt;I want to end this love-filled article by inviting you to remember that we all do our best. Whether it's the proofreader or the proofreader, we all make mistakes and we always will.&lt;br&gt;
Let's be indulgent and kind with others, of course, but especially with ourselves&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.pinimg.com%2Foriginals%2F89%2F24%2F29%2F892429ef4fbbd9467ccfe8178bcea536.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.pinimg.com%2Foriginals%2F89%2F24%2F29%2F892429ef4fbbd9467ccfe8178bcea536.gif" alt="self hug"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>team</category>
      <category>beginners</category>
    </item>
    <item>
      <title>ESN, agence, client final: comment choisir ?</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Mon, 08 Feb 2021 14:10:12 +0000</pubDate>
      <link>https://dev.to/juyn/esn-agence-client-final-comment-choisir-ec2</link>
      <guid>https://dev.to/juyn/esn-agence-client-final-comment-choisir-ec2</guid>
      <description>&lt;p&gt;This post will only exist in French since this topic is only relevant for French developers on the French job market ;-)&lt;/p&gt;

&lt;p&gt;Nous, les devs, nous avons énormément de chance: nous avons le choix.&lt;br&gt;
Nous avons le choix de la techno, de travailler en présentiel ou en remote mais aussi du type d'entreprise pour lequel nous travaillons.&lt;br&gt;
Ce n'est pas donné à tout le monde d'avoir autant de liberté quant à sa carrière et l'orientation que nous lui donnons.&lt;/p&gt;

&lt;p&gt;Mais, comme Oncle Ben le dit si bien:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SYzRDuJ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/http://fabcopywriter.com/wp-content/uploads/2019/08/fabcopywriting-redaction-pouvoir-mots-1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SYzRDuJ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/http://fabcopywriter.com/wp-content/uploads/2019/08/fabcopywriting-redaction-pouvoir-mots-1.gif" alt="great power spiderman" width="498" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il n'est pas toujours simple de s'y retrouver dans l'informatique, les technos évoluent très vite et le marché de l'emploi est un panier de crabe; il y a presque autant de recruteur IT que d'offre d'emploi, et ils ne sont pas tous de bon conseillers.&lt;/p&gt;

&lt;p&gt;Le monde du développement se découpe en 3 secteurs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les  &lt;del&gt;SSII&lt;/del&gt; ESN (Entreprise de Service du Numérique)&lt;/li&gt;
&lt;li&gt;Les clients finaux&lt;/li&gt;
&lt;li&gt;Les agences (digitales, WEB, marketing ...)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chaque secteur offre une expérience bien différente du métier de dev, autant par le quotidien que l'on y trouve que par les rémunérations ou l'ambiance générale.&lt;/p&gt;

&lt;p&gt;Je précise dès maintenant que cet article est basé sur mon expérience personnelle et sur celles de mes connaissances.&lt;br&gt;
Bien sûr, cela n'est pas vrai pour toutes les entreprises du secteur (et encore heureux !) et tu peux toi même avoir vécu une expérience totalement différente ! Je t'invite à venir en discuter en commentaire si c'est le cas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/VBxaJamsDUqc0/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/VBxaJamsDUqc0/giphy.gif" alt="Let's go sloth" width="360" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Les ESN (Entreprise de Service du Numérique)
&lt;/h2&gt;

&lt;p&gt;Je commence par le secteur le plus controversé par mes paires; le monde impitoyable de l'ESN (ou SSII, si t'es &lt;del&gt;vieux&lt;/del&gt; vrai).&lt;br&gt;
Les ESN externalisent leurs compétences en expertise informatique en envoyant (majoritairement) leurs devs en missions, plus ou moins temporaire, chez des clients.&lt;/p&gt;

&lt;p&gt;Le but du jeu pour le client c'est d'avoir une ressource opérationnelle immédiatement sans avoir à assumer le coût à long terme de la dite ressource.&lt;/p&gt;

&lt;h3&gt;
  
  
  Double XP
&lt;/h3&gt;

&lt;p&gt;Le plus gros avantage de l'ESN c'est l'expérience.&lt;br&gt;
L'essence même des entreprises de service est de proposer des missions courtes (de quelques mois à quelques années max), ce qui fait que tu vas avoir l'opportunité de travailler avec de nombreux clients différents.&lt;br&gt;
Et chaque client possède sa propre stack technique, son propre métier et ses propres contraintes.&lt;/p&gt;

&lt;p&gt;Tu dois donc, à chaque changement de mission, te réapproprier le projet et donc apprendre de nouvelles choses.&lt;/p&gt;

&lt;p&gt;Alors, bien sûr, l'ESN, dont le principal but est la rentabilité maximum, va essayer de capitaliser sur tes expériences précédente (si tu as fait du bancaire, tu risque fort de continuer à en faire) mais préfèrera tu proposer une mission totalement différente que de te laisser en inter-contrat.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rémunération
&lt;/h3&gt;

&lt;p&gt;L'ESN est réputée pour mal payer ses devs (cf objectif rentabilité), mais ce n'est pas la dernière du classement pour autant.&lt;br&gt;
La rémunération est calculée en fonction des diplômes, des compétences et de l'expérience.&lt;br&gt;
De mon expérience, il ne faut pas trop compter sur les primes annexes (participation &amp;amp; co) pour faire monter sa rémunération, et la négociation annuelle demande énormément de préparation pour aboutir à une augmentation substantielle. Pourquoi ? Car pour continuer à être rentable l'ESN doit répercuter ton augmentation aux clients. Et ça, c'est pas toujours simple !&lt;/p&gt;

&lt;p&gt;Les recruteurs tentent d'attirer les devs (surtout les plus juniors) avec les "à côtés".&lt;br&gt;
Comprendre que, comme il s'agit de boite brassant pas mal d'argent et ayant en générale d'autres activités lucratives, ils ont des locaux assez moderne et sympa.&lt;br&gt;
Et comme tu risque de passer un peu de temps sur le "plateau" (en mission ou inter-contrat dans les locaux de l'ESN directement et pas dans ceux du client).&lt;/p&gt;

&lt;p&gt;Alors oui, c'est cool d'avoir un babyfoot, une cafétéria, des massages, une conciergerie, un open space ultra moderne, des trotinettes en libre service dans les locaux ou encore des meet-up dans tes propres bureaux (ok, ça c'est vraiment cool !), mais ... ça ne permet pas de mettre du pain sur la table !&lt;/p&gt;

&lt;h3&gt;
  
  
  Évolution
&lt;/h3&gt;

&lt;p&gt;C'est compliqué, toujours à cause de cette satanée rentabilité !&lt;br&gt;
Former un employé, peu importe son secteur, c'est accepter d'investir dans l'employé et d'avoir une période où cet employé ne rapporte pas d'argent, vu qu'il est en formation.&lt;br&gt;
Et, même une fois formé, il faut un temps de montée en compétence avant d'espérer un retour sur investissement.&lt;/p&gt;

&lt;p&gt;Seulement, l'ESN a davantage intérêt à te garder en mission le plus souvent possible, c'est son seul moyen de faire de l'argent.&lt;br&gt;
Et si on ajoute à ça le turnover important en ESN, il n'y a pas vraiment d'avantage à offrir des formations (sauf si c'est pour signer une mission et ... te vendre en tant qu'expert sur la techno que tu ne connais pas encore, bien sûr !)&lt;/p&gt;

&lt;h3&gt;
  
  
  It's a trap !
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/GYeLcrWi5DMqs/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/GYeLcrWi5DMqs/giphy.gif" alt="It's a trap !" width="500" height="200"&gt;&lt;/a&gt;&lt;br&gt;
Oui, l'ESN c'est Double XP, mais il faut être prudent.&lt;br&gt;
Il y a loup, une bête du Gévaudan, un piège !&lt;/p&gt;

&lt;p&gt;Tous (ou presque) la redoute, et, une fois attrapé il est difficile d'y échapper !&lt;/p&gt;

&lt;p&gt;Je veux parler de la TMA (Tierce Maintenance Applicative) !&lt;br&gt;
Késako ? De la maintenance évolutive (ou pas), souvent pour de très très grosses boites (SNCF, Orange, EDF ...) qui ont des parcs applicatifs aussi vieux qu'énorme.&lt;/p&gt;

&lt;p&gt;Le problème c'est qu'une fois qu'on est montée en compétence sur ces applications (legacy ou non) il est difficile de faire autre chose, car le principe même de la TMA est d'avoir des ressources opérationnelles disponible en tout temps pour réagir dans le délai imparti en cas de problème en prod.&lt;/p&gt;

&lt;p&gt;Et, trouver un nouveau CDI après avoir stagner pendant des années sur des applications legacy, ça peut vite devenir compliqué !&lt;/p&gt;

&lt;h2&gt;
  
  
  Client final
&lt;/h2&gt;

&lt;p&gt;Un client final est appelé comme ça car il s'agit du client des ESN. C'est lui qui va payer ces boites pour avoir des devs de manière ponctuelle (ou pas).&lt;br&gt;
Mais certains préfèrent avoir une équipe en interne, soit car ils ont une croissance exponentielle et payer une ESN ne serait pas viable, soit car ils ont compris qu'internaliser son métier n'était pas une si mauvaise idée.&lt;/p&gt;

&lt;p&gt;Tu as 3 catégories de client final:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La startup&lt;/li&gt;
&lt;li&gt;L'éditeur&lt;/li&gt;
&lt;li&gt;l'entreprise classique&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chacune de ces catégorie peut offrir une expérience légèrement différente (surtout la startup), mais, dans l'ensemble les avantages et inconvénients sont assez semblable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maitre Jedi
&lt;/h3&gt;

&lt;p&gt;Autant en ESN tu risque de rester un Padawan sur plein de sujet car tu n'a pas le temps de devenir un expert sur un techno en particulier, autant tu va vite devenir un Maitre Jedi chez le client final.&lt;/p&gt;

&lt;p&gt;En effet, si le CTO de la boite est compétent, il est fort à parier qu'il capitalise sur les techno déjà implémentées pendant quelques années, au moins le temps d'avoir un bon retour sur investissement.&lt;br&gt;
Ce qui signifie que tu va avoir le temps d'apprendre les tenants et aboutissants de la stack technique.&lt;/p&gt;

&lt;p&gt;Bien sûr, tu peux te dire qu'au bout d'un moment, travailler sur le même projet peut devenir rébarbatif, hein ?&lt;br&gt;
Et tu aurais raison, même si cela n'est pas toujours vrai et dépend grandement du client.&lt;/p&gt;

&lt;p&gt;Si tu rejoins une boite en pleine croissance, il y a fort à parier qu'une refonte soit à l'ordre du jour pour suivre la croissance.&lt;br&gt;
Dans le cas d'une startup, selon quand tu rejoins l'équipe, tu peux avoir à gérer un changement de pivot, ou une levée de fond et, par conséquent un séisme technologique !&lt;/p&gt;

&lt;h3&gt;
  
  
  Rémunération
&lt;/h3&gt;

&lt;p&gt;Contrairement à l'ESN le client final investi dans son équipe. Son but, c'est de te conserver dans ses effectifs pour ne pas avoir à perdre du temps (et de l'argent) dans la formation d'un newbie, avec la perte obligatoire de compétence entre les deux devs.&lt;/p&gt;

&lt;p&gt;Du coup, même si le salaire de base n'est pas forcément importante, c'est un sujet qui peut vite évoluer, et la discussion est généralement assez ouverte sur le sujet.&lt;/p&gt;

&lt;p&gt;Il n'est pas rare dans une boite en pleine croissance de prendre 10% par an, ce qui n'est pas négligeable !&lt;/p&gt;

&lt;h3&gt;
  
  
  Évolution
&lt;/h3&gt;

&lt;p&gt;C'est peut être le meilleur des mondes pour évoluer, tant que tu es compétent.&lt;br&gt;
Chez le client final il y aura de gros challenge techniques à relever. Souvent.&lt;br&gt;
A la clé, il y a la possibilité d'évoluer dans l'organigramme.&lt;/p&gt;

&lt;p&gt;Si la croissance de l'entreprise est à deux chiffre, il y a fort à parier que l'équipe va grandir. C'est l'occasion de décrocher une place de Lead dev, de Product Owner ou même de CTO si tu rejoins l'entreprise assez tôt dans son développement.&lt;/p&gt;

&lt;h3&gt;
  
  
  It's (still) a trap !
&lt;/h3&gt;

&lt;p&gt;Bin oui. C'est pas le monde parfait non plus !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/LKTTAzGboJGzC/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/LKTTAzGboJGzC/giphy.gif" alt="I can't the office" width="480" height="270"&gt;&lt;/a&gt;&lt;br&gt;
Chez le client final, il y a aussi des pièges à éviter, et en plus, ils peuvent se déguiser en avantage, alors il faut vraiment être prudent !&lt;/p&gt;

&lt;p&gt;Oui, on peut facilement gratter une très bonne rémunération, mais ce n'est pas toujours le meilleur plan.&lt;br&gt;
Déjà, une trop grosse rémunération peut cacher une impossibilité d'évoluer dans l'entreprise. "On sait que tu es compétent, on le reconnais via ton salaire, mais nous ne pouvons rien t'offrir de plus".&lt;br&gt;
Et, si ce constat devait t'arriver, un second écueil apparaitra: comment se vendre au même prix chez une autre entreprise, sachant que tes compétences ne seront pas forcément aussi utiles et reconnues ?&lt;/p&gt;

&lt;p&gt;Un autre piège c'est de s'enfermer dans une techno sans voire que celle ci est en train de mourir.&lt;br&gt;
Elle peut être le coeur de métier pour ton entreprise, mais si cette dernière n'a pas pris le virage technologique, et que, toi, pris dans le confort du quotidien tu n'as pas continuer ta veille quotidienne, alors tu peux te retrouver à faire du COBOL dans un monde régit par Javascript et son armée de frameworks !&lt;/p&gt;

&lt;h2&gt;
  
  
  Les agences
&lt;/h2&gt;

&lt;p&gt;Je dois confesser avoir une (petite) préférence pour les agences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/5wWf7GR2nhgamhRnEuA/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/5wWf7GR2nhgamhRnEuA/giphy.gif" alt="It's true The Office" width="488" height="275"&gt;&lt;/a&gt;&lt;br&gt;
C'est un peu de meilleur des deux mondes, un savant mélange entre ESN et client final.&lt;/p&gt;

&lt;p&gt;Enfin, ça, c'est la théorie, dans les faits la réalité n'est pas toujours aussi rose !&lt;/p&gt;

&lt;p&gt;Comme pour les clients finaux il y a plusieurs catégories d'agences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les agences de communication (ou "digitales", c'est à la mode)&lt;/li&gt;
&lt;li&gt;Les agences WEB&lt;/li&gt;
&lt;li&gt;Les ESN qui s'assument pas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Je ne vais pas parler de la dernière catégorie, elle est assez facile à détecter lors du premier entretien: 90% des missions sont en régie chez le client !.&lt;br&gt;
Non, je vais me concentrer sur les 2 premières.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agence &lt;del&gt;Marketing&lt;/del&gt; / &lt;del&gt;de communication&lt;/del&gt;/ digitale
&lt;/h3&gt;

&lt;p&gt;Les agences de communications sont très centrés sur des projets avec assez peu de technique et de problématique métiers.&lt;br&gt;
L'objectif de l'équipe IT d'une agence de communication est d'offrir une offre complète: une expertise marketing et une mise une expertise opérationnelle.&lt;/p&gt;

&lt;p&gt;Le plus gros avantage est qu'on y travail souvent avec des clients prestigieux (et je parles des mastodontes SNCF, EDF et Orange comme le ferait un recruteur, mais de clients à forte réputation, comme Dior, Nike ou l’Élysée).&lt;br&gt;
On apprend donc forcément énormément et les projets demandent souvent une grande rigueur, car il en va de l'image de la marque.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/YiAgJl71eKEfPMUzmj/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/YiAgJl71eKEfPMUzmj/giphy.gif" alt="targeting without CRM data be like" width="182" height="182"&gt;&lt;/a&gt;&lt;br&gt;
L'inconvénient c'est qu'il s'agit souvent de site vitrine ou événementiel. Parfois un peu de e-commerce, mais c'est pas si répandue.&lt;br&gt;
Du coup, on peut vite s'ennuyer techniquement, mais c'est une expérience intéressant et très formatrice.&lt;br&gt;
La qualité WEB est un acquis qui te différenciera de la concurrence !&lt;/p&gt;

&lt;h3&gt;
  
  
  Les Agences Web
&lt;/h3&gt;

&lt;p&gt;Le mélange parfait entre client final et ESN !&lt;br&gt;
Une (grosse) dose d'expérience et de clients différents et une aussi grosse dose de valorisation de la part de ton employeur !&lt;/p&gt;

&lt;p&gt;L'agence WEB est, comme son nom l'indique, spécialisée dans le monde du WEB (mais, soyons honnête, mis à part l'embarqué, presque tout est "web" aujourd'hui) et a un fonctionnement très proche de celui d'une ESN: elle intervient ponctuellement pour répondre à un besoin.&lt;br&gt;
La différence ? L'agence WEB garde ses compétences en interne (majoritairement) et mise sur un turnover réduit.&lt;/p&gt;

&lt;p&gt;En effet les agences WEB ont tendance à essayer de faire "grandir" ses équipes et d'investir dedans afin d'agrandir son catalogue des possibles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Formation
&lt;/h3&gt;

&lt;p&gt;Forcément, qui dit investir dans ses équipes signifie qu'il est possible d'obtenir des formations assez facilement.&lt;br&gt;
La rentabilité et les journées non facturées sont ici aussi des enjeux stratégique, mais la volonté d'obtenir plus d'investissement et de compétences d'un employé prends souvent le dessus.&lt;/p&gt;

&lt;p&gt;Qui plus est, l'attrait de devenir un organisme de formation certifié encourage pas mal d'agence à faire profiter leurs employés de  nombreuses formations afin de pouvoir capitaliser doublement dessus.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rémunération
&lt;/h3&gt;

&lt;p&gt;Ici on retrouve pour moi les mêmes avantages que pour les clients finaux. Le salaire de base n'est pas forcément fou, mais il est possible de faire évoluer sa rémunération au fil des années.&lt;br&gt;
Néanmoins, le fait d'avoir un fonctionnement aussi proche de l'ESN remet sur la table un inconvénient de taille: toute augmentation doit être répercutée chez les clients pour espérer être rentable.&lt;/p&gt;

&lt;p&gt;Il faut donc avoir des nouvelles compétences à proposer pour convaincre !&lt;/p&gt;

&lt;h3&gt;
  
  
  Évolution
&lt;/h3&gt;

&lt;p&gt;Cela dépend grandement des agences. &lt;br&gt;
Celles qui privilégie l'intraprenariat peuvent offrir un éventail d'évolution infini et réunissent tous les éléments nécessaire pour t'emmener très loin.&lt;/p&gt;

&lt;p&gt;Mis à part cela, il y a très peu d'évolution interne, mis à part pour des rôles de lead ou d'archi. Par contre, d'un point de vue expérience l'agence est aussi riche que l'ESN !&lt;/p&gt;

&lt;h3&gt;
  
  
  Is it still a trap ?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o84szW0PrWZyUv0mA/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o84szW0PrWZyUv0mA/giphy.gif" alt="You were the chosen one !" width="480" height="208"&gt;&lt;/a&gt;&lt;br&gt;
Il y a forcément des pièges. &lt;br&gt;
Le plus important, et cela est aussi vrai pour les ESN par ailleurs, c'est l'investissement que l'on te demande.&lt;br&gt;
Les deadlines sont importantes et les sprint souvent chargés et il faut souvent du temps pour réussir à façonner tes chefs de projets pour que les estimations de tâches soit réalistes.&lt;/p&gt;

&lt;p&gt;Du coup, les 35 heures sont pas évidentes à respecter et on peut avoir du mal à trouver un équilibre vie pro/vie perso.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Je dirais que toutes les expériences se valent, mais qu'il faut choisir prudemment.&lt;br&gt;
Je conseillerais les yeux fermés les ESN à des juniors en sorti d'école. On y apprend énormément de choses, et même si l'ascension hiérarchique n'est pas assurée, c'est une très bonne opportunité pour se construire un CV digne de ce nom.&lt;/p&gt;

&lt;p&gt;Mis à part ça, je vous encourage tous, amis devs à réaliser la chance que nous avons et à en profiter.&lt;br&gt;
Je ne dis pas de changer de boulot tous les ans, mais nous avons la possibilité d'être des "Divas" et de trouver un nouvel emploi très facilement. Il n'y a donc presque aucune raison d'aller travailler tous les jours à reculons, en se plaignant toute la journée en se disant qu'on pourrait faire tellement mieux.&lt;br&gt;
Le job de vos rêves est quelque part dans cette jungle à vous attendre ! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o6ZsZaeq8wtUnGQ3m/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o6ZsZaeq8wtUnGQ3m/giphy.gif" alt="Like a diva" width="400" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
    </item>
    <item>
      <title>How to write bad-ass technical tests for your interviews ?</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Thu, 29 Aug 2019 21:20:57 +0000</pubDate>
      <link>https://dev.to/juyn/how-to-write-bad-ass-technical-tests-for-your-interviews-51ee</link>
      <guid>https://dev.to/juyn/how-to-write-bad-ass-technical-tests-for-your-interviews-51ee</guid>
      <description>&lt;p&gt;I don't know how it works in other countries, but, in France, during interviews, it usual to have a technical test.&lt;br&gt;
Sometimes you can do it from home, sometimes it's in live during the interview.&lt;/p&gt;

&lt;p&gt;There is a lot of posts about the second one, so I won't speak about it. Let's focus on the "homework technical test".&lt;br&gt;
I do code review on those for a while now, here is what I'm looking for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make it works
&lt;/h2&gt;

&lt;p&gt;My first concern is that the code works.&lt;br&gt;
I don't really care if the developer (especially if he is a junior) cover all the scope. I mean, it's better, but I prefer having an unfinished user story than a bugged one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean code
&lt;/h2&gt;

&lt;p&gt;We always have room for improvements, and, a lot of experienced developers don't have the cleanest code. I get it.&lt;br&gt;
But, technical tests are like a resume, I except at least to understand easily what you have done.&lt;/p&gt;

&lt;p&gt;If you are coding in PHP, I except PHPDoc for example,but also meaningful variable names, correct indentation and comments if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't do more
&lt;/h2&gt;

&lt;p&gt;If a scope is given, respect it. Don't over do.&lt;br&gt;
You may think that's a bonus and the reviewer will see how implicated you are, but it send another message: You don't know how to respect the scope of a user story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git
&lt;/h2&gt;

&lt;p&gt;Usually a Git repository is provided, and we except you to commit your code.&lt;br&gt;
It's alright if you don't master Git yet, but you have to be careful about some little things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do little commits, with explicit title/messages&lt;/li&gt;
&lt;li&gt;Don't hesitate to provide a Read me, explaining how you proceed and what you tried to do&lt;/li&gt;
&lt;li&gt;We'll check your GitHub. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ask for help
&lt;/h2&gt;

&lt;p&gt;Not all companies does it, but I always stay available for the recruits (and I provide a way to get in touch).&lt;br&gt;
That mean I except you to contact me if something is bothering you or if you are stuck.&lt;/p&gt;

&lt;p&gt;Google is good, but we are looking for team player, and that's a good skill to be able to ask for help.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write your own code
&lt;/h2&gt;

&lt;p&gt;I love copying a piece of the provided code, and look for it on Google.&lt;br&gt;
It's amazing how effective it is to disqualify a candidate.&lt;/p&gt;

&lt;p&gt;You can search for technical solutions or tutorials on the net, that's what a developer do for a living, but don't just copy/past the code.&lt;br&gt;
I am already sure that you know how to do that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write your own code&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't take too long
&lt;/h2&gt;

&lt;p&gt;We know you have a life, maybe kids, surely a full time job. That's ok.&lt;br&gt;
But don't take too much time to get back to the company, it send the wrong signal.&lt;/p&gt;

&lt;p&gt;You can't do it within the week ? No problems, but explain it, I'm sure it will be all good !&lt;/p&gt;

&lt;h2&gt;
  
  
  KISS
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep It Stupid Simple&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You have been asked for an API implementation. It is simple, right ?&lt;br&gt;
Let's your code reflect that.&lt;/p&gt;

&lt;p&gt;If you have been asked for 2 endpoints, on Symfony, I don't want to see any Interfaces, or complex paradigms.&lt;br&gt;
Just a controller, with as many object as requested and some tests.&lt;br&gt;
That's all folks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tests
&lt;/h2&gt;

&lt;p&gt;Not everybody know how to write unit or functional tests. But I always ask at least for unit tests.&lt;br&gt;
Try to do it, even if you are not sure. It shows implication and learning capacities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't get crazy with technologies
&lt;/h2&gt;

&lt;p&gt;90% of the time, a technology will be imposed. Well, it's because it will certainly be the technology you will be working with if you join the team.&lt;/p&gt;

&lt;p&gt;Recruiter ask for a Laravel implementation with Api Platform ? Don't use GraphQl !&lt;/p&gt;

&lt;h2&gt;
  
  
  Do your homework
&lt;/h2&gt;

&lt;p&gt;If the company have public repository, take a look. You may find some tips on how things are done by the team.&lt;br&gt;
It's always nice to see that the candidate will try to fit in (even if fresh ideas and mindset are always welcome)&lt;/p&gt;

&lt;h2&gt;
  
  
  Do it alone
&lt;/h2&gt;

&lt;p&gt;If you cheat, people will notice. And it's like lying on your resume, you can be fire for that. And you will.&lt;/p&gt;




&lt;p&gt;I hope this few advice will help you. &lt;br&gt;
Please share you advice in the comment section, I'll edit this post to add all the good ideas !&lt;/p&gt;

</description>
      <category>career</category>
      <category>codenewbie</category>
      <category>interview</category>
      <category>recruiting</category>
    </item>
    <item>
      <title>Enhanced your functional tests with Symfony (API context)</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Fri, 16 Aug 2019 09:52:17 +0000</pubDate>
      <link>https://dev.to/juyn/enhanced-your-functional-tests-with-symfony-api-context-nfg</link>
      <guid>https://dev.to/juyn/enhanced-your-functional-tests-with-symfony-api-context-nfg</guid>
      <description>&lt;p&gt;My team and I have a lot of micro services to develop and maintain, and, since the key of success for this kind of architecture is performance, it is our main concern while coding.&lt;/p&gt;

&lt;p&gt;Unfortunalty, Symfony does not provide a simple way for monitoring performances metrics other than the Profiler.&lt;/p&gt;

&lt;p&gt;TL;DR:&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j44qCh95--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/RwD8eyx.gif" class="article-body-image-wrapper"&gt;&lt;img alt="You shall not pass !" src="https://res.cloudinary.com/practicaldev/image/fetch/s--j44qCh95--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/RwD8eyx.gif"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;We wanted to be able to perform automatic checks on our performances:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Number of database queries&lt;/li&gt;
&lt;li&gt;Execution time (and not only the response time, which include too much variables)&lt;/li&gt;
&lt;li&gt;Memory used&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to be fast ?
&lt;/h2&gt;

&lt;p&gt;That's not the subject of this post, but I'll do a quick reminder about few requirements for  a fast API, in a Symfony context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have as less database queries as possible&lt;/li&gt;
&lt;li&gt;Don't have too much injected services&lt;/li&gt;
&lt;li&gt;Use as less as memory as possible&lt;/li&gt;
&lt;li&gt;Disable/remove all unused extra Symfony packages&lt;/li&gt;
&lt;li&gt;If possible, don't use Listeners&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  But, how'd you check that ?
&lt;/h2&gt;

&lt;p&gt;Symfony provides a very handfull tool to check some of the previous bullet points.&lt;br&gt;
It allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know the number of database queries&lt;/li&gt;
&lt;li&gt;Know how much memory your app is using&lt;/li&gt;
&lt;li&gt;Have information about performances&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Amazing,  right ? &lt;/p&gt;

&lt;p&gt;When I'm coding or doing a code review, it's one of the first thing I check.&lt;br&gt;
It's easy when you have a route to get all rows of a table, with a OneToMany relation to have an impressive number of queries, and that should not go to production !&lt;/p&gt;
&lt;h2&gt;
  
  
  What about functional tests ?
&lt;/h2&gt;

&lt;p&gt;Well, your code is OK on your machine, you have the right number of queries, you know your route don't consume too much memory and that it's fast enough.&lt;/p&gt;

&lt;p&gt;But I'm a paranoid developer, I don't trust code, not even mine. That's why I write unit tests, functional tests and integration tests.&lt;br&gt;
And none of this tests allow me to assert that my route has less than 5 database queries, and that the execution time (which if different than response time) is fast enough.&lt;/p&gt;

&lt;p&gt;I looked over, and I didn't find any easy way to do so. BlackFire.io do it, but it's expensive and a little bit too much for me.&lt;br&gt;
But, hey, I'm a developer, so let's do it myself, that'll be fun !&lt;/p&gt;

&lt;p&gt;First, where do I want to have access to this data ?&lt;/p&gt;
&lt;h3&gt;
  
  
  During unit tests ?
&lt;/h3&gt;

&lt;p&gt;Nah, I don't want to do database calls during thoses tests, and, I prefer not have to boot the kernel&lt;/p&gt;
&lt;h3&gt;
  
  
  During integration tests ?
&lt;/h3&gt;

&lt;p&gt;That might do the trick, but for now we don't go through CI before commiting, so that'll be triggered only before being push on production&lt;/p&gt;
&lt;h3&gt;
  
  
  During functional tests ?
&lt;/h3&gt;

&lt;p&gt;Yes ! That'd be &lt;strong&gt;perfect&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;We do that using Postman (and its CLI tool "newman"). &lt;br&gt;
I love this tool because it provide a way to test your work in progress and, when you're done, you just write tests in Javascript.&lt;/p&gt;

&lt;p&gt;We are used to run the postman tests before commiting, during the code review (it's part of it), and, of course, before any push on production.&lt;/p&gt;
&lt;h2&gt;
  
  
  Accessing the data
&lt;/h2&gt;

&lt;p&gt;Ok, I know when I want to have access to the metrics, I still have to figure how.&lt;br&gt;
Postman cannot access the profiler, since it'd require a secondary HTTP call, and to crawl the HTTP response. So we had to figure out another way.&lt;/p&gt;

&lt;p&gt;Why not pushing those metrics in the response header ?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Postman can read them and perform some tests on it&lt;/li&gt;
&lt;li&gt;We can access them with ease, even from Chrome dev tool&lt;/li&gt;
&lt;li&gt;It's pretty sexy, let's admit it !&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We decided that we want to have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The name of the controller and method called by the router&lt;/li&gt;
&lt;li&gt;Have the number of database query&lt;/li&gt;
&lt;li&gt;The memory used&lt;/li&gt;
&lt;li&gt;The execution time
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Execution-Controller → App\Controller\MyController -&amp;gt; myMethod
Execution-Doctrine-Queries → 8
Execution-Max-Memory → 4194304 bytes
Execution-Time → 206 ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How it works ?
&lt;/h2&gt;

&lt;p&gt;Well, it's really simple.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A StopWatch is started when any Controller is triggered using the &lt;code&gt;onKernelController&lt;/code&gt; event, then stoped on KernelResponse. This StopWatch give us the Execution-Time AND the Max-Memory&lt;/li&gt;
&lt;li&gt;We use the DoctrineDataCollector (as the Profiler does) to count the number of queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add it to the headers, and that's it !&lt;/p&gt;

&lt;p&gt;Write some tests in Postman or whatever tool you are using, and you can assert that your route is using less than 2mb of memory and require less than 5 database queries !&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_RM_ygI0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media3.giphy.com/media/3o7btNa0RUYa5E7iiQ/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img alt="You shall not pass !" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_RM_ygI0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media3.giphy.com/media/3o7btNa0RUYa5E7iiQ/giphy.gif"&gt;&lt;/a&gt;
&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qF2jUiUG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-6a5bca60a4ebf959a6df7f08217acd07ac2bc285164fae041eacb8a148b1bab9.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/laboutiqueofficielle"&gt;
        laboutiqueofficielle
      &lt;/a&gt; / &lt;a href="https://github.com/laboutiqueofficielle/MonitHeaderBundle"&gt;
        MonitHeaderBundle
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Add monitoring data in the response's header
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="instapaper_body md"&gt;
&lt;h1&gt;
MonitHeaderBundle&lt;/h1&gt;
&lt;p&gt;This Symfony 3 Bundle add some extra informations to the response's header&lt;/p&gt;
&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;p&gt;Simple add this line to AppKernel.php&lt;/p&gt;
&lt;div class="highlight highlight-text-html-php"&gt;&lt;pre&gt;&lt;span class="pl-s1"&gt; &lt;span class="pl-k"&gt;public&lt;/span&gt; &lt;span class="pl-k"&gt;function&lt;/span&gt; &lt;span class="pl-en"&gt;registerBundles&lt;/span&gt;()&lt;/span&gt;
&lt;span class="pl-s1"&gt;    {&lt;/span&gt;
&lt;span class="pl-s1"&gt;        &lt;span class="pl-smi"&gt;$bundles&lt;/span&gt; &lt;span class="pl-k"&gt;=&lt;/span&gt; &lt;span class="pl-c1"&gt;array_merge&lt;/span&gt;(&lt;span class="pl-smi"&gt;$this&lt;/span&gt;&lt;span class="pl-k"&gt;-&amp;gt;&lt;/span&gt;servicesBundles(&lt;span class="pl-smi"&gt;$this&lt;/span&gt;&lt;span class="pl-k"&gt;-&amp;gt;&lt;/span&gt;getEnvironment(), &lt;span class="pl-smi"&gt;$this&lt;/span&gt;), [&lt;/span&gt;
&lt;span class="pl-s1"&gt;            [&lt;span class="pl-k"&gt;...&lt;/span&gt;]&lt;/span&gt;
&lt;span class="pl-s1"&gt;            &lt;span class="pl-k"&gt;new&lt;/span&gt; &lt;span class="pl-c1"&gt;Lbo\Bundle\MonitHeaderBundle\&lt;/span&gt;&lt;span class="pl-c1"&gt;MonitHeaderBundle&lt;/span&gt;(),&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;
Usage&lt;/h2&gt;
&lt;p&gt;Then, inspect your headers with, for example, Postman&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Execution-Controller →App\Controller\MyController -&amp;gt; myMethod
Execution-Doctrine-Queries →8
Execution-Max-Memory →4194304 bytes
Execution-Time →206 ms
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/laboutiqueofficielle/MonitHeaderBundle"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;
 

</description>
      <category>php</category>
      <category>symfony</category>
      <category>testing</category>
      <category>functional</category>
    </item>
    <item>
      <title>Entities properties : public, protected or private ?</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Wed, 14 Aug 2019 10:33:54 +0000</pubDate>
      <link>https://dev.to/juyn/entities-properties-public-protected-or-private-78m</link>
      <guid>https://dev.to/juyn/entities-properties-public-protected-or-private-78m</guid>
      <description>&lt;p&gt;We all write a lot of models and entities, specially when we are working with frameworks like Symfony.&lt;/p&gt;

&lt;p&gt;But, when you code them, you have to make a choice for the properties. Should they be public, protected or private ?&lt;/p&gt;

&lt;p&gt;Symfony made a choice: private. &lt;br&gt;
Laravel chose public.&lt;/p&gt;

&lt;p&gt;My coworkers, inside our Symfony projects code them either protected or private, with a bunch of accessors.&lt;/p&gt;

&lt;p&gt;I prefer the Laravel's way, and always code them with a public visibility.&lt;/p&gt;

&lt;p&gt;I made that choice because most of the time (like 99% of the time), &lt;strong&gt;accessors are useless&lt;/strong&gt;, they don't transform the data. I prefer access them with &lt;code&gt;object-&amp;gt;property&lt;/code&gt; instead of &lt;code&gt;object-&amp;gt;getProperty()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And you, what visibility is your default choice, and why ?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>php</category>
      <category>laravel</category>
      <category>symfony</category>
    </item>
    <item>
      <title>Do you even unit test, bro ?</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Tue, 13 Aug 2019 21:44:12 +0000</pubDate>
      <link>https://dev.to/juyn/do-you-even-unit-test-bro-434g</link>
      <guid>https://dev.to/juyn/do-you-even-unit-test-bro-434g</guid>
      <description>&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fopzje4q2t83pwio9c042.png" class="article-body-image-wrapper"&gt;&lt;img alt="I don't always test my code, but when I do, I do it in production" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fopzje4q2t83pwio9c042.png"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Unit test is rocket science
&lt;/h1&gt;

&lt;p&gt;A lot a coders don't write any unit tests. The main reason if that they don't understand why the should spend time on this. It's just a waste of time, right ?&lt;/p&gt;

&lt;p&gt;I was exactly like that, then my code start crashing in production. On big and visible projects. So, I looked for a way to be more confident about my code, about my commits.&lt;/p&gt;

&lt;p&gt;Unit test was the first answer, but it took me time before writing them correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a good unit test ?
&lt;/h2&gt;

&lt;p&gt;To write a good, rock solid and trusty unit test, you need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Understand what you are testing&lt;/strong&gt;. That may sound stupid or obvious, but it's not.  Read the method, understand what it does, how and why. How can you test it if you don't know what it should or shouldn't do ?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid the "over mocking" syndrom&lt;/strong&gt;. Mocking make writing test easy, but it's not a good practice. Only mock if you don't have any other choice, like for an API call. And, please, don't stub the class you are testing !&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SEAT&lt;/strong&gt;. Setup, Exercises, Assert, Teardown. And repeat for each tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;I/O&lt;/strong&gt;. Focus on data transformation. Defined a start state, run the test, assert on the output. What happened during the process, or how it happened is not your concern.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decide a scope. Stick to it&lt;/strong&gt;.  A method can have as many tests as you want, but try to separates tests in use case scenarios.&lt;br&gt;
You want to assert that a method transform an array to json, but also throw an exception ? Alright, make it 2 independant tests !&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Does code coverage really matter ?
&lt;/h2&gt;

&lt;p&gt;TL;DR: &lt;strong&gt;No. It does not&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I've heard a LOT of people saying that you should aim for 100% code coverage. But that's a bad idea.&lt;br&gt;
Don't get me wrong, the higher code coverage you have, the better. But it should not be your main concern, neither your objective.&lt;/p&gt;

&lt;p&gt;I ask myself a few questions before writting a test for a method:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the method transform the data ?&lt;/li&gt;
&lt;li&gt;Can I write this test without mocking what the method will output ?&lt;/li&gt;
&lt;li&gt;Does the method returns something at all ?&lt;/li&gt;
&lt;li&gt;Can I make an assertion on the result ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of this questions is anwsered by a no, it is likely I'll not write any test.&lt;/p&gt;

&lt;p&gt;It's not because you have 100% code coverage that your code is tested properly.&lt;/p&gt;
&lt;h2&gt;
  
  
  You shall not pass !
&lt;/h2&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia3.giphy.com%2Fmedia%2FPShPwoSC3HAR2%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img alt="You shall not pass !" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia3.giphy.com%2Fmedia%2FPShPwoSC3HAR2%2Fgiphy.gif"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Code is composed by public methods, yes, but also by private and protected ones.&lt;br&gt;
Should we test them ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Of course not. But also yes !&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They usually contains the business logic, so, yeah, test them. But, unlike public methods, the are not worth a specific test.&lt;br&gt;
The purpose of a private method it's to be called by a public method of the same class. Let's apply the same logic inside our tests. Private and protected methods should be test through public method's tests.&lt;/p&gt;
&lt;h2&gt;
  
  
  Always be F.I.R.S.T
&lt;/h2&gt;

&lt;p&gt;I am used to write tests following the FIRST principles, but other methods exists, like AAC for example.&lt;br&gt;
I assume that, as a developper, you know how to use Google to find them if FIRST is not a good fit for you !&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F36c1e3ad00040f5e8ef886332613317a%2Ftenor.gif%3Fitemid%3D7863239" class="article-body-image-wrapper"&gt;&lt;img alt="Timey wimey dr who" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F36c1e3ad00040f5e8ef886332613317a%2Ftenor.gif%3Fitemid%3D7863239"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast&lt;/strong&gt;: A test should be light fast. If not, I'll discouraged you or your team from running it. Big project may have thousands of tests and assertations.&lt;br&gt;
Setup, test and tears down should not take more than a few milliseconds&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Independent&lt;/strong&gt;: Tests &lt;strong&gt;must not&lt;/strong&gt; depends on each other, or on the state of a previous test.&lt;br&gt;
All data needed should be created for the current test, and destroy afterward. &lt;br&gt;
If you need the same data for many tests, just create it during setup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Repeatable&lt;/strong&gt;: Tests should be repeatable over and over. Time, date or zone should not affect them.&lt;br&gt;
Yes. You can be a Time Lord and mock Time (unless it's a fix point in time, of course ;-) )&lt;br&gt;
Remember, if a test failed, the only valid reason should be that the method is not working as expected. Or that the test is wrong. But that's all folks !&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-validating&lt;/strong&gt;: No manual inspection required to check whether the test has passed or failed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Thorough&lt;/strong&gt;:  Don't be lazy. Unit testing should take time to write, sometime even more than writing the method itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test every use case scenario&lt;/li&gt;
&lt;li&gt;Don't limitate yourself for simple values. Go for edge values&lt;/li&gt;
&lt;li&gt;If the methods can process bulk data, test if with a large data set&lt;/li&gt;
&lt;li&gt;Tests for exceptions and errors&lt;/li&gt;
&lt;li&gt;Don't only test for success. You can assert a faillure, and you should !&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;Keep your tests simple, limit them to a specific scope and focus on the output of the method.&lt;/p&gt;

&lt;p&gt;Unit test is just the first step for a complete test cycle. Take a look on the pyramid bellow.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fwww.testingreferences.com%2Fpyramids%2FBagmar2012.jpg" class="article-body-image-wrapper"&gt;&lt;img alt="Idea test pyramid" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fwww.testingreferences.com%2Fpyramids%2FBagmar2012.jpg"&gt;&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>tests</category>
      <category>testing</category>
      <category>first</category>
      <category>unittest</category>
    </item>
    <item>
      <title>Using Laravel's Collection into Symfony</title>
      <dc:creator>Xavier Dubois 🇫🇷</dc:creator>
      <pubDate>Thu, 01 Aug 2019 21:43:20 +0000</pubDate>
      <link>https://dev.to/juyn/using-laravel-s-collection-into-symfony-4nf8</link>
      <guid>https://dev.to/juyn/using-laravel-s-collection-into-symfony-4nf8</guid>
      <description>&lt;h2&gt;
  
  
  What is Collections ?
&lt;/h2&gt;

&lt;p&gt;With PHP, we are all used to works with Arrays. And it's great for simple things, but it can become tricky pretty fast !  &lt;/p&gt;

&lt;p&gt;I mean, who has never struggle to make a Slice, an array_map or even an array_walker with the built in methods ?&lt;br&gt;&lt;br&gt;
Personally, I always have to check the doc to get it right.  &lt;/p&gt;

&lt;p&gt;Collections provides an alternative. Laravel documentation describes it like this :  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Illuminate\Support\Collection class provides a fluent, convenient wrapper for working with arrays of data&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, it provides a bunch of methods and helpers to access, transform and use arrays of data.&lt;br&gt;
For example, you have a API endpoint that is in charge of sending emails. You get an array of Email object in input, but you have to check first if they passed some assertion before trying to send them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$emails&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Email&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Email&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

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


&lt;p&gt;Pretty neat, right ?&lt;br&gt;
Yes, it's a really simple code, you might say it could have been done with a foreach and a if, but when you start to have serious business logic and a LOT of data to filter, it provides lisibility.&lt;/p&gt;
&lt;h3&gt;
  
  
  Symfony and the Collections
&lt;/h3&gt;

&lt;p&gt;Before, I was talking about Laravel's implementation of collections.&lt;br&gt;
It has a lot of methods and helpers to make your life easier.&lt;/p&gt;

&lt;p&gt;But, profesionally I have to work with Symfony. Which is great, don't get me wrong, but its collection implementation is really basic.&lt;/p&gt;

&lt;p&gt;ArrayCollection (it's his little name), provided by Doctrine allows you to filter, access and map array of data, and that's it.&lt;br&gt;
Laravel, in the other hand, provides advanced method, like "first", "sum" or "toJson".&lt;/p&gt;
&lt;h3&gt;
  
  
  How can we get Laravel's Collection into Symfony ?
&lt;/h3&gt;

&lt;p&gt;Well, that should be simple right ? Because, since Composer exist, all we have to do is&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require laravel/collection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;right ?&lt;/p&gt;

&lt;p&gt;But, hey, life is not that easy all the time !&lt;br&gt;
Actually, Collections are part of the Laravel Framework, so, if you want it, you'll have to extract it, copy it on your own repo, and watch Laravel changes to stay up to date.&lt;br&gt;
No thanks !&lt;/p&gt;
&lt;h2&gt;
  
  
  1st attempt
&lt;/h2&gt;

&lt;p&gt;At first, I got cocky. Why not write my own implementation ?&lt;/p&gt;

&lt;p&gt;I mean, nothing complicated to do. Just a bunch of methods ... easy.&lt;br&gt;
ExtendedArrayCollection was born. The name says it all. I based my project on Doctrine's ArrayCollection to minimise the job to do, but also to make sure it will works everywhere in Symfony.&lt;/p&gt;

&lt;p&gt;And it did for a while. Until it didn't anymore. To obtain something as good as Laravel does, it demands a huge amount of time, and, I don't have it ...&lt;/p&gt;
&lt;h2&gt;
  
  
  So, why not use Laravel's Collection ?
&lt;/h2&gt;

&lt;p&gt;Back to Google, looking for a guy with more bravour than me, with more time, maybe.&lt;br&gt;
I found a package, made by Matt Stauffer (Tighten Co.), which is an export of Laravel's Collection.&lt;/p&gt;

&lt;p&gt;This was PERFECT. Well, almost perfect.&lt;/p&gt;

&lt;p&gt;Laravel's entities are a little bit different thant Symfony's ones.&lt;br&gt;
In Laravel, properties are declared public where, in Symfony, they usually are private or protected, with a bunch of getters and setters. &lt;/p&gt;

&lt;p&gt;As you can imagine, it was a problem since, in Laravel's Collection, object data is access like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;is_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Annnnd yup. That cannot works with a protected properties, since you have to use $taget-&amp;gt;getSegment() to access the value.&lt;/p&gt;

&lt;p&gt;Well, since I really hate ArrayCollection, I decided to not give up.&lt;br&gt;
So, I created a fork from Tightenco/collect package to make some tweaks that allows me to use Laravel's Collection into Symfony.&lt;/p&gt;
&lt;h3&gt;
  
  
  Code modification
&lt;/h3&gt;

&lt;p&gt;Alright, then all I needed to do was to find a way of accessing data no matter their visibility.&lt;/p&gt;

&lt;p&gt;I had a few options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assert that "getSegment" method exist, and, if not, trying to access value with -&amp;gt;segment.&lt;/li&gt;
&lt;li&gt;Always assume that since I'm in Symfony, getter will always be set&lt;/li&gt;
&lt;li&gt;Use ReflectionObject&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I chose to use the third option, with ReflectionObject because it provides a more secure way to do it.&lt;br&gt;
The code became:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;is_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$reflectedObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;\ReflectionObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Use Reflection class to check if property even exist, otherwhise let's use default value&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$reflectedObject&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;hasProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$default&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$reflectedObject&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// If property is public, no need to get all the way down&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;isPublic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="nv"&gt;$target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$segment&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Make the property accessible before geting its value&lt;/span&gt;
            &lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;setAccessible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And, that's it folks. I just have to make a Collection class on my own namespace, extend TightenCo version, and my Symfony is ready to use the amazing Laravel's Collection !&lt;/p&gt;
&lt;h3&gt;
  
  
  What's next ?
&lt;/h3&gt;

&lt;p&gt;That is already pretty cool and handy, but I want more.&lt;br&gt;
Next steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Override Doctrine to make it use Collection instead of ArrayCollection&lt;/li&gt;
&lt;li&gt;Make a proper repository with documentation, example&lt;/li&gt;
&lt;li&gt;Find a way to simplify the namespace management &lt;/li&gt;
&lt;li&gt;make unit tests !&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of you is interested by the package: &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Juyn"&gt;
        Juyn
      &lt;/a&gt; / &lt;a href="https://github.com/Juyn/collect"&gt;
        collect
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
collect&lt;/h1&gt;
&lt;p&gt;Add support for Symfony on Laravel's awesome Collection&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Juyn/collect"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>php</category>
      <category>symfony</category>
      <category>collection</category>
      <category>laravel</category>
    </item>
  </channel>
</rss>
