<?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: Lloyds digital</title>
    <description>The latest articles on DEV Community by Lloyds digital (@lloyds-digital).</description>
    <link>https://dev.to/lloyds-digital</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%2Forganization%2Fprofile_image%2F2282%2F0ae1d322-99b9-4f5f-9c1a-01f042126d42.png</url>
      <title>DEV Community: Lloyds digital</title>
      <link>https://dev.to/lloyds-digital</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lloyds-digital"/>
    <language>en</language>
    <item>
      <title>Use Laravel with OpenAI to validate inappropriate content</title>
      <dc:creator>Ricardo Čerljenko</dc:creator>
      <pubDate>Fri, 10 Feb 2023 20:40:29 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/use-laravel-with-openai-to-validate-inappropriate-content-2e67</link>
      <guid>https://dev.to/lloyds-digital/use-laravel-with-openai-to-validate-inappropriate-content-2e67</guid>
      <description>&lt;p&gt;Recently I stumbled across &lt;a href="https://platform.openai.com/docs/api-reference/moderations" rel="noopener noreferrer"&gt;OpenAI Moderations API&lt;/a&gt; which gives you a way to query OpenAI in order to detect if input text contains inappropriate content such as hate, violence, etc.&lt;/p&gt;

&lt;p&gt;API is completly free - you just need to create an OpenAI account and issue a fresh API token.&lt;/p&gt;

&lt;p&gt;Since I'm primary a Laravel PHP Framework developer, I decided to &lt;a href="https://github.com/rcerljenko/laravel-openai-moderation" rel="noopener noreferrer"&gt;make a package&lt;/a&gt; which will provide a way to validate request payload fields against OpenAI Moderations API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Standard &lt;a href="https://getcomposer.org/download" rel="noopener noreferrer"&gt;Composer&lt;/a&gt; package installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require rcerljenko/laravel-openai-moderation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Publish config and translation files.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"RCerljenko&lt;/span&gt;&lt;span class="se"&gt;\L&lt;/span&gt;&lt;span class="s2"&gt;aravelOpenAIModeration&lt;/span&gt;&lt;span class="se"&gt;\L&lt;/span&gt;&lt;span class="s2"&gt;aravelOpenAIModerationServiceProvider"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Set your OpenAI API key and enable package via newly created config file =&amp;gt; &lt;code&gt;config/openai.php&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use provided rule with your validation rules.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Requests&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Foundation\Http\FormRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;RCerljenko\LaravelOpenAIModeration\Rules\OpenAIModeration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StoreText&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;FormRequest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="cd"&gt;/**
  * Determine if the user is authorized to make this request.
  */&lt;/span&gt;
 &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;bool&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;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="cd"&gt;/**
  * Get the validation rules that apply to the request.
  */&lt;/span&gt;
 &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAIModeration&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;];&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! Your content can now be validated with powerfull (and yet free) OpenAI Moderations API.&lt;/p&gt;

&lt;p&gt;Thank you for reading this! If you've found this interesting, consider leaving a ❤️, 🦄 , and of course, share and comment on your thoughts!&lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, &lt;a href="https://lloyds-digital.com" rel="noopener noreferrer"&gt;check us out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, don’t forget to follow us on &lt;a href="https://instagram.com/lloyds.digital" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; and &lt;a href="https://facebook.com/lloydsdigital" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>remote</category>
      <category>startup</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Laravel - Serve API requests with translated validation rules</title>
      <dc:creator>Ricardo Čerljenko</dc:creator>
      <pubDate>Wed, 19 Oct 2022 18:49:32 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/laravel-serve-api-requests-with-translated-validation-rules-1c6o</link>
      <guid>https://dev.to/lloyds-digital/laravel-serve-api-requests-with-translated-validation-rules-1c6o</guid>
      <description>&lt;p&gt;Consider building a mobile app (or a website) which connects to a Laravel CMS over API for dynamic content. Now, the app can be a multi-language app which expects to receive a translated content from the CMS.&lt;br&gt;
Usually, in our company, we instruct our frontend developers to send a &lt;code&gt;lang&lt;/code&gt; query param on every request in order to deliver the correct translated content back.&lt;/p&gt;

&lt;p&gt;E.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/blogs?lang=en
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, Laravel validation is not aware of this and it always returns validation error messages according to app locale (or fallback locale).&lt;/p&gt;

&lt;p&gt;Therefore we created a route middleware which groups all API routes and sets app locale based on the &lt;code&gt;lang&lt;/code&gt; query param:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Middleware&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Closure&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\HttpFoundation\Response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChangeLocale&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Handle an incoming request.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Closure&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Response&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'lang'&lt;/span&gt;&lt;span class="p"&gt;);&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;$locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;setLocale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$locale&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="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;);&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 in routes file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// routes/api.php&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Middleware\ChangeLocale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Route&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ChangeLocale&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;group&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="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ROUTES&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your validation messages will be in the requested locale. If you don't like handling this over query param you can always use a header or something else, e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Accept-Language'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for reading this! If you've found this interesting, consider leaving a ❤️, 🦄 , and of course, share and comment on your thoughts!&lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, &lt;a href="https://lloyds-digital.com"&gt;check us out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, don’t forget to follow us on &lt;a href="https://instagram.com/lloyds.digital"&gt;Instagram&lt;/a&gt; and &lt;a href="https://facebook.com/lloydsdigital"&gt;Facebook&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Creating a Neat DateTime Helper Function in PHP</title>
      <dc:creator>Ricardo Čerljenko</dc:creator>
      <pubDate>Thu, 24 Mar 2022 12:35:05 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/creating-a-neat-datetime-helper-function-in-php-45in</link>
      <guid>https://dev.to/lloyds-digital/creating-a-neat-datetime-helper-function-in-php-45in</guid>
      <description>&lt;p&gt;Let me start with a statement: I'm not a big fan of global helper functions being included in the project, but sometimes it's a good thing to have that little helper functions here and there.&lt;/p&gt;

&lt;p&gt;Working with datetime in PHP could be a real pain if you don't take advantage of popular libraries like &lt;a href="https://carbon.nesbot.com"&gt;Carbon&lt;/a&gt;. It's all good until you have to convert dates provided on user input into another timezone (eg. UTC) and vice versa. Other example could be that you have to manage various input datetime formats, and sanitize them into a consistent one before saving it to database.&lt;/p&gt;

&lt;p&gt;I will show you how I handled that by creating a datetime helper function which will take any datetime format and convert it into a consistent one with the power of Carbon library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Carbon\Carbon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;DateTimeInterface&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$inputDateTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$outputFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Y-m-d H:i:s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;DateTimeZone&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$outputTimezone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'UTC'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;DateTimeZone&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$inputTimezone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'UTC'&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$carbon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;is_numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$inputDateTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;Carbon&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;createFromTimestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$inputDateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$inputTimezone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Carbon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$inputDateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$inputTimezone&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$carbon&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setTimezone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$outputTimezone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$outputFormat&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;Let's go over this bit by bit. The function takes 4 arguments and none of them are required which means that if called without any argument, the function should return a current UTC datetime string in a common database format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// 2022-02-03 08:10:21&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First argument &lt;code&gt;$inputDateTime&lt;/code&gt; is the most important one and by its signature you can easily figure out that it can accept various datetime formats including a string, float, integer and a &lt;code&gt;DateTimeInterface&lt;/code&gt; capable object. That last one is important because it enables us to work with any PHP datetime object as well as any potential library that implements that interface (such as Carbon).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2022-02-03 08:10:21'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2022-12-31'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// int (UNIX timestamp)&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// float (UNIX timestamp in microseconds)&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;microtime&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="c1"&gt;// DateTime object&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Carbon object&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Carbon&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Laravel Carbon datetime casting&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other arguments are pretty self-explanatory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$outputFormat&lt;/code&gt; controls in which format will function return the datetime string, e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d/m/Y'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// 03/02/2022&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$outputTimezone&lt;/code&gt; controls the result timezone and &lt;code&gt;$inputTimezone&lt;/code&gt; tells the function in which timezone is the &lt;code&gt;$inputDateTime&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you're running under PHP8+ then it's even easier to handle arguments with the "named arguments" feature like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;inputTimezone&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Europe/Zagreb'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for reading this! If you've found this interesting, consider leaving a ❤️, 🦄 , and of course, share and comment on your thoughts!&lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, &lt;a href="https://lloyds-digital.com"&gt;check us out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, don’t forget to follow us on &lt;a href="https://instagram.com/lloyds.digital"&gt;Instagram&lt;/a&gt; and &lt;a href="https://facebook.com/lloydsdigital"&gt;Facebook&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>php</category>
      <category>datetime</category>
      <category>webdev</category>
      <category>carbon</category>
    </item>
    <item>
      <title>How to handle both API and Basic authentication in Laravel</title>
      <dc:creator>Ricardo Čerljenko</dc:creator>
      <pubDate>Thu, 03 Mar 2022 09:55:42 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/how-to-handle-both-api-and-basic-authentication-in-laravel-1bgc</link>
      <guid>https://dev.to/lloyds-digital/how-to-handle-both-api-and-basic-authentication-in-laravel-1bgc</guid>
      <description>&lt;p&gt;While building your app in Laravel PHP Framework, you have multiple ways of protecting your API routes with various auth guards or Basic auth. Would it be nice to support both API guard and Basic auth at the same time?&lt;/p&gt;

&lt;p&gt;In default Laravel app you can protect your API routes like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// routes/api.php&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Route&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth:api'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;group&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="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// PROTECTED ROUTES&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or using Basic auth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// routes/api.php&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Route&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth.basic'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;group&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="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// PROTECTED ROUTES&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it's not possible to guard your routes with both of them. E.g., if there's no provided Bearer token use the Basic auth. To accomplish this we need to make some adjustments to the default &lt;code&gt;Authenticate&lt;/code&gt; middleware which is provided in the &lt;code&gt;app/Http/Middleware&lt;/code&gt; directory. Here's how I achieved that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Middleware&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Closure&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Auth\AuthenticationException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\HttpFoundation\Response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Auth\Middleware\Authenticate&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;Middleware&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Authenticate&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Middleware&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Handle an incoming request.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Closure&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$guards&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Response&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&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="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$guards&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AuthenticationException&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&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;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;wantsJson&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&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;$response&lt;/span&gt; &lt;span class="o"&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="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;onceBasic&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="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;;&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="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;);&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;First, we catch the &lt;code&gt;AuthenticationException&lt;/code&gt; which is thrown by the parent &lt;code&gt;authenticate()&lt;/code&gt; method. That means that every provided guard (or a default one) didn't produce a valid user.&lt;/p&gt;

&lt;p&gt;Now we can try to do a Basic auth but only if the client expects a JSON response (we don't want to try Basic auth in a normal web context because it would pop-up the Basic auth prompt box on every browser request).&lt;/p&gt;

&lt;p&gt;Take note that &lt;code&gt;onceBasic()&lt;/code&gt; method returns &lt;code&gt;null&lt;/code&gt; if the provided Basic auth credentials are valid. If not, it returns an already formed Error Response bag which you can safely return from the middleware.&lt;/p&gt;

&lt;p&gt;Now we're able to authenticate our users on API routes with both API guard and fallback Basic auth by simply using a default &lt;code&gt;auth&lt;/code&gt; middleware.&lt;/p&gt;

&lt;p&gt;Thank you for reading this! If you've found this interesting, consider leaving a ❤️, 🦄 , and of course, share and comment on your thoughts!&lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, &lt;a href="https://lloyds-digital.com"&gt;check us out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, don’t forget to follow us on &lt;a href="https://instagram.com/lloyds.digital"&gt;Instagram&lt;/a&gt; and &lt;a href="https://facebook.com/lloydsdigital"&gt;Facebook&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>auth</category>
      <category>webdev</category>
      <category>php</category>
    </item>
    <item>
      <title>9 tricks to make your React Native development easier</title>
      <dc:creator>Masimo Orbanic</dc:creator>
      <pubDate>Mon, 28 Feb 2022 08:58:36 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/9-tricks-to-make-your-react-native-development-easier-39i1</link>
      <guid>https://dev.to/lloyds-digital/9-tricks-to-make-your-react-native-development-easier-39i1</guid>
      <description>&lt;p&gt;We all agree that React Native is a great way to develop mobile apps. But in the process of making a mobile app, besides the endless hours spent reading the documentation and debugging some badly implemented package, you come across a situation that makes you think “hmm, I wonder if there is an easier way to do this”. So I bring you some tricks that I’ve learned over the years developing React Native apps and wish that somebody told them to me years ago. Hope you find something useful for yourself, let’s start!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Open a new terminal in the same folder - from the terminal (Mac only)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  UPDATE
&lt;/h3&gt;

&lt;p&gt;You can open new terminal in the same folder with a  setting in the preferences. Go to the Terminal preferences, General settings, and under &lt;em&gt;New windows&lt;/em&gt; open with select &lt;em&gt;Same Working Directory&lt;/em&gt;.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8vf7m2bko4wfjy0j2ro9.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8vf7m2bko4wfjy0j2ro9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your work day probably starts with opening a Terminal, navigating to the project folder and running &lt;code&gt;yarn android&lt;/code&gt; or/and &lt;code&gt;yarn start&lt;/code&gt; . But after some time you need to install some React Native package or run some tricky git command, and wish to have another Terminal window in the same folder. So you press cmd + N to open new Terminal window and navigate in the terminal to the project folder. To make this thing easier you can run &lt;code&gt;open -a Terminal \$(pwd)&lt;/code&gt; in the terminal, which basically opens the Terminal app in the desired folder, which in our case can be obtained with the &lt;code&gt;pwd&lt;/code&gt; command.  But that command is too long to write and remember, so you can add it in your &lt;em&gt;.zshrc&lt;/em&gt; file as alias &lt;code&gt;alias nt="open -a Terminal \$(pwd)"&lt;/code&gt; . After you restart the Terminal app, if you run &lt;code&gt;nt&lt;/code&gt; command (I’ve named the alias &lt;em&gt;nt&lt;/em&gt; for &lt;strong&gt;n&lt;/strong&gt;ew &lt;strong&gt;t&lt;/strong&gt;erminal, you can call it whatever you want), you will get a new Terminal window in the same directory from which you ran the &lt;code&gt;nt&lt;/code&gt; command.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Simulate push notifications on iOS
&lt;/h2&gt;

&lt;p&gt;Let’s say that you are doing some push notification suff and you want to quickly test how your app reacts when a push notification is received. Instead of manually triggering a push notification by doing some in-app action or sending one from a dashboard, you can create a &lt;em&gt;noti&lt;/em&gt;&lt;em&gt;fication.apns&lt;/em&gt; file and drag ‘n drop it in the Simulator window! And what exactly is in the &lt;em&gt;notification.apns&lt;/em&gt; file? Well, it looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 "Simulator Target Bundle": "com.example.simpush",
 "aps": {
   "alert": {
     "title": "New notification!",
     "subtitle": "notification.apns triggered notification",
     "body": "Hello there!"
   },
   "sound": "default"
 },
 "custom": {
   "test": "something",
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The first information is &lt;em&gt;"Simulator Target Bundle": "com.example.simpush"&lt;/em&gt;, and it tells which application to run, in our case it is the application with bundle id &lt;code&gt;com.example.simpush&lt;/code&gt; . Next comes the &lt;em&gt;"&lt;/em&gt;&lt;em&gt;aps&lt;/em&gt;&lt;em&gt;"&lt;/em&gt; section, and as you can see it has an alert section where you define the &lt;em&gt;title&lt;/em&gt;, &lt;em&gt;subtitle&lt;/em&gt; and &lt;em&gt;body&lt;/em&gt; of the notification. Also in the “&lt;em&gt;a&lt;/em&gt;&lt;em&gt;ps&lt;/em&gt;” section you can define the sound and vibration settings. In the “&lt;em&gt;custom&lt;/em&gt;” you can define custom information that is sent with the push notification.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fop1gmlkm67nnfr26gfwn.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fop1gmlkm67nnfr26gfwn.gif" alt="Simulation of push notification on iOS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depending on your app push notification setup, the &lt;em&gt;notification.apns&lt;/em&gt; file can be different. But once you’ve configured in Xcode that your app can receive push notifications, and you granted permission to receive push notifications, you should be able to make it work.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Share Android device screen on your desktop
&lt;/h2&gt;

&lt;p&gt;You will probably need to share your phone’s screen to your desktop. Either you don’t want to stay leaned above your phone all day, or you have something to present to your client/colleague over a video conference. There are some solutions like Vysor or Screen stream over HTTP, but the picture quality is not that great and there could be some ads playing during usage. But there is an app called &lt;a href="https://github.com/Genymobile/scrcpy" rel="noopener noreferrer"&gt;&lt;em&gt;scrcpy&lt;/em&gt;&lt;/a&gt; , that provides display and control of Android devices connected with USB (or over TCP/IP, covered in tip number 8). It does not require any root access, and it works on Linux, Windows and macOS. I’ve been using it for some time and it works great. Also the setup is very easy. You can learn how to install it and use &lt;a href="https://github.com/Genymobile/scrcpy" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Generate app icons
&lt;/h2&gt;

&lt;p&gt;When you have an app that is ready to go the stores, you must have an app icon. And you have one because your design team did a great job on creating one! But you must have them in a couple of specific dimensions, with square and rounded corners, for both iOS and Android. To spare yourself and designers from this time consuming and boring task, there are some web applications that can do that for you, and the best one we have been using in Lloyds digital so far is &lt;a href="https://appiconmaker.co/" rel="noopener noreferrer"&gt;appiconmaker.co&lt;/a&gt; for iOS, and for Android &lt;a href="http://romannurik.github.io/AndroidAssetStudio/icons-launcher.html" rel="noopener noreferrer"&gt;AndroidAssetStudio&lt;/a&gt;. They is free and easy to use, no watermarks or limitations. &lt;/p&gt;

&lt;h2&gt;
  
  
  5. Open Xcode project from the Terminal
&lt;/h2&gt;

&lt;p&gt;The longest way to open an Xcode project of your app is to &lt;em&gt;open Finder&lt;/em&gt; &amp;gt; &lt;em&gt;find your React Native project folder&lt;/em&gt; &amp;gt; &lt;em&gt;open ios folder&lt;/em&gt; &amp;gt; &lt;em&gt;open .xcworkspace&lt;/em&gt; &lt;em&gt;file&lt;/em&gt;. The shortest way is to put &lt;code&gt;"xc": "xed -b ios"&lt;/code&gt; in your projects &lt;em&gt;package.json&lt;/em&gt; under “scripts”, and just run &lt;code&gt;yarn xc&lt;/code&gt; from project folder to open Xcode project of your React Native app. You can find out more about &lt;code&gt;xed&lt;/code&gt; in this &lt;a href="https://medium.com/xcblog/xed-the-lightweight-text-editor-for-xcode-269aae5b2a77#:~:text=The%20xed%20is%20Xcode%20Text,files%20or%20creating%20new%20files." rel="noopener noreferrer"&gt;Medium&lt;/a&gt; &lt;a href="https://medium.com/xcblog/xed-the-lightweight-text-editor-for-xcode-269aae5b2a77" rel="noopener noreferrer"&gt;post&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Use transform.tools
&lt;/h2&gt;

&lt;p&gt;Transforming code or data from one format to other can be time consuming and boring, and you could miss some piece of information if the structure is too confusing and big. To help you with that, there is an online app &lt;a href="https://transform.tools" rel="noopener noreferrer"&gt;transform.tools&lt;/a&gt; which offers many kinds of transformations. I will mention just some of them, mostly used in React Native:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SVG to React Native (JSX)&lt;/li&gt;
&lt;li&gt;JSON to JSDoc&lt;/li&gt;
&lt;li&gt;JSON to Typescript&lt;/li&gt;
&lt;li&gt;JSON to MobX-State-Tree Model&lt;/li&gt;
&lt;li&gt;GraphQL to Typescript&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Visit &lt;a href="https://transform.tools/" rel="noopener noreferrer"&gt;transform.tools&lt;/a&gt; and make transformations of your code or data with ease. &lt;/p&gt;

&lt;h2&gt;
  
  
  7. Consider implementing Code Push for faster feedback loop from developer to the testers and clients
&lt;/h2&gt;

&lt;p&gt;As the project timeline comes to an end, communication and feedback loop between testers/client and developer must be the fastest possible. You will probably come to a situation where you made a test release of the app with some small bug that breaks the app and the testing can not continue. And the fix for the bug is very simple, one or two lines of JS code. In order to deliver that fixed version you need to increase build numbers, create a new release, and upload it to the TestFlight or Google Play store testing track, which we all can agree is at least 1 hour of work. To make the feedback loop shorter you can use &lt;a href="https://github.com/microsoft/react-native-code-push" rel="noopener noreferrer"&gt;Code push&lt;/a&gt;. Code Push is a cloud service from Microsoft Visual Studio App Center, that acts as a central repository where developers can publish certain updates. These updates are then queried by apps using the client Code Push SDK. Since Code Push is in semi-violation of the Google and Apple store guidelines, I won’t encourage you to implement it in the production version of the app, but for test and development purpose you can find it very helpful. I’ve covered Code Push in the &lt;a href="https://dev.to/lloyds-digital/implementing-code-push-in-react-native-applications-25nj"&gt;Implementing Code Push in React Native applications&lt;/a&gt; article. In the article you can find more information on what Code Push is and how to implement it.&lt;/p&gt;

&lt;h2&gt;
  
  
  8.  ADB over WiFi
&lt;/h2&gt;

&lt;p&gt;Your computer communicates with your Android device using Android Debug Bridge (&lt;em&gt;adb&lt;/em&gt;). Maybe you remember &lt;em&gt;adb&lt;/em&gt; from the &lt;a href="https://reactnative.dev/docs/running-on-device" rel="noopener noreferrer"&gt;running on device tutorial&lt;/a&gt;, and in the tutorial you are guided to use USB to make everything work. But there is an option to have &lt;em&gt;adb&lt;/em&gt; over WiFi! Here is how to setup &lt;em&gt;adb&lt;/em&gt; over WiFi:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure that your Android device and &lt;em&gt;adb&lt;/em&gt; host computer are connected to a common Wi-Fi network accessible to both&lt;/li&gt;
&lt;li&gt;Connect the device to the host computer with a USB cable&lt;/li&gt;
&lt;li&gt;Set the target device to listen for a TCP/IP connection on port 5555 by running &lt;code&gt;adb tcpip 5555&lt;/code&gt; in your Terminal&lt;/li&gt;
&lt;li&gt;Disconnect the USB cable from your device&lt;/li&gt;
&lt;li&gt;Find the IP address of your Android device. You can usually find the IP address at &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;About phone&lt;/strong&gt; &amp;gt; &lt;strong&gt;Status&lt;/strong&gt; &amp;gt; &lt;strong&gt;IP address&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Connect to the device by its IP address using &lt;code&gt;adb connect &amp;lt;&amp;lt;device_ip_address&amp;gt;&amp;gt;:5555&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Confirm that your host computer is connected to the target device by running &lt;code&gt;adb devices&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From that point you can do everything on your Android device as if you were connected with USB, like run &lt;code&gt;adb reverse tcp:8081 tcp:8081&lt;/code&gt; , or use scrcpy from the #3 tip in this article!&lt;/p&gt;

&lt;p&gt;Android devices running Android 11+ have a method to wirelessly use &lt;em&gt;adb&lt;/em&gt; using Wireless debugging feature.  You can find out goodies about &lt;em&gt;adb&lt;/em&gt; &lt;a href="https://developer.android.com/studio/command-line/adb" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  9. r - Terminal command (Mac)
&lt;/h2&gt;

&lt;p&gt;This is a trick that can be widely used. Basically when you run &lt;em&gt;r&lt;/em&gt; in your Terminal, the last command that you executed will be executed again, just like it would if you pressed up key and hit enter. But the trick is that it has options for start and end command that will be ran from your history. &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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakvhndv9qehlyscoe6qs.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakvhndv9qehlyscoe6qs.png" alt="Presentation of r command"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first option, -4 from the screenshot, is the start, and it runs the fourth command from your terminal history, and the second option -2 is the end and it runs every command between fourth and second one in your terminal history. You can find it useful if you have same the set of commands that you need to run multiple times, like running some test script, or for example pushing a fix to git. &lt;br&gt;
If you once ran &lt;code&gt;git add -Av&lt;/code&gt; , &lt;code&gt;git commit -m "small fix"&lt;/code&gt; and &lt;code&gt;git push&lt;/code&gt; , you can re-run all of them by running &lt;code&gt;r -3 -1&lt;/code&gt; in your Terminal.&lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, click &lt;a href="https://lloyds-digital.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
Also, don’t forget to follow us on &lt;a href="https://www.instagram.com/lloyds.digital/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; and &lt;a href="https://www.facebook.com/lloydsdigital/" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>javascript</category>
      <category>tips</category>
      <category>dev</category>
    </item>
    <item>
      <title>Structuring a CI/CD workflow in GitLab (Node.js example)</title>
      <dc:creator>Tomas Martincic</dc:creator>
      <pubDate>Thu, 03 Feb 2022 08:25:20 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/structuring-a-cicd-workflow-in-gitlab-nodejs-example-2500</link>
      <guid>https://dev.to/lloyds-digital/structuring-a-cicd-workflow-in-gitlab-nodejs-example-2500</guid>
      <description>&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What are pipelines&lt;/li&gt;
&lt;li&gt;DevOps pipelines&lt;/li&gt;
&lt;li&gt;What CI/CD pipeline software to use?&lt;/li&gt;
&lt;li&gt;Why did we choose GitLab?&lt;/li&gt;
&lt;li&gt;Docker Technology&lt;/li&gt;
&lt;li&gt;gitlab-ci.yml file&lt;/li&gt;
&lt;li&gt;Pipeline lifecycle example&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What are pipelines
&lt;/h2&gt;

&lt;p&gt;In computing, pipeline refers to the logical queue that is filled with all the instructions for the computer processor to process in parallel. It is the process of storing and queuing tasks and instructions that are executed simultaneously by the processor in an organized way. &lt;/p&gt;

&lt;p&gt;This is different from the regular queue or stack data structures in computer science. These data structures work in FIFO or LIFO approaches, respectively. This means literally "&lt;strong&gt;F&lt;/strong&gt;irst &lt;strong&gt;I&lt;/strong&gt;n &lt;strong&gt;F&lt;/strong&gt;irst &lt;strong&gt;O&lt;/strong&gt;ut" or "&lt;strong&gt;L&lt;/strong&gt;ast &lt;strong&gt;I&lt;/strong&gt;n &lt;strong&gt;F&lt;/strong&gt;irst &lt;strong&gt;O&lt;/strong&gt;ut" principles, no matter if working with elements, instructions, files, or any other arbitrarily listable item. &lt;/p&gt;

&lt;h2&gt;
  
  
  DevOps pipelines
&lt;/h2&gt;

&lt;p&gt;DevOps is a set of practices that combines software development and IT operations. It aims to shorten the systems development life cycle and provide continuous delivery with high software quality. DevOps is complementary with Agile software development; several DevOps aspects came from the Agile methodology.&lt;/p&gt;

&lt;p&gt;So if you're planning on having an 'agile' work environment, you must have good software foundations and automation processes set in place to achieve fast-paced development and results. If everything is done manually, the environment would be rigid, stiff, and slow, thus being the exact opposite of agile.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is CI/CD?
&lt;/h2&gt;

&lt;p&gt;In software engineering, CI/CD or CICD is the combined practice of continuous integration and either continuous delivery or continuous deployment. CI/CD bridges the gaps between development and operation activities and teams by enforcing automation in the building, testing, and deployment of applications. This would preferably shorten the gap between developers developing the project locally in their IDE and the project being published in their normal production environment, either on public domain for clients or private domain for staging with other branches of the product development lifecycle (backend/frontend/design/QA/testers/...).&lt;/p&gt;

&lt;h4&gt;
  
  
  It works on my machine ¯\&lt;em&gt;(ツ)&lt;/em&gt;/¯
&lt;/h4&gt;

&lt;p&gt;Not only that we've shortened the gap between the developer and productional environment, but we've also introduced an assurance that it will work within the productional environment. The main component of CI/CD is that we run install/compilation, build, and test inside environment which mimics production. Therefore we've eliminated the chance of "&lt;em&gt;but it works on my machine&lt;/em&gt;" happening.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5smzoxr1ijqsukrk9tl.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5smzoxr1ijqsukrk9tl.png" alt="Gitlab pipeline flow"&gt;&lt;/a&gt;&lt;br&gt;
Gitlab's CI/CD flow, other software uses mostly similar flow&lt;/p&gt;

&lt;h2&gt;
  
  
  What CI/CD pipeline software to use?
&lt;/h2&gt;

&lt;p&gt;There are many options available to provide continuous delivery and integration in your software development lifecycle. Some of the most popular CI/CD tools are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.jenkins.io" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://circleci.com" rel="noopener noreferrer"&gt;CircleCI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://about.gitlab.com" rel="noopener noreferrer"&gt;GitLab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jetbrains.com/teamcity" rel="noopener noreferrer"&gt;TeamCity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.atlassian.com/software/bamboo" rel="noopener noreferrer"&gt;Bamboo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tool for the job is a personal preference and depends on which of these tools fit your project, budget, requirements, language, technology, etc.&lt;/p&gt;

&lt;p&gt;From this point on, we will focus on &lt;strong&gt;GitLab's pipeline&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why did we choose GitLab?
&lt;/h2&gt;

&lt;p&gt;Well, the choice was not a hard one. GitLab is our default VCS and provides a rich set of features for CI/CD pipelines leveraging the Docker technology. The beauty of in-house CI/CD integration with your VCS is that the pipeline itself can be triggered upon various events from the developers. The pipeline itself can be configured in a way that it triggers certain code blocks in all kinds of situations. For example, it can be triggered upon pushing to a certain branch, or by providing some sort of specific trigger key within commit message, it can be triggered upon Merge Requests, upon the success of those merges, etc. &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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiz98lz5kxqg41mhkjhbp.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiz98lz5kxqg41mhkjhbp.png" alt="Gitlab pipeline stages"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach allows the DevOps engineer to configure the pipeline in a way that other software engineers mindlessly continue with their usual workflows and are completely oblivious to what's happening in the background. This is great because now you need only one good engineer to configure and maintain it, whereas the rest of the team/organization does not have to bother with learning the technology inside out to use it.&lt;/p&gt;

&lt;p&gt;Alongside being our default VCS and having great flexibility, it can also be hosted on-premise. This way we are not using GitLab's servers (also called runners) but our own. GitLab's pipeline will only charge you for computing time on their servers so we are saving some money. But GitLab does have fast servers which are relatively cheap (10$ for 1000min of computation). That would be a good approach for big companies, it would cost much less in the long run than configuring their cluster of runners. &lt;/p&gt;

&lt;h2&gt;
  
  
  Docker Technology
&lt;/h2&gt;

&lt;p&gt;Docker is a set of 'platform as a service' products that use OS-level virtualization to deliver software in packages called containers. Containers are isolated from one another and bundle their software, libraries, and configuration files; they can communicate with each other through well-defined channels. A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries, and settings. &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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa2gd3q1qp20xw9p1aso.jpg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa2gd3q1qp20xw9p1aso.jpg" alt="Docker vs Virtual Machine"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;The main difference between Docker and Virtual machines is that docker is running within its container virtualization engine, whereas virtual machines virtualize whole guest operating systems.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In raw, the docker allows you to simulate the production environment by replicating it beforehand and then containerizing it and publishing to &lt;a href="https://hub.docker.com" rel="noopener noreferrer"&gt;hub.docker.com&lt;/a&gt;. The important thing to consider is that you want to keep your docker image as minimalistic as possible because it does produce a heavy load for the machine using it. You want to containerize only the service which you need to use and test, eg. for our backend stack, we've had to containerize PHP 8 on Ubuntu, and we've added node, npm, and composer to the container. That's it, voila! Now you'd think that it's smart to ship other technologies to the same container, for example, using this container to test the frontend services would be pretty inefficient.&lt;/p&gt;

&lt;p&gt;A much better approach is to use a different image for each stack you require because otherwise, you will have unused software within your container. &lt;br&gt;
&lt;em&gt;"Yeah I have it on my computer and server too, so what's the deal?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The thing is, for every job in the pipeline, once started, the docker fires a fresh container and boots it up. If you want it to be fast, you want it to be as minimal as possible. Meaning that the backend will have only backend software on its image, whereas the frontend will only boot up node.js image, without PHP and composer. Separating services in different containers will help you speed up the pipeline overall.&lt;/p&gt;

&lt;p&gt;The boot time is the biggest overhead that you get with additional software, but only if you are using the self-hosted runner. Otherwise, if you're running the pipeline on GitLab servers, you need to download the image (container) at every step of the pipeline. And if you have big images with unneeded software, you will both download and boot longer, and GitLab charges per minute of processing time, meaning that you're twice as inefficient. &lt;/p&gt;

&lt;h2&gt;
  
  
  GitLab-ci.yml file
&lt;/h2&gt;

&lt;p&gt;YAML is used because it is easier for humans to read and write than other common data formats like XML or JSON. Further, there are libraries available in most programming languages for working with YAML. For a syntactic guidelines of YAML files, &lt;a href="http://giybf.com" rel="noopener noreferrer"&gt;Google is your best friend&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This file is the main configuration for your Gitlab pipeline. Whenever you add this file to your project, Gitlab will go through it whenever you change something within your project. Here you will define the flow of your pipeline, jobs, stages, what it will do, when will it execute, etc. By default, it will use shared GitLab runners where you'll have &lt;a href="https://about.GitLab.com/blog/2020/09/01/ci-minutes-update-free-users/#changes-to-the-gitlabcom-free-tier" rel="noopener noreferrer"&gt;400 free minutes&lt;/a&gt; monthly, by default.&lt;/p&gt;

&lt;p&gt;The YAML file has a variety of keywords and control structures so you're able to define the what and when. The content of the job, within the &lt;code&gt;script&lt;/code&gt; tag, are the commands which will execute inside the docker container containing your application. Here are some of the most commoontrol structures: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;image&lt;/code&gt; - defines which docker container will run for given job/pipeline (pulls from &lt;a href="https://hub.docker.com" rel="noopener noreferrer"&gt;hub.docker.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stages&lt;/code&gt; - define stages in which you can group your jobs. Stages run serially (one after another), whereas jobs within the same stage run in parallel &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;only&lt;/code&gt; - defines when a job will run (eg. only on merge request)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifacts&lt;/code&gt; - defines which files will be shared between different jobs (because the new container is initialized per job, thus contents are lost unless specified with artifacts)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cache&lt;/code&gt; - defines which files will be saved to the server for retrospection&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;script&lt;/code&gt; - defines what commands will be executed within the container (OS-level commands, eg. &lt;code&gt;echo&lt;/code&gt;, &lt;code&gt;apt-get install&lt;/code&gt;, &lt;code&gt;composer install xy&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are some of the main control structures out of many, for more you can &lt;a href="https://docs.gitlab.com/ee/ci/yaml/index.html" rel="noopener noreferrer"&gt;check the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipeline lifecycle example
&lt;/h2&gt;

&lt;p&gt;The pipeline starts from the &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file. Here we'll analyze a simple pipeline configuration and what happens each step of the way. We will consider the following pipeline for a front-end project. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

image: node:latest

stages:
  - build
  - run

# Job's name
first-job:
  # Define stage
  stage: build
  # What to run on the job.
  script:
    - npm install
  artifacts:
    paths:
      - node_modules

second-job:
  stage: run
  script:
    - npm run start
    - node test.js
  artifacts:
    paths:
      - node_modules/

second-job-parallel:
  stage: run
  script:
    - echo "I'm running at the same time as second-job!!!"


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

&lt;/div&gt;

&lt;p&gt;As we can see, we have two stages, first stage installs the modules and has only one job. The second stage kicks in if the first one finishes successfully and starts two jobs in parallel.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfpk7kplpm9tqm6htqc8.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfpk7kplpm9tqm6htqc8.png" alt="Gitlab's visualization of stages and jobs"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Gitlab's visualization of stages and jobs&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first thing that happens once you push your code is that GitLab scans the &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;. If there are no limitations in configuration, the pipeline will be running on every push, merge request and merge result. Gitlab will then contact the 'runner', aka. the server which will be executing your pipeline. &lt;strong&gt;Note&lt;/strong&gt;, if you have a single GitLab runner they will queue in FIFO principle. &lt;/p&gt;

&lt;p&gt;Once the server responds, it will start the docker executor with the image you've specified. In our case, it is &lt;a href="https://hub.docker.com/_/node?tab=tags&amp;amp;page=1" rel="noopener noreferrer"&gt;node:latest&lt;/a&gt;. If required, you can specify a different image for each job. If the server has the image cached, it will start using it, otherwise, it will have to download it first.&lt;/p&gt;

&lt;p&gt;Then, once you have your container ready and booted up, your project will be downloaded from your repository and once you're placed into the project root directory, it will start executing commands you've provided within the &lt;code&gt;scripts&lt;/code&gt; list. In our case, it will install node modules. Once the job is finished, the artifacts will be uploaded so the next job using can download them back into the container. Then the cleanup kicks in and the container is closed.&lt;/p&gt;

&lt;p&gt;The second job is different, but only slightly. It will download the artifacts right after the project is downloaded, so we have everything ready for scripts. Once this job finishes, it will again upload the modified artifacts for whoever might be using them next. Other than that, it is the same as the first job regarding the structure. But the commands are slightly different, and here as an example, we run test.js to test if our application is working. Here are the contents of test.js:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;console.log('Hello from Node.js!')&lt;br&gt;
console.log(new Date().toUTCString())&lt;br&gt;
console.log('Exiting Node.js...')&lt;/p&gt;

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

&lt;/div&gt;
&lt;h4&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Here is the output from the second job:&lt;br&gt;
&lt;/h4&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqc0aa7e05crmojzuy2yo.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqc0aa7e05crmojzuy2yo.png" alt="Pipeline output on gitlab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the last job is no different from the others, it just proved to us that two jobs can indeed run in parallel.&lt;/p&gt;

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

&lt;p&gt;To conclude the pipelines, I would say that it is a &lt;strong&gt;must&lt;/strong&gt; for any serious company to have these operations set in stone. Human error is removed from the equation and monotonous tasks are automatized. A good pipeline will also deploy the code to a staging server, the company's internal server for testing, quality assurance, and collaboration; but ultimately all productional deploys should be done manually by setting &lt;code&gt;when&lt;/code&gt; key to &lt;code&gt;manual&lt;/code&gt; in &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file. Many many more things could be done within the pipeline such as benchmarking the app, stress-testing, and others. I might cover them in the next blog, but until then, what features do you think would make an awesome pipeline? &lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, click &lt;a href="https://lloyds-digital.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
Also, don’t forget to follow us on &lt;a href="https://www.instagram.com/lloyds.digital/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; and &lt;a href="https://www.facebook.com/lloydsdigital/" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>git</category>
      <category>pipeline</category>
      <category>cicd</category>
    </item>
    <item>
      <title>How to add a splash screen to a React Native app - The easy way</title>
      <dc:creator>Mateo Hrastnik</dc:creator>
      <pubDate>Thu, 27 Jan 2022 12:24:20 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/how-to-add-a-splash-screen-to-a-react-native-app-the-easy-way-3ego</link>
      <guid>https://dev.to/lloyds-digital/how-to-add-a-splash-screen-to-a-react-native-app-the-easy-way-3ego</guid>
      <description>&lt;p&gt;A splash screen is the first screen the users see after tapping the app icon. It's typically a simple screen with your app logo in the center and goes away once the app is ready to launch.&lt;/p&gt;

&lt;p&gt;There are two popular packages for adding a splash screen to your app. Namely &lt;code&gt;react-native-splash-screen&lt;/code&gt; and &lt;code&gt;expo-splash-screen&lt;/code&gt;. While both of them work, the problem is that they're complicated to install and control. There's a much simpler way to add a splash screen and I'm going to show you how.&lt;/p&gt;

&lt;p&gt;The idea is to move the splash screen from native code to Javascript. This will give us more control over the rendering, plus we can have matching splash screens on both platforms. We're going to do a couple of things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Manually set a blank, single-color splash screen background on the native side&lt;/li&gt;
&lt;li&gt;On iOS, set the background color of the React Native root view to that same color&lt;/li&gt;
&lt;li&gt;As soon as React Native loads, add a View with the same color in React Native and fade in the app logo on it&lt;/li&gt;
&lt;li&gt;Once the app loads, fade out the splash screen&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The idea is to show the same color screen while the app boots up and React Native initializes. This is typically really short. Then we fade in the splash screen from our React Native code, and while the splash screen is visible, we can initialize the app, fetch assets, load configuration files, and everything else.&lt;/p&gt;

&lt;p&gt;Here's what the final product looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxod5d5onhevs7wvg5p3n.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxod5d5onhevs7wvg5p3n.gif" alt="App with splash screen" width="296" height="640"&gt;&lt;/a&gt;&lt;/p&gt;
App with splash screen



&lt;p&gt;And here's a GitHub repo with a blank app with the added splash screen functionality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hrastnik/react-native-splash-screen-example" rel="noopener noreferrer"&gt;https://github.com/hrastnik/react-native-splash-screen-example&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Pick a background color and get the hex value and RGB values in range 0-1. In my example I picked &lt;code&gt;#E0B9BB&lt;/code&gt;. The RGB values are 0.87843, 0.72549 and 0.73333. You can use &lt;a href="https://www.easyrgb.com/en/convert.php" rel="noopener noreferrer"&gt;this converter&lt;/a&gt; to grab the RGB values easily.&lt;/p&gt;

&lt;p&gt;Now pick an image you'll show in the center of the splash screen. This can be the logo or the app icon or anything else. In my case, it's a PNG of my cat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting a blank background on iOS
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;AppDelegate.swift&lt;/code&gt; and add this just before the &lt;code&gt;return true&lt;/code&gt; line in the &lt;code&gt;application&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;rootViewController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;!.&lt;/span&gt;&lt;span class="n"&gt;rootViewController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;rootViewController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;red&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;0.87843&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;green&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;0.72549&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;0.73333&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.00000&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;If you're using an older version where you have &lt;code&gt;AppDelegate.mm&lt;/code&gt; do this:&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;AppDelegate.mm&lt;/code&gt; and change add the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight objective_c"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;super&lt;/span&gt; &lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="nf"&gt;didFinishLaunchingWithOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;launchOptions&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight objective_c"&gt;&lt;code&gt;&lt;span class="n"&gt;BOOL&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;super&lt;/span&gt; &lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="nf"&gt;didFinishLaunchingWithOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;launchOptions&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rootViewController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UIColor&lt;/span&gt; &lt;span class="nf"&gt;colorWithRed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;87843&lt;/span&gt; &lt;span class="nf"&gt;green&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;72549&lt;/span&gt; &lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;73333&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're using an even older versions of React Native that uses &lt;code&gt;AppDelegate.m&lt;/code&gt;, open &lt;code&gt;AppDelegate.m&lt;/code&gt; and change the lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight objective_c"&gt;&lt;code&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;@available&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;rootView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UIColor&lt;/span&gt; &lt;span class="nf"&gt;systemBackgroundColor&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="n"&gt;rootView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UIColor&lt;/span&gt; &lt;span class="nf"&gt;whiteColor&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;to simply say&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight objective_c"&gt;&lt;code&gt;&lt;span class="n"&gt;rootView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UIColor&lt;/span&gt; &lt;span class="nf"&gt;colorWithRed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;87843&lt;/span&gt; &lt;span class="nf"&gt;green&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;72549&lt;/span&gt; &lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;73333&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to change the RGB values to match your color.&lt;/p&gt;

&lt;p&gt;This changed the background color of the React Native root view, but we still need to change the background of the whole app. You could do this step through XCode but I find it faster to use a text editor. Simply paste this code in your &lt;code&gt;ios/&amp;lt;AppName&amp;gt;/LaunchScreen.storyboard&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;document&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB"&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"3.0"&lt;/span&gt; &lt;span class="na"&gt;toolsVersion=&lt;/span&gt;&lt;span class="s"&gt;"19529"&lt;/span&gt; &lt;span class="na"&gt;targetRuntime=&lt;/span&gt;&lt;span class="s"&gt;"iOS.CocoaTouch"&lt;/span&gt; &lt;span class="na"&gt;propertyAccessControl=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt; &lt;span class="na"&gt;useAutolayout=&lt;/span&gt;&lt;span class="s"&gt;"YES"&lt;/span&gt; &lt;span class="na"&gt;launchScreen=&lt;/span&gt;&lt;span class="s"&gt;"YES"&lt;/span&gt; &lt;span class="na"&gt;useTraitCollections=&lt;/span&gt;&lt;span class="s"&gt;"YES"&lt;/span&gt; &lt;span class="na"&gt;useSafeAreas=&lt;/span&gt;&lt;span class="s"&gt;"YES"&lt;/span&gt; &lt;span class="na"&gt;colorMatched=&lt;/span&gt;&lt;span class="s"&gt;"YES"&lt;/span&gt; &lt;span class="na"&gt;initialViewController=&lt;/span&gt;&lt;span class="s"&gt;"01J-lp-oVM"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;device&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"retina4_7"&lt;/span&gt; &lt;span class="na"&gt;orientation=&lt;/span&gt;&lt;span class="s"&gt;"portrait"&lt;/span&gt; &lt;span class="na"&gt;appearance=&lt;/span&gt;&lt;span class="s"&gt;"light"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;deployment&lt;/span&gt; &lt;span class="na"&gt;identifier=&lt;/span&gt;&lt;span class="s"&gt;"iOS"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;plugIn&lt;/span&gt; &lt;span class="na"&gt;identifier=&lt;/span&gt;&lt;span class="s"&gt;"com.apple.InterfaceBuilder.IBCocoaTouchPlugin"&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"19519"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;capability&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Safe area layout guides"&lt;/span&gt; &lt;span class="na"&gt;minToolsVersion=&lt;/span&gt;&lt;span class="s"&gt;"9.0"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;capability&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"documents saved in the Xcode 8 format"&lt;/span&gt; &lt;span class="na"&gt;minToolsVersion=&lt;/span&gt;&lt;span class="s"&gt;"8.0"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scenes&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!--View Controller--&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;scene&lt;/span&gt; &lt;span class="na"&gt;sceneID=&lt;/span&gt;&lt;span class="s"&gt;"EHf-IW-A2E"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;objects&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;viewController&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"01J-lp-oVM"&lt;/span&gt; &lt;span class="na"&gt;sceneMemberID=&lt;/span&gt;&lt;span class="s"&gt;"viewController"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;view&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"view"&lt;/span&gt; &lt;span class="na"&gt;autoresizesSubviews=&lt;/span&gt;&lt;span class="s"&gt;"NO"&lt;/span&gt; &lt;span class="na"&gt;opaque=&lt;/span&gt;&lt;span class="s"&gt;"NO"&lt;/span&gt; &lt;span class="na"&gt;clearsContextBeforeDrawing=&lt;/span&gt;&lt;span class="s"&gt;"NO"&lt;/span&gt; &lt;span class="na"&gt;userInteractionEnabled=&lt;/span&gt;&lt;span class="s"&gt;"NO"&lt;/span&gt; &lt;span class="na"&gt;contentMode=&lt;/span&gt;&lt;span class="s"&gt;"scaleToFill"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"1L6-XZ-uwR"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"frame"&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"0.0"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"0.0"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"375"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"667"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;autoresizingMask&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"autoresizingMask"&lt;/span&gt; &lt;span class="na"&gt;flexibleMaxX=&lt;/span&gt;&lt;span class="s"&gt;"YES"&lt;/span&gt; &lt;span class="na"&gt;flexibleMaxY=&lt;/span&gt;&lt;span class="s"&gt;"YES"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;viewLayoutGuide&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"safeArea"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"VQL-mw-5y0"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;color&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"backgroundColor"&lt;/span&gt; &lt;span class="na"&gt;red=&lt;/span&gt;&lt;span class="s"&gt;"0.87843"&lt;/span&gt; &lt;span class="na"&gt;green=&lt;/span&gt;&lt;span class="s"&gt;"0.72549"&lt;/span&gt; &lt;span class="na"&gt;blue=&lt;/span&gt;&lt;span class="s"&gt;"0.73333"&lt;/span&gt; &lt;span class="na"&gt;alpha=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;colorSpace=&lt;/span&gt;&lt;span class="s"&gt;"deviceRGB"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/view&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/viewController&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;placeholder&lt;/span&gt; &lt;span class="na"&gt;placeholderIdentifier=&lt;/span&gt;&lt;span class="s"&gt;"IBFirstResponder"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"iYj-Kq-Ea1"&lt;/span&gt; &lt;span class="na"&gt;userLabel=&lt;/span&gt;&lt;span class="s"&gt;"First Responder"&lt;/span&gt; &lt;span class="na"&gt;sceneMemberID=&lt;/span&gt;&lt;span class="s"&gt;"firstResponder"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/objects&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;point&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"canvasLocation"&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"22"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/scene&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/scenes&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/document&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that you'll have to change the line that starts with &lt;code&gt;&amp;lt;color key="backgroundColor"&lt;/code&gt; and replace the RGB values with your own.&lt;/p&gt;

&lt;p&gt;If you run the app at this point, you should see the background color you picked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr767enafzo6qvp7vnbhb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr767enafzo6qvp7vnbhb.gif" alt="App with blank background" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;
App with blank background



&lt;h2&gt;
  
  
  Setting a blank background on Android
&lt;/h2&gt;

&lt;p&gt;On Android, all you have to do is add the following line to &lt;code&gt;android/app/src/main/res/values/styles.xml&lt;/code&gt; file inside the &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag of your app theme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"android:windowBackground"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;#E0B9BB&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;resources&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;style&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"AppTheme"&lt;/span&gt; &lt;span class="na"&gt;parent=&lt;/span&gt;&lt;span class="s"&gt;"Theme.AppCompat.DayNight.NoActionBar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"android:windowBackground"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;#E0B9BB&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/resources&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The JS part
&lt;/h2&gt;

&lt;p&gt;Now let's add the &lt;code&gt;Splash&lt;/code&gt; component. It works like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;At first, it shows only a blank View with the background color we picked. This is visible until the splash screen image is loaded into memory&lt;/li&gt;
&lt;li&gt;The image fades in&lt;/li&gt;
&lt;li&gt;We wait in this state until the app is initialized and ready to run&lt;/li&gt;
&lt;li&gt;The whole splash screen fades out, revealing the app's first screen&lt;/li&gt;
&lt;li&gt;Finally, the splash screen assets are cleaned up
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WithSplashScreen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;isAppReady&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;isAppReady&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isAppReady&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Splash&lt;/span&gt; &lt;span class="na"&gt;isAppReady&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isAppReady&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LOADING_IMAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Loading image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FADE_IN_IMAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fade in image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WAIT_FOR_APP_TO_BE_READY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Wait for app to be ready&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FADE_OUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fade out&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HIDDEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hidden&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Splash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isAppReady&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;isAppReady&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;containerOpacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageOpacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;LOADING_IMAGE&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;FADE_IN_IMAGE&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;WAIT_FOR_APP_TO_BE_READY&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;FADE_OUT&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;HIDDEN&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LOADING_IMAGE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;FADE_IN_IMAGE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageOpacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;toValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Fade in duration&lt;/span&gt;
        &lt;span class="na"&gt;useNativeDriver&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="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;WAIT_FOR_APP_TO_BE_READY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;imageOpacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;WAIT_FOR_APP_TO_BE_READY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAppReady&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;FADE_OUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isAppReady&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;FADE_OUT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;containerOpacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;toValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Fade out duration&lt;/span&gt;
        &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Minimum time the logo will stay visible&lt;/span&gt;
        &lt;span class="na"&gt;useNativeDriver&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="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HIDDEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;containerOpacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;HIDDEN&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="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;
      &lt;span class="na"&gt;collapsable&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;containerOpacity&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;~/assets/splash.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;fadeDuration&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onLoad&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;FADE_IN_IMAGE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageOpacity&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;resizeMode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"contain"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;absoluteFillObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#E0B9BB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&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;Note that you must change the colors and the path to your image asset to match your project.&lt;/p&gt;

&lt;p&gt;You could add more content to your splash screen if you feel it's necessary.&lt;/p&gt;

&lt;p&gt;Lastly, we need to actually use this component in our app. My app entry point looks like this, and you'll probably have something similar. The idea is to wrap your app entry point in the &lt;code&gt;WithSplashScreen&lt;/code&gt; component and once the app is initialized, set the &lt;code&gt;isAppReady&lt;/code&gt; prop to &lt;code&gt;true&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AppEntry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isAppReady&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsAppReady&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nf"&gt;setIsAppReady&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="p"&gt;});&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WithSplashScreen&lt;/span&gt; &lt;span class="na"&gt;isAppReady&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isAppReady&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StoreProvider&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SafeAreaProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;KeyboardAvoidingView&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ModalProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Router&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ModalProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;KeyboardAvoidingView&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SafeAreaProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;QueryClientProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StoreProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;WithSplashScreen&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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;If you did everything right, the end result should look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxod5d5onhevs7wvg5p3n.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxod5d5onhevs7wvg5p3n.gif" alt="App with splash screen" width="296" height="640"&gt;&lt;/a&gt;&lt;/p&gt;
App with splash screen



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

&lt;p&gt;Instead of adding complex native dependencies that are hard to control, it's easy to add a splash screen to your app with just a couple of changes on the native side. As a benefit, you get extra control over how the splash screen looks and behaves.&lt;/p&gt;

&lt;p&gt;Thanks for giving this article a read! If you've found it useful, consider liking and sharing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lloyds-digital.com/" rel="noopener noreferrer"&gt;Lloyds digital&lt;/a&gt; is available for partnerships and open for new projects. If you want to know more about us, check us out.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>splash</category>
      <category>screen</category>
      <category>easy</category>
    </item>
    <item>
      <title>The ultimate guide for junior frontend developers</title>
      <dc:creator>Nikolina Ljubičić</dc:creator>
      <pubDate>Tue, 10 Aug 2021 06:55:12 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/the-ultimate-guide-for-junior-frontend-developers-cff</link>
      <guid>https://dev.to/lloyds-digital/the-ultimate-guide-for-junior-frontend-developers-cff</guid>
      <description>&lt;p&gt;How hard is it to become a developer? Can I do that? The answer is yes, you can. First of all, it should be noted that this path is not easy; there will undoubtedly be frustration and a desire to give up. If you want to be a good frontend developer, you have to realize that you will never finish learning. I have been through all of this, and I can tell you if you are persistent in achieving your goals, I can guarantee you that you will succeed.&lt;/p&gt;

&lt;p&gt;But how to get to the desired position of junior frontend developer? I believe that most of the students graduating from college are interested in that. Many employers look for people with work experience in their profession, &lt;strong&gt;but how do you gain experience if no one provides you a job opportunity?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sit tight, and let me share my story.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to start?
&lt;/h1&gt;

&lt;p&gt;One solution is to look for a professional internship. Keep in mind that even if you do it pro bono, believe me, it will pay off. Be grateful for the opportunity and try to use that time to learn as much as possible. You’ll have a chance to experience the real work environment, and that’s exactly what you need after college. Try to prove yourself, show the desire to learn, and progress. Don't come to an internship for the formality and signature that you have to take to college; you are making a big mistake that you will only be aware of later. Make the most of that time: ask questions, research, work hard, code, and learn. &lt;strong&gt;Perseverance will pay off.&lt;/strong&gt; It always does. &lt;/p&gt;

&lt;p&gt;However, if you don't have the opportunity to start with an internship, there are other alternatives, such as courses on Udemy, Udacity, Coursera, etc. You can find various courses for less than 15€. And here is a tip for you: the prices of the courses should be researched in the Incognito window, only in this way you will find out the real price. When you take a course, finish it completely and write the code in parallel with the lecturer. In addition, you should regularly take notes on paper or laptop, write comments in the code, and additionally follow official documentation as you discover new things. At that moment, you think you will remember it, but trust me, you probably won’t so you will be grateful when you see that you have something written down. &lt;strong&gt;It has been proven that we remember faster while writing.&lt;/strong&gt; After finishing the course, there is no need to immediately take a new one. You should rather set yourself your own project that needs to be done, and you will be able to apply your knowledge there. To sharpen your skills, it is necessary to complete as many projects as possible and invest a lot of effort in the exercises. This is a guaranteed path to success, no mistake.&lt;/p&gt;

&lt;p&gt;Consistently invest in your knowledge. If you focus on working on yourself, the results will definitely come. That’s guaranteed! Depending on how you want to feel or what you want more in your path to success, choose one book or online program - and get started. Just start somewhere and do it as soon as possible. &lt;strong&gt;Yes, it's never too late, but if you can start learning earlier and possibly create something, why not do it?&lt;/strong&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhy6oc1ggzrsq7y8wsvrw.jpg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhy6oc1ggzrsq7y8wsvrw.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Top tech skills you need to know
&lt;/h1&gt;

&lt;p&gt;First of all, it's important to point out a few significant facts. If you want to become a frontend developer, needless to say, you must know HTML and CSS, because these are the basics. If you are asked at a job interview which programming languages you know, do not say HTML and CSS because they are not programming languages. HTML is a markup language, while CSS is a style language. Five years ago, it was completely normal to say at job interviews that you have knowledge of HTML or CSS, and they would be thrilled. Today is different and much more is expected from you. There is no need for fear; if you have the desire to learn, you will master other programming languages with ease. &lt;/p&gt;

&lt;p&gt;What we need to know now when we talk about the position of a frontend developer are JavaScript and/or TypeScript. Today, it's good to know Sass or Less - both are CSS preprocessors that script superset of CSS that makes writing CSS code easier. &lt;strong&gt;Knowing the rules for responsive web design is a crucial thing you need to know today.&lt;/strong&gt; One of the things that have made my life a lot easier is the &lt;a href="https://jonitrythall.com/content/flexboxsheet.pdf" rel="noopener noreferrer"&gt;CSS flex property&lt;/a&gt;. The number of internet users who access and use the web through smartphones and other mobile devices is constantly increasing at an alarming rate. This means that websites should be even more optimized than before, especially the customization of web design for different types of screen sizes is necessary. If you fail to do that, then you will end up losing customers. Based on &lt;a href="https://www.statista.com/statistics/277125/share-of-website-traffic-coming-from-mobile-devices/" rel="noopener noreferrer"&gt;Statista&lt;/a&gt; research, 54,8% of websites are viewed from a mobile device - use that information wisely.&lt;/p&gt;

&lt;p&gt;Another thing to know are &lt;strong&gt;software version control platforms&lt;/strong&gt; - which allow users to track changes in projects and collaboration between teams during and after software development. There are some free platforms such as GitLab, GitHub, or BitBucket. Realistically, working on it isn’t that abstract at all; it’s quick to learn, and it can make your life so much easier. Trust me, you will sleep more peacefully when you know that everything is stored on your Git.&lt;/p&gt;

&lt;p&gt;It is a big plus for a frontend developer if you know the basics of DNS, HTTP, and HTTPS (read: you have to know it).&lt;/p&gt;

&lt;h1&gt;
  
  
  The soft skills you need to know as a junior frontend developer
&lt;/h1&gt;

&lt;p&gt;Now we came to the point that developers don’t really like, but these skills are just as important as tech skills. These skills do not include programming, but if you stick to them, they can make you a more skilled and better programmer as well as a team player.&lt;/p&gt;

&lt;p&gt;In this industry, things change very quickly, and only by learning can one keep up with new things and technologies. When learning, it is important to be humble and learn from your mistakes because that is one of the better ways to learn. And most important of all, show that you are always passionate and highly motivated for what you do.&lt;/p&gt;

&lt;p&gt;Of course, in this position, the key skill is writing code, but there is much more behind it, and to progress, it is important to know other skills.&lt;/p&gt;

&lt;p&gt;Here are some skills that are important to master:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Written communication.&lt;/strong&gt;  You can't escape it, you will use it every day in email. Try to write in a friendly way, always thank the person for contacting you, and most important of all - quickly get to the point without overcomplicating things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Mentoring.&lt;/strong&gt;  You probably don't understand why a junior frontend developer needs this, but in fact, there is always something you know and some of your colleagues don’t. Also, after a while and after you master things, you find yourself in situations where you need to explain something to someone. Trust me, this is the best way to further solidify and validate your knowledge (and only then realize how much you have already learned!). In principle, as soon as you teach someone something new,  you are on the right track, so just keep it up. I speak from my own experience when I say the combination of learning and mentoring is very effective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Focus.&lt;/strong&gt; In this industry, your focus should be on goals.  For example, to achieve a goal which is developing a website, you have to be focused on details, especially on small ones, because the frontend is just that, what is seen on the user’s screen. The developer must be focused on how the website works and how it will look, although the look and feel are resolved with the designers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Troubleshooting.&lt;/strong&gt;  This aspect is crucial in programming. It would be easiest to remember the commands to copy from StackOverflow and throw in the code. However it is crucial to know the problem, look at the bigger picture of the problem, and only then, with the help of Google and StackOverflow, solve the problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Teamwork.&lt;/strong&gt; If you want to be a good programmer, it is also decisive that you are a team player. There is a lot of collaboration with designers, other developers, clients, and others in this work, so this skill is necessary.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhg06iq48zdcvllf2i9pb.jpg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhg06iq48zdcvllf2i9pb.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What can you do to become a better programmer?
&lt;/h1&gt;

&lt;p&gt;Frontend development is considered to be much harder to master than it was before. The difficulty has remained the same, but web development is evolving very quickly, which entails several new things in a very short time and in a much larger number. That way, you need to learn a lot more things in a shorter amount of time than previously. Documentation will save you in many situations, don't be repulsed by it, read it several times.&lt;/p&gt;

&lt;p&gt;Here are some tips on how to quickly overcome all the difficulties of the programming process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Learn to read someone else's code.  You can find out a lot from it and see good ways to write code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Always be informed - this is one of the ways to help you learn constantly. There is nothing better than listening to industry experts. This allows you to keep up with the dev trends so focus on things you need to master.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attend technical meetings. The advice is to listen to podcasts, follow certain YT channels, join Facebook groups - a lot can be learned from the community.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try to make your code clear and understandable from the beginning. However, once you start training as a programmer, you will certainly try to go back to some parts and prepare that source code. Make your code better for other developers that will work on its maintenance in the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s important to seek feedback, be it good or bad, it will surely help you see what you are doing wrong or which direction you have to follow.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Short tips and tricks
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It’s important to understand the difference between image formats:  PNG, SVG, and JPG. Whenever you need a transparent image, use PNG, when you use icons, use SVG, for full-color images (and whenever possible if you don't need one of the above.), use JPG.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For web optimization, it is necessary to compress images. There are free services available online such as &lt;a href="https://tinypng.com/" rel="noopener noreferrer"&gt;TinyPNG&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you have icons on the web that change color on hover or some other action, use the program for &lt;a href="https://icomoon.io/" rel="noopener noreferrer"&gt;vector icons&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you install some packages but end up not using them, please uninstall those unnecessary packages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the designer didn't prepare the final pictures for you, don't use some crazy gray squares, use &lt;a href="https://placeholder.com/" rel="noopener noreferrer"&gt;placeholders&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Every time you finish a task on your project upload it on Git (&lt;code&gt;git push&lt;/code&gt;) and every time you enter the project use &lt;code&gt;git pull&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What you need to know as a junior frontend developer
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Mandatory knowledge of HTML and CSS (CSS flex property)&lt;/li&gt;
&lt;li&gt;Knowledge of JavaScript or Typescript&lt;/li&gt;
&lt;li&gt;Basic knowledge of WordPress&lt;/li&gt;
&lt;li&gt;Knowing some JS frameworks (e.g. Vue.js, Nuxt.js)&lt;/li&gt;
&lt;li&gt;Basic understanding of SEO optimization&lt;/li&gt;
&lt;li&gt;Knowledge of working on Git&lt;/li&gt;
&lt;li&gt;Know how to use CSS preprocessors - Less or Sass&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Basic things that you need to do on the web as a frontend developer
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Set up SEO optimization&lt;/li&gt;
&lt;li&gt;Enable Google Analytics&lt;/li&gt;
&lt;li&gt;Turn on the Google Search Console&lt;/li&gt;
&lt;li&gt;Turn on Sitemap&lt;/li&gt;
&lt;li&gt;Enable REcaptcha if the website has forms&lt;/li&gt;
&lt;li&gt;Set Error page&lt;/li&gt;
&lt;li&gt;Set up a website favicon&lt;/li&gt;
&lt;li&gt;Set an open graph image&lt;/li&gt;
&lt;li&gt;Placing of lazy loading on images to reduce the initial load &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  To sum it up
&lt;/h1&gt;

&lt;p&gt;I realized over time that the more we know, the clearer it is to us how much we still have to learn. The fact that you know how much you don't know is the best indicator that you already know a lot.&lt;br&gt;
You have to be committed to the end goal, that’s the key that will guide you forward when it gets tough or tricky. &lt;strong&gt;The most important thing is to learn to think like a programmer.&lt;/strong&gt; Once you have fully mastered one programming language, you can easily switch to new languages.&lt;/p&gt;

&lt;p&gt;As long as you’re willing to invest your time learning the necessary skills for a developer, you’ll be at a huge advantage over others, so if you’re not embarking on doing new things, it’s time to do it today.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=PfykaYKS5tY" rel="noopener noreferrer"&gt;Keep on learning!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, click &lt;a href="https://lloyds-digital.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
Also, don’t forget to follow us on &lt;a href="https://www.instagram.com/lloyds.digital/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; and &lt;a href="https://www.facebook.com/lloydsdigital/" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;! &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>Let them call it Blockchain</title>
      <dc:creator>Toni</dc:creator>
      <pubDate>Tue, 23 Mar 2021 10:21:55 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/let-them-call-it-blockchain-5fb0</link>
      <guid>https://dev.to/lloyds-digital/let-them-call-it-blockchain-5fb0</guid>
      <description>&lt;p&gt;With the recent rise of Bitcoin and other cryptocurrency values, there are more and more people interested in buying them. Unfortunately, not many of them are interested in educating themselves before investing. In the media, we can often hear that blockchain is the technology behind bitcoin, and the conferences once called "Bitcoin conference" are now called "Blockchain/crypto conference". In this blog post, I will explain how blockchain works and why it doesn’t actually matter that much.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is a hash function?
&lt;/h1&gt;

&lt;p&gt;Before explaining how blockchain works, it's necessary to know what a hash function is. Hash function gets a string of any length as an input and reproduces output that has the exact length (e.g. 256 bits). The most used algorithm for hashing is called SHA256 (Secure hashing algorithm) which reproduces 256bits (32 bytes) output. Each time we hash the same data, we will get the same result. This function is very useful because it's not possible to decrypt the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4VKhlyOL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hitoceqnjmet2hz2ilfs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4VKhlyOL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hitoceqnjmet2hz2ilfs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What is blockchain?
&lt;/h1&gt;

&lt;p&gt;The shortest explanation - blockchain is a database. This database is made of so-called "blocks". Blocks contain the actual data of transactions. At the end of each block is its hash. We get the block hash when we pull all transactions inside a block through the hash function. The next block adds to the previous by using the previous block hash at the beginning. With this way of storing data, if any data (transaction) changes, the whole chain breaks. Because of this, cryptocurrencies get the characteristic of immutability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---lI6NL_M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/prmbqup355yeej3poa6t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---lI6NL_M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/prmbqup355yeej3poa6t.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Source: &lt;a href="https://bitcoin.org/bitcoin.pdf"&gt;Bitcoin Whitepaper&lt;/a&gt;
&lt;/h6&gt;

&lt;h1&gt;
  
  
  Is every cryptocurrency immutable?
&lt;/h1&gt;

&lt;p&gt;The answer is no. Even though they use blockchain, 99% of them are not immutable. What matters is how new blocks are created. Cryptocurrencies that use proof of work (POW) for creating new blocks are far more secure/immutable. For attacking such a network, you need a lot of electricity, which is expensive. Or in other words, to attack such a network you need to have 51% of the network’s power. On the other hand, many cryptocurrencies use proof of stake and similar technology for validating new transactions. This means the more coins you have stacked, the more likely your block will be included next.&lt;/p&gt;

&lt;h1&gt;
  
  
  Are all proof of work blockchains equally secured?
&lt;/h1&gt;

&lt;p&gt;The answer is, again, no. This depends on how many people currently mine on that network. Their power is measured in the number of hashes per second. The next graph shows the Bitcoin hash rate compared to some other popular cryptocurrencies such as Ethereum or Litecoin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1xLDj8Uj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xl5x700a083118l15ndu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1xLDj8Uj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xl5x700a083118l15ndu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Source: &lt;a href="https://bitinfocharts.com/"&gt;Bitinfocharts&lt;/a&gt;
&lt;/h6&gt;

&lt;h1&gt;
  
  
  Blockchain is slow
&lt;/h1&gt;

&lt;p&gt;Blockchain is a very slow database. A new block (on the bitcoin network) that contains around 3000 transactions is created every 10 minutes. Some people argue that’s the reason behind the unscalability of Bitcoin. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MM5g_hA_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gnyzblgu3svcj82fvcvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MM5g_hA_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gnyzblgu3svcj82fvcvg.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Source : &lt;a href="https://www.researchgate.net/publication/330585021_Analysis_of_the_Possibilities_for_Improvement_of_BlockChain_Technology"&gt;Analysis of the Possibilities for Improvement of BlockChain Technology&lt;/a&gt;
&lt;/h6&gt;

&lt;h1&gt;
  
  
  Why Blockchain then?
&lt;/h1&gt;

&lt;p&gt;Because it's distributed, that's its greatest strength. However, to be distributed, it has to be open, public, and accessible to anyone at any moment. The key is to understand there is no single blockchain, but many copies of the same blockchain on thousands of different nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jYSzc-PL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/300t2cgj63z6d0mf1rhb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jYSzc-PL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/300t2cgj63z6d0mf1rhb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Open vs Closed blockchains
&lt;/h1&gt;

&lt;p&gt;Bitcoin uses a public and open blockchain and doesn’t ask for permission to use it. On the other hand, we have closed blockchains controlled by corporations (e.g. Ripple). In such blockchains, you have to ask for permission and they are able to change data as they will. It still blows my mind that people call them cryptocurrencies.&lt;/p&gt;

&lt;h1&gt;
  
  
  Blockchains only use case
&lt;/h1&gt;

&lt;p&gt;Blockchain on its own is a useless, slow database. This has been proven a thousand times. Only blockchain used together with proof of work, P2P (peer-to-peer), and cryptography is useful and it's called Bitcoin, not blockchain. This still hasn’t stopped people from selling things by promoting them as something new by using words such as blockchain.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final words
&lt;/h1&gt;

&lt;p&gt;Since the rise of bitcoin popularity and its value, we have seen a lot of people and companies trying to make profit by selling their products and calling them innovative and new just because they use blockchain. My opinion is they are not innovative and that blockchain's only use case is bitcoin as the hardest money ever created.&lt;/p&gt;

&lt;p&gt;I highly encourage you to educate yourself more on bitcoin as I think it's &lt;strong&gt;the technology that will change the world&lt;/strong&gt;. I recommend reading &lt;a href="https://www.amazon.com/Bitcoin-Standard-Decentralized-Alternative-Central/dp/1119473861"&gt;Bitcoin Standard&lt;/a&gt; by Saifedean Ammous as well as &lt;a href="https://www.amazon.com/Internet-Money-Andreas-M-Antonopoulos-ebook/dp/B01L9WM0H8/ref=sr_1_1?crid=755IUSZ9BC2M&amp;amp;dchild=1&amp;amp;keywords=internet+of+money&amp;amp;qid=1616163067&amp;amp;s=books&amp;amp;sprefix=internet+of+mon%2Cstripbooks-intl-ship%2C438&amp;amp;sr=1-1"&gt;Internet of money&lt;/a&gt; and &lt;a href="https://www.amazon.com/Mastering-Bitcoin-Programming-Open-Blockchain/dp/1491954388/ref=pd_sim_2?pd_rd_w=sI9cz&amp;amp;pf_rd_p=dc435707-6f1f-492e-b80d-8408db56abc9&amp;amp;pf_rd_r=N04PPYXPQ393AMDH1CMN&amp;amp;pd_rd_r=26a4d193-0fd9-4f4a-8fdf-f5da0e4d97cb&amp;amp;pd_rd_wg=xFGEm&amp;amp;pd_rd_i=1491954388&amp;amp;psc=1"&gt;Mastering Bitcoin&lt;/a&gt; by Andreas Antonopoulos.&lt;/p&gt;

&lt;p&gt;Thank you for reading this! &lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, check out our company profile &lt;a href="https://lloyds.design/weare/Company_Profile_2021_final.pdf"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, don’t forget to follow us on &lt;a href="https://www.linkedin.com/company/lloyds-design-studio"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://facebook.com/lloydsgn"&gt;Facebook&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>bitcoin</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>How to make WooCommerce, CorvusPay and Nuxt.js dance together</title>
      <dc:creator>Dina Knapic</dc:creator>
      <pubDate>Wed, 03 Mar 2021 12:50:42 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/how-to-make-woocommerce-corvuspay-and-nuxt-js-dance-together-cp4</link>
      <guid>https://dev.to/lloyds-digital/how-to-make-woocommerce-corvuspay-and-nuxt-js-dance-together-cp4</guid>
      <description>&lt;p&gt;When you are assigned to do a webshop project where you need to implement a payment gateway on your own for the very first time, along with using an eCommerce platform, you may start to panic. But soon you realize that the hardest part is finding a quiet place in the office to focus on reading the documentation properly. For anyone who needs to fill some voids to make a complete webshop, I hope this post will be right for you.&lt;/p&gt;

&lt;p&gt;In our company, in frontend web dev we use Nuxt framework for Vue.js. WordPress serves us as a headless backend, and to build this specific webshop we decided to give a shot to eCommerce plugin WooCommerce. As a payment gateway our customer chose CorvusPay.&lt;/p&gt;

&lt;p&gt;In general, my tasks for this project were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build UI&lt;/li&gt;
&lt;li&gt;set up WordPress and WooCommerce, add the products data&lt;/li&gt;
&lt;li&gt;get WooCommerce data through REST API&lt;/li&gt;
&lt;li&gt;build shop functionalities&lt;/li&gt;
&lt;li&gt;process payments with Corvus Pay&lt;/li&gt;
&lt;li&gt;get orders to WooCommerce&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Integrating CorvusPay payment gateway
&lt;/h1&gt;

&lt;p&gt;In this post I focused on implementing payment gateway and getting orders to backend.&lt;br&gt;
The whole process is pretty comprehensive and describing it all would take ages, so I rather choose to write about some obstacles, give some advice and point out things to pay more attention to. Some things may seem too obvious, but trust me, they can cause the worst headaches. I’ll go through my project and give you a heads up for problems I stumbled upon.&lt;/p&gt;

&lt;p&gt;In CorvusPay Merchant portal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you register on the CorvusPay Merchant portal, you will need to fill in some company info. Be especially careful with entering the store URL domain, success and cancel URLs. Write HTTP, HTTPS, www and slashes right and be consistent. If you somewhere in the process strip www from URL and somewhere you don’t, you may have some problems, especially because links with and without "www" don't share the same local storage.&lt;/li&gt;
&lt;li&gt;Choose GET http postback method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;As the order number must be unique for every order sent on checkout, you need to find a way to generate it. You can write some functions that return unique numbers, or you can go the very easy way using  &lt;code&gt;new Date().getTime()&lt;/code&gt;, a function that returns current time in milliseconds. There is a very, very, very small chance that two customers will hit the buy button in the exact same millisecond, so I went with that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don’t be surprised if nothing happens when you change email language in the Merchant portal. The language parameter you include in the POST method is the language the sent emails will be written in. Even if you choose a different language in the CorvusPay Merchant portal, the one in the POST method will win.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amount parameter must have a decimal point, not a comma, and have two decimal digits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In signature, beware you include all mandatory parameters, sorted alphabetically and concatenated without separators. POST requests must be signed using HMAC-SHA256. To do that, I installed &lt;code&gt;vue-criptojs&lt;/code&gt; package. Signature was then created as simple as: &lt;code&gt;const signature = this.CryptoJS.HmacSHA256(parameters, this.corvusSecretKey)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can include cardholder data in signature, but you don't have to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you go live don’t forget to change Store ID, Secret key and checkout URL to wallet.corvuspay.com/checkout.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you carefully go through documentation and you do above said things right, your buyer will now be successfully redirected to the CorvusPay checkout page, where they will see the total amount, fill in credit card data and make a payment. When buyers complete this step they will be redirected to the success URL provided by you in the CorvusPay Merchant portal.&lt;br&gt;
At the same time payment/order gets to Merchant portal for the company owner to see, email is sent to the shop owner and to the customer. This could be the final step for some simple online purchase.&lt;/p&gt;

&lt;h1&gt;
  
  
  Sending orders to WooCommerce
&lt;/h1&gt;

&lt;p&gt;But if you also have an eCommerce platform like WooCommerce in your project, your job here is far from over.&lt;br&gt;
You need to find a way to send all the purchase data to WooCommerce if the payment is done correctly. Where do you start? You may notice the success page provides you with order data in the URL when landing on it, and we will use that. &lt;br&gt;
Now go back to your code. In the same function where you are submitting data to Corvus checkout, also store in the browser's local storage all the needed order data you prepared for WooCommerce, along with the order number. The order number is mandatory because it will be used as an identifier. On your success page write a function that gets the order_number parameter from the URL. You can use &lt;code&gt;this.$route.query.order_number&lt;/code&gt;. When you finally get the order number, perform the search for it in the local storage. If found, send belonging order data to WooCommerce with the POST method. &lt;/p&gt;

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

&lt;p&gt;Building a webshop for the first time requires quite a bit of time and a lot of nerves. There are many dots you have to connect, and they all have to collaborate together well. But once you figure it all out, life gets much easier. At least until you get a more advanced task to implement next time.&lt;/p&gt;




&lt;p&gt;Thank you for reading this! If you've found this interesting, consider leaving a ❤️, 🦄, and of course, share and comment your thoughts!&lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, click &lt;a href="https://lloyds-design.com/"&gt;here&lt;/a&gt;.&lt;br&gt;
Also, don’t forget to follow us on &lt;a href="https://www.instagram.com/lloyds.design/"&gt;Instagram&lt;/a&gt; and &lt;a href="https://www.facebook.com/lloydsgn/"&gt;Facebook&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>payment</category>
      <category>corvuspay</category>
      <category>woocommerce</category>
      <category>nuxt</category>
    </item>
    <item>
      <title>Stripe in-app payments in React Native</title>
      <dc:creator>Masimo Orbanic</dc:creator>
      <pubDate>Tue, 08 Dec 2020 11:05:29 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/stripe-in-app-payments-in-react-native-27jg</link>
      <guid>https://dev.to/lloyds-digital/stripe-in-app-payments-in-react-native-27jg</guid>
      <description>&lt;p&gt;Stripe is currently one of the best payment services that you can use in your web and mobile applications. It offers many features like subscriptions, the option to collect payments from customers and pay them out to sellers or service providers, invoicing, and many other good things. It is also very developer-friendly, it has support for popular programming languages, Webhooks for all types of events and the developer documentation is well written.&lt;/p&gt;

&lt;p&gt;🚨 Important 🚨&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Since May 2021 Stripe has an official package to support React Native platform called &lt;a href="https://github.com/stripe/stripe-react-native"&gt;stripe-react-native&lt;/a&gt; . It's recommended to use the official package for long term support and stability. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Stripe does not have an official package for React Native, but the community has some libraries to offer. One of them is &lt;a href="https://github.com/tipsi/tipsi-stripe"&gt;tipsi-stripe&lt;/a&gt;. The stable release of tipsi-stripe is not currently supported (December 2020) because the last stable release is from August 2019, and since then the EU Strong Customer Authentication (SCA) came into power. It requires a major update of the package because the native part of the package has been updated. The version of tipsi-stripe that supports SCA &lt;a href="https://github.com/tipsi/tipsi-stripe/tree/8.0.0-beta.11"&gt;8.0.0-beta.11&lt;/a&gt; is still being developed.&lt;/p&gt;

&lt;p&gt;Another package is react-native-stripe-payments, it has a stable release that supports SCA, but accepts only payments with credit cards. Other methods are not supported. We in &lt;a href="https://lloyds-design.com/"&gt;Lloyds&lt;/a&gt; are using react-native-stripe-payments and so far it is working well.&lt;/p&gt;

&lt;h1&gt;
  
  
  What do you need in order to implement Stripe?
&lt;/h1&gt;

&lt;p&gt;The first thing you will need is, of course, a &lt;a href="https://dashboard.stripe.com/register"&gt;Stripe account&lt;/a&gt;. After you create one, you are free to jump into testing mode by turning on the test mode ("View test data" switch in the sidebar). To switch Stripe to production environment, you must enter a bunch of company data and bank account information to receive payments. Also, you must be sure that Stripe is &lt;a href="https://stripe.com/global"&gt;available in the country&lt;/a&gt; where the company is registered.&lt;/p&gt;

&lt;p&gt;In order to have Stripe in your React Native app, you must have a backend where the majority of the checkout process is defined. The official Stripe package is available for Node, Ruby, Python, PHP, .NET, Java and Go. In &lt;a href="https://lloyds-design.com/"&gt;Lloyds&lt;/a&gt; we are using Laravel, a PHP framework.&lt;/p&gt;

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

&lt;p&gt;Everything is revolving around &lt;a href="https://stripe.com/docs/payments/payment-intents"&gt;Payment intents&lt;/a&gt;. Payment intents track a payment, from initial creation through the entire checkout process, and triggers additional authentication steps when required. In order for react-native-stripe-payments to work, you must have &lt;em&gt;&lt;a href="https://stripe.com/docs/payments/payment-intents#passing-to-client"&gt;client_secret&lt;/a&gt;&lt;/em&gt; which is retrieved from the backend where the payment intent is created. &lt;/p&gt;

&lt;p&gt;The flow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;user presses the BUY button,&lt;/li&gt;
&lt;li&gt;a request containing items to buy is sent to the backend,&lt;/li&gt;
&lt;li&gt;payment intent is created on the backend and &lt;em&gt;client_secret&lt;/em&gt; is returned in the response,&lt;/li&gt;
&lt;li&gt;user is prompted to enter credit card details,&lt;/li&gt;
&lt;li&gt;payment is confirmed on the client-side using &lt;em&gt;client_secret&lt;/em&gt; and credit card details,&lt;/li&gt;
&lt;li&gt;payment confirmation is recorded in the backend using Stripe Webhooks&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since the items to buy and &lt;em&gt;client_secret&lt;/em&gt; are the only two thing shared between client and server, this process is very secure, there is very little room for the corruption of the payment process.&lt;/p&gt;

&lt;h1&gt;
  
  
  Backend
&lt;/h1&gt;

&lt;p&gt;Backend is used to create Payment intent and to store information about the transactions that occurred.&lt;/p&gt;

&lt;p&gt;First, we add the &lt;a href="https://stripe.com/docs/api"&gt;Stripe package&lt;/a&gt; to our framework so our backend can communicate with Stripe.&lt;/p&gt;

&lt;p&gt;In total, the basic implementation of Stripe requires two API endpoints to be created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;to create payment intent and return &lt;em&gt;client_secret&lt;/em&gt; to client&lt;/li&gt;
&lt;li&gt;Webhook URL to receive information from Stripe about a successful payment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The endpoint to create payment intent is used to create payment intent and to bind created payment intent to order in the database. The order in the database must have stored information about payment intent because the payment is not confirmed yet, the confirmation of the payment is done through the Webhook endpoint. The response must contain &lt;em&gt;client_secret&lt;/em&gt;, which can be found in the created Payment intent object. &lt;/p&gt;

&lt;p&gt;The request from Stripe to our backend (Webhook) contains data about the payment intent, so we can find an order which is bound to payment intent in the database and mark that order as completed. Webhook can be configured on &lt;a href="https://dashboard.stripe.com/webhooks"&gt;Stripe dashboard&lt;/a&gt;. The event that you want to trigger is &lt;code&gt;payment_intent.succeeded&lt;/code&gt;. That is just the basic setup, but with Stripe Webhooks you can configure Webhook for many types of events, in other words, notify your backend about the change that occurred.&lt;/p&gt;

&lt;h1&gt;
  
  
  React Native
&lt;/h1&gt;

&lt;p&gt;As mentioned earlier, we will use the &lt;a href="https://github.com/Fitpassu/react-native-stripe-payments"&gt;react-native-stripe-payments&lt;/a&gt; package. Installation of the package does not require any linking process, everything is handled with autolinking. &lt;/p&gt;

&lt;p&gt;The package is very simple and does not require a lot of configuration. The first thing we must do is to call &lt;code&gt;setOptions&lt;/code&gt; method and pass the &lt;a href="https://stripe.com/docs/keys"&gt;Stripe publishing key&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-stripe-payments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setOptions&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;publishingKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;STRIPE_PUBLISHING_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next thing, as we described in the "How it works" section, we'll send a request to your backend on route to create payment intent. In the request, you can pass the cart_id, or array of cart items that are being bought, as long as you can calculate the total price, you are good.&lt;br&gt;
If the request was successful, the backend should return you the &lt;em&gt;client_secret&lt;/em&gt;, and you can prompt the user to enter his credit card details. You can create your own design of the credit card input, or you can use &lt;a href="https://github.com/sbycrosz/react-native-credit-card-input"&gt;react-native-credit-card-input&lt;/a&gt; or some other credit card input package. You can check if the credit card is valid using the stripes &lt;code&gt;isCardValid&lt;/code&gt; &lt;a href="https://github.com/Fitpassu/react-native-stripe-payments#validate-the-given-card-details"&gt;method&lt;/a&gt;. For testing you can find the test credit cards &lt;a href="https://stripe.com/docs/testing"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When you have &lt;em&gt;client_secret&lt;/em&gt; and valid credit card, you can run the &lt;code&gt;confirmPayment&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;confirmPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;client_secret_from_backend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cardDetails&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// payment was successful&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// error occurred&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the payment was successful, Stripe will fire a Webhook request to the backend, and the backend will make a record that the transaction occurred and store data relevant to the transaction so the transaction can be back-traced if needed. You can also check the received payments on the &lt;a href="https://dashboard.stripe.com/test/dashboard"&gt;Stripe dashboard&lt;/a&gt; and make sure that the transaction was successful. &lt;/p&gt;

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

&lt;p&gt;The process of payment on the web and in mobile apps is evolving and is being made secure every day. It is on the developer to create flexible solutions and quickly respond to the changes that need to be made. Also, don't forget to check if you are viewing the test data or live data on the Stripe dashboard 🙂&lt;/p&gt;

&lt;p&gt;Thank you for reading this! If you've found this interesting, consider leaving a ❤️, 🦄, and of course, share and comment your thoughts!&lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, click &lt;a href="https://lloyds-design.com/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, don’t forget to follow us on &lt;a href="https://www.instagram.com/lloyds.design/"&gt;Instagram&lt;/a&gt; and &lt;a href="https://www.facebook.com/lloydsgn/"&gt;Facebook&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>stripe</category>
      <category>payment</category>
      <category>checkout</category>
    </item>
    <item>
      <title>Modern desk setup for developers in 2020</title>
      <dc:creator>Dominik Rusac</dc:creator>
      <pubDate>Wed, 25 Nov 2020 12:36:29 +0000</pubDate>
      <link>https://dev.to/lloyds-digital/modern-desk-setup-for-developers-in-2020-9co</link>
      <guid>https://dev.to/lloyds-digital/modern-desk-setup-for-developers-in-2020-9co</guid>
      <description>&lt;p&gt;I spent a lot of time looking at different pieces of IT equipment and how to connect them most efficiently for everyday use. Every developer prefers their own type of desk setup. Some developers find one laptop enough while others like a multi-monitor setup with laptop or desktop PC. I prefer a laptop with two extra monitors while I work in the office because I find that as my perfect desk setup.&lt;/p&gt;

&lt;p&gt;You are asking why this is my perfect setup? On two big screens, I can do the main work while I am using the 3rd screen (laptop) as an additional helping screen. I use my main screen in the middle and that’s where I write the code while my second screen on the left is showing the result of the code I wrote on my main screen. Also I use my left screen for browsing the internet and reading the documentation. &lt;/p&gt;

&lt;p&gt;The laptop is on my right and depending on what I'm doing at the moment, there is usually Slack, Insomnia or Chrome DevTools opened if I am doing some JavaScript. Sometimes I think it would be nice to have a 4th screen for browsing MySQL database in phpmyadmin but I’m fine for now. 😄&lt;/p&gt;

&lt;p&gt;What would be the best way to connect every piece of hardware to a laptop?&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjxx4zedqe3hkoysugr5j.jpg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjxx4zedqe3hkoysugr5j.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Content:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Efficient connection with peripherals&lt;/li&gt;
&lt;li&gt;Today's laptops...&lt;/li&gt;
&lt;li&gt;Why Type-C?&lt;/li&gt;
&lt;li&gt;How? What are the requirements?&lt;/li&gt;
&lt;li&gt;What about the second monitor?&lt;/li&gt;
&lt;li&gt;Possible problems and solutions&lt;/li&gt;
&lt;li&gt;Which monitor and how many?&lt;/li&gt;
&lt;li&gt;Laptop specifications?&lt;/li&gt;
&lt;li&gt;Keyboard and mouse&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Efficient connection with peripherals &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;For sure, there also must be a headset, separate keyboard and mouse connected to my laptop. All of that must be connected with the minimum number of cables. The desk needs to be as clean as possible with the ability to quickly connect and start working. &lt;/p&gt;

&lt;p&gt;When I need to take my laptop to a meeting, I don’t want to have to disconnect a lot of cables from my laptop, and when I get back on my desk reconnect all the cables back. That’s inefficient and annoying. I needed to come up with the perfect solution on how to connect all peripherals and two extra monitors to a laptop using as few cables as possible. &lt;/p&gt;

&lt;p&gt;A lot of questions came up, but the final, perfect solution was found. Connect everything together using a single Thunderbolt 3 / Type-C cable. Type-C is the perfect solution for my problem and probably for yours too. When I get back to my desk after the meeting, plugging in one cable instantly connects the headset, keyboard, mouse, two monitors and power to my laptop and my desk is usable in a second! Isn’t that nice? I love it. To achieve that level of connectivity, your equipment must support it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Today's laptops... &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Many modern laptops have fewer connectivity options than older laptops. Few years ago, laptops had VGA, HDMI and Display port built-in, so you could easily connect multiple monitors using a few cables. Today that's not the case. For example, the new Apple Macbook has only 4 ports and they are all the same - Type-C/Thunderbolt which means no VGA, HDMI or Display port connectivity.&lt;/p&gt;

&lt;p&gt;I found out that's also the case with other brands, the more expensive the laptop is the fewer ports it has. That’s a little bit odd, don’t you think? It is, but the premium laptop has premium connectivity ports, and the premium connectivity port today is Type-C / Thunderbolt port.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Type-C? &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;On cheap laptops, you’ll hardly find a Type-C/Thunderbolt port. Cheaper non-premium laptops still have some ports for connecting to external displays, most common today are HDMI and DisplayPort. Connecting through these you can get video and audio to your monitor, but you still need to connect the keyboard and mouse to your laptop via USB. And also you need your laptop charger plugged in. That’s like 4 cables already connected to a laptop which is really messy. So how can we fix that? Type-C to the rescue! &lt;/p&gt;

&lt;p&gt;Type-C can do all that through one cable. Yes, you read that correctly. To achieve that, it is required to have a Type-C supported monitor. Once your laptop is connected to your monitor via Type-C cable, you can connect all of your peripherals to that monitor. Through the monitor everything is connected to a laptop via single Type-C cable. Boy, that’s clean!&lt;/p&gt;

&lt;h3&gt;
  
  
  How? What are the requirements? &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To be able to connect your setup this way, your hardware must support it. For sure, you must have Type-C/Thunderbolt port on your laptop and at least one Type-C external monitor. &lt;/p&gt;

&lt;p&gt;When you buy a Type-C monitor you should also get a Type-C cable in the box, at least that’s the case with Dell’s monitors. You should use that cable to connect your laptop to the monitor. Once connected, since the monitor has a 3.5 audio jack and multiple USB ports, you can easily connect your headset, mouse, keyboard, smartphone and all other devices you use to your monitor. All of that is instantly connected to your laptop through the single Type-C cable.&lt;/p&gt;

&lt;p&gt;Another great thing about Type-C is that you don’t need to use your laptop charger because the monitor provides power to your laptop through the same Type-C cable. Single Type-C cable carries power, data, display and audio all at once. How awesome is that?&lt;/p&gt;

&lt;h3&gt;
  
  
  What about the second monitor? &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now we have connected one monitor, keyboard, mouse and headset to our laptop using only one cable. How to connect the second monitor to our setup? It’s pretty simple as long as your monitor supports MST (Multi-Stream Transport), also known as Daisy Chaining. If your monitor has one display port input (DP IN) and one display port output (DP OUT) that means your monitor supports MST/Daisy Chain, but to be sure take a closer look into monitor specifications.&lt;/p&gt;

&lt;p&gt;The first monitor your laptop is connected to via Type-C cable should support MST/Daisy Chain. You simply use a display port cable to connect the first monitor to your second monitor. In the first monitor (the one connected to laptop via Type-C), plug your display port cable in DP OUT and on the second monitor plug that same display port cable in DP IN port. You got two monitors connected to your laptop all together with all of your peripherals that go into your laptop through one single Type-C cable. Let me repeat, ONE cable!&lt;/p&gt;

&lt;h3&gt;
  
  
  Possible problems and solutions &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If you don’t get a picture on some of your monitors, first make sure the proper input source is set up in the monitor settings. The first monitor input source must be set on “Type-C” while the second monitor input source must be set on “Display port”.&lt;/p&gt;

&lt;p&gt;Also, MST must be turned on in your first monitor settings so you are able to get a picture on the second display. If you still have problems after that make sure you are using DP v1.2 cable or newer. If you don’t get a picture even on the first monitor, try to use higher quality Type-C cable. Not every Type-C cable is gonna work, but the cable that comes in a box with a monitor should always work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which monitor and how many? &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The number of monitors mostly depends on what you prefer and how you work. The more monitors you have, the more space you have to work on without minimizing the windows all the time. That way it’s faster and easier to work and because of that you are more efficient and you make more money! 💵&lt;/p&gt;

&lt;p&gt;While choosing the new monitor, make sure it supports MST/Daisy Chaining and Type-C connectivity. Dell has a lot of nice Type-C monitors, for example, U2419HC is the one that supports everything you need to connect to the laptop the way I described. Look for letter “C” in the model name to be sure it supports Type-C connectivity. Also make sure that monitor has sufficient USB ports on the back and audio jack for connecting headphones.&lt;/p&gt;

&lt;p&gt;I wouldn’t recommend a monitor sized under 24-inches, if possible go with a 27-inch with a 2K resolution. Full HD is fine on a 24-inch, but on a 27-inch monitor it’s not that good. IPS panel type would probably be the best, also VA is fine except for some lower viewing angles, as long as you sit in front of it, it will be fine and will probably have a better contrast.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laptop specifications &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Always look for the best laptop your money can buy. Don’t buy the first laptop you see, do your research. I recommend a configuration with at least 12 GB RAM (don’t go under 8 GB) and Intel i5 CPU. A dedicated GPU is a plus but not required. SSD is a must with a capacity of 250/500 GB. Make sure it has at least one Type-C/Thunderbolt port, other ports like USB Type A and audio jack are welcome.&lt;/p&gt;

&lt;p&gt;The ideal screen size for a laptop would be 14” because it’s in the perfect middle of 13” and 15” laptop screens. I left out 17” laptops because they are too big and heavy to carry around. I wouldn’t mind a 13” laptop as long as I am using two external monitors with it. Still, 14” seems ideal with of course Full HD resolution or better.&lt;/p&gt;

&lt;p&gt;A bigger battery means longer battery life and battery life is important. Look for around 50-60 Wh battery which should get you through the day. High quality keyboard and touchpad is also a thing you should worry about - you don't want laggy touchpad or squeaky keyboard. Overall laptop build quality is better the more money you spend. Also, you will pay more for a thinner and lighter laptop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyboard and mouse &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This mostly depends on your preferences and budget. Whether you want classic, mechanical, small size (tenkeyless) or a full size keyboard. I currently use Logitech K280 wired keyboard which is fine but... I am looking at you Logitech MX keys.&lt;/p&gt;

&lt;p&gt;I use Logitech G502 wired mouse and I find it almost perfect, it has all the extra buttons I need. There is also an even better G502 Lightspeed which is practically identical but wireless. You could pair your wireless mouse with wireless charging mousepad so you don't need to worry about the battery.&lt;/p&gt;

&lt;p&gt;Choose what suits you best and go wireless for an even cleaner desk setup!&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A desk that makes you comfortable and suits your needs is a productive desk. Make sure you organize it the way you want as this will lead you to grow and become a better and more efficient developer!&lt;/p&gt;

&lt;p&gt;Happy coding everyone!&lt;/p&gt;




&lt;p&gt;Thank you for reading this! If you've found this interesting, consider leaving a ❤️, 🦄, and of course, share and comment your thoughts!&lt;/p&gt;

&lt;p&gt;Lloyds is available for partnerships and open for new projects. If you want to know more about us, click &lt;a href="https://lloyds-design.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, don’t forget to follow us on &lt;a href="https://www.instagram.com/lloyds.design/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; and &lt;a href="https://www.facebook.com/lloydsgn/" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>modern</category>
      <category>desk</category>
      <category>setup</category>
      <category>developer</category>
    </item>
  </channel>
</rss>
