<?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: Chaudhry Talha 🇵🇸</title>
    <description>The latest articles on DEV Community by Chaudhry Talha 🇵🇸 (@thechaudhrysab).</description>
    <link>https://dev.to/thechaudhrysab</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891299%2Fb6889c8f-22ae-417f-8e58-c945a565e840.jpg</url>
      <title>DEV Community: Chaudhry Talha 🇵🇸</title>
      <link>https://dev.to/thechaudhrysab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thechaudhrysab"/>
    <language>en</language>
    <item>
      <title>TLDR; Deploy Vite + ReactJS App to Cloudflare Pages</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Sun, 05 Apr 2026 16:56:01 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/tldr-deploy-vite-reactjs-app-to-cloudflare-pages-5f5h</link>
      <guid>https://dev.to/thechaudhrysab/tldr-deploy-vite-reactjs-app-to-cloudflare-pages-5f5h</guid>
      <description>&lt;p&gt;Assuming you already have created a vite + react-js project.&lt;/p&gt;

&lt;p&gt;Open &lt;a href="https://dash.cloudflare.com/" rel="noopener noreferrer"&gt;cloudflare dashboard&lt;/a&gt; and login to you account. Cloudflare, go to &lt;strong&gt;Compute &amp;gt; Workers &amp;amp; Pages&lt;/strong&gt; and then click &lt;strong&gt;Create application&lt;/strong&gt; you'll see something similar to 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%2Fc6ld3p9mdcr654qwatcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6ld3p9mdcr654qwatcl.png" alt=" " width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Looking to deploy pages? Get started&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Click on the &lt;strong&gt;Get started&lt;/strong&gt; next to &lt;strong&gt;Import an existing Git repository&lt;/strong&gt; option:&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%2F5i5moevl2yypau897h1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5i5moevl2yypau897h1i.png" alt=" " width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select your github repository where your vite + reactjs project is, and click on &lt;strong&gt;Begin Setup&lt;/strong&gt;:&lt;/p&gt;

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

&lt;p&gt;Select the branch on which anytime you commit and push the code to cloudflare will automatically run your build and deploy command (basically taking care of the CI/CD for your react project). As the project is vite + reactjs project so the run command and output directory by default will be as it is shown in the image below.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can add &lt;code&gt;.env&lt;/code&gt; variables at this stage as well if you have any. The arrow is point to that in the image, but it is optional and you can always add/edit them later.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;strong&gt;Save &amp;amp; Deploy&lt;/strong&gt; to continue.&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%2F6gngmtcvjqsh1x31fk9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gngmtcvjqsh1x31fk9j.png" alt=" " width="800" height="854"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once deployed you can check out the URL it has given. Now anytime you push code to the branch you select it'll deploy the app automatically.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>cloud</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>TLDR; ReactJS project initialization with Tailwind CSS and Shadcn using Vite</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Sat, 14 Mar 2026 18:24:17 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/tldr-reactjs-project-initialization-with-tailwind-css-and-shadcn-using-vite-4g0f</link>
      <guid>https://dev.to/thechaudhrysab/tldr-reactjs-project-initialization-with-tailwind-css-and-shadcn-using-vite-4g0f</guid>
      <description>&lt;p&gt;TLDR; guide of initializing a ReactJS project using Vite and installing TailwindCSS and Shadcn. You can choose to use pure CSS as well.&lt;/p&gt;

&lt;p&gt;Run this command to create a new project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest my-app &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react-ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F0zcquehry5lgivbk3p9v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zcquehry5lgivbk3p9v.png" alt=" " width="671" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above the dependencies are automatically installed. To manually install dependencies and running the app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
yarn &lt;span class="nb"&gt;install
&lt;/span&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you open localhost:5137 the URL given in your terminal you'll see something similar to 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%2F5fyuqi9hqp3dhxnyvynj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fyuqi9hqp3dhxnyvynj.png" alt=" " width="706" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tailwind Setup
&lt;/h2&gt;

&lt;p&gt;Install the required package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; tailwindcss @tailwindcss/vite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;shadcn absolutely requires path aliases (&lt;code&gt;@/components/...&lt;/code&gt;) to work, so we'll need to install this package as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; @types/node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;vite.config.ts&lt;/code&gt; file and in it add &lt;code&gt;tailwindcss()&lt;/code&gt; in plugins and the whole &lt;code&gt;resolve: {…&lt;/code&gt; object as shown below:&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;tailwindcss&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;@tailwindcss/vite&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="nx"&gt;react&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;@vitejs/plugin-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="nx"&gt;path&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;path&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;defineConfig&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;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// https://vite.dev/config/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;tailwindcss&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src&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="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;&lt;em&gt;If you're seeing errors in import statements see the pnp fix in at the end of this post&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now open &lt;code&gt;tsconfig.json&lt;/code&gt; and ensure it matches the below code i.e. added &lt;code&gt;"compilerOptions": {…&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"references"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./tsconfig.app.json"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./tsconfig.node.json"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./src/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;src/index.css&lt;/code&gt; and remove everything in it and add this on top of that file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;"tailwindcss"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  shadcn/ui Setup
&lt;/h2&gt;

&lt;p&gt;From you app root directory in terminal, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx shadcn@latest init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F8lhnnktmcmk77t5is039.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8lhnnktmcmk77t5is039.png" alt=" " width="469" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;Radix&lt;/strong&gt; if prompted to select a component library. Which preset would you like to use I selected &lt;strong&gt;Vega&lt;/strong&gt; and you can select any.&lt;/p&gt;

&lt;p&gt;Let's install the button UI from shadcn to test if we got it installed successfully:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx shadcn@latest add button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test everything
&lt;/h3&gt;

&lt;p&gt;To test if everything is working okay let's replace the &lt;code&gt;&amp;lt;button&lt;/code&gt; with the button from shadcn in &lt;code&gt;App.tsx&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&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;./components/ui/button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//... Other code        &lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
          &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;destructive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-black"&lt;/span&gt;
          &lt;span class="na"&gt;onClick&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&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="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          count is &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&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;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F6lq6afmytaq6n568kem6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lq6afmytaq6n568kem6.png" alt=" " width="800" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The red color is coming from Shadcn variant and the background black is added via tailwind.&lt;/p&gt;




&lt;h4&gt;
  
  
  pnp error from yarn
&lt;/h4&gt;

&lt;p&gt;When using &lt;code&gt;yarn&lt;/code&gt; to install packages etc, the latest version install and manages packages using &lt;strong&gt;Yarn Plug'n'Play&lt;/strong&gt; (there will be a pnp file created in your codebase instead of &lt;code&gt;node_modules&lt;/code&gt; folder) if you use yarn. To use the traditional &lt;code&gt;node_modules&lt;/code&gt; you can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn &lt;span class="nb"&gt;set &lt;/span&gt;version stable
yarn config &lt;span class="nb"&gt;set &lt;/span&gt;nodeLinker node-modules
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; .pnp.cjs .pnp.loader.mjs node_modules
yarn &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this restart your IDE if it is still not resolving the imports.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>TLDR; Google Auth in ReactJS using Supabase</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Fri, 10 Oct 2025 15:02:16 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/tldr-google-auth-in-reactjs-using-supabase-h16</link>
      <guid>https://dev.to/thechaudhrysab/tldr-google-auth-in-reactjs-using-supabase-h16</guid>
      <description>&lt;p&gt;My project was created using vite + react-js. &lt;/p&gt;

&lt;p&gt;Let's get the required keys from Google Cloud Console. I have these two URLs form which I'll be sending the google sign-in request from Local host i.e. &lt;code&gt;http://localhost:5173&lt;/code&gt; and a Production URL &lt;code&gt;https://MY_DOMAIN_NAME.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Go to &lt;strong&gt;&lt;a href="https://console.cloud.google.com/welcome/new" rel="noopener noreferrer"&gt;Google Cloud Console&lt;/a&gt;&lt;/strong&gt; create/select a new proejct → in search bar search &lt;strong&gt;OAuth consent screen&lt;/strong&gt; and select it:&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%2Fqe6zdg94wehvrc30llts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqe6zdg94wehvrc30llts.png" alt=" " width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Branding&lt;/strong&gt; you'll need to add you &lt;code&gt;https://MY_DOMAIN_NAME.com&lt;/code&gt; in the &lt;strong&gt;Authorized domains&lt;/strong&gt; section:&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%2Fopx5bg5rlie3xne9rsa8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopx5bg5rlie3xne9rsa8.png" alt=" " width="800" height="1145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can keep the app in test mode or &lt;strong&gt;Publish App&lt;/strong&gt;. I'll keep it in test mode and click on &lt;strong&gt;+ Add users&lt;/strong&gt; towards the end under &lt;strong&gt;Test users&lt;/strong&gt;. These users will be allowed to login into the app only.&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%2F43lud6jvjprmotalfpds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43lud6jvjprmotalfpds.png" alt=" " width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you decides to publish you'll need to have links for privacy policy and terms of service to your website.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Click Clients on the left sidebar. Click Create OAuth client.&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%2F0m6z5bo6xu4vj42f88rn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0m6z5bo6xu4vj42f88rn.png" alt=" " width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fill out name of your project&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%2F5adpubiblnuz9yt2wjcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5adpubiblnuz9yt2wjcl.png" alt=" " width="800" height="1193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Authorized redirect URIs: Paste your exact Supabase callback URL. It looks exactly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;YOUR_PROJECT_ID&amp;gt;.supabase.co/auth/v1/callback
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find the ...supabase.co/auth/v1/... from &lt;em&gt;Supabase Dashboard -&amp;gt; Authentication -&amp;gt; Sign In / Providers &amp;gt; Google&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Click &lt;strong&gt;Create&lt;/strong&gt;. Copy the &lt;strong&gt;Client ID&lt;/strong&gt; and &lt;strong&gt;Client Secret&lt;/strong&gt; it gives you.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;Next, back in your &lt;em&gt;Supabase Dashboard -&amp;gt; Authentication -&amp;gt; Sign In / Providers &amp;gt; Google&lt;/em&gt;, toggle it on.&lt;/p&gt;

&lt;p&gt;Paste the &lt;strong&gt;Client ID&lt;/strong&gt; and &lt;strong&gt;Client Secret&lt;/strong&gt; you just created in GCP, and click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhozvd2v0vazot0taphl0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhozvd2v0vazot0taphl0.png" alt="Google client IDs and client secret already configured" width="800" height="1055"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, Go to &lt;strong&gt;Authentication&lt;/strong&gt; -&amp;gt; &lt;strong&gt;URL Configuration&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Site URL: Enter &lt;code&gt;https://MY_DOMAIN_NAME.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Redirect URLs: Click "Add URL" and add these two exact lines so auth works locally and in production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http://localhost:5173/**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://MY_DOMAIN_NAME.com/**&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have the URL whitelisted in my Supabase project as well:&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%2Ff9jdqv8z0z2derp25wls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9jdqv8z0z2derp25wls.png" alt=" " width="800" height="679"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Below is how I'll implement it in my ReactJS project. I'll be using context API to keep the logged in state (feel free to use zustand or any you prefer).&lt;/p&gt;

&lt;p&gt;Install this first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add @supabase/supabase-js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have your:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;VITE_SUPABASE_URL&lt;/span&gt;=&lt;span class="n"&gt;https&lt;/span&gt;://&amp;lt;&lt;span class="n"&gt;YOUR_PROJECT_ID&lt;/span&gt;&amp;gt;.&lt;span class="n"&gt;supabase&lt;/span&gt;.&lt;span class="n"&gt;co&lt;/span&gt;
&lt;span class="n"&gt;VITE_SUPABASE_ANON_KEY&lt;/span&gt;=&lt;span class="n"&gt;your_long_anon_key_here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in your &lt;code&gt;.env&lt;/code&gt; file. &lt;em&gt;If you haven't check the &lt;strong&gt;Extras&lt;/strong&gt; section at the end.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Add a file named &lt;code&gt;supabaseClient.ts&lt;/code&gt; and in it add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createClient&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;@supabase/supabase-js&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;supabaseUrl&lt;/span&gt; &lt;span class="o"&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;YOUR_PUBLIC_SUPABASE_URL&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;supabaseAnonKey&lt;/span&gt; &lt;span class="o"&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;YOUR_SUPABASE_ANON_KEY&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="nx"&gt;supabaseUrl&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;supabaseAnonKey&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Missing Supabase environment variables. Please set YOUR_PUBLIC_SUPABASE_URL and YOUR_SUPABASE_ANON_KEY.&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;supabaseUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;supabaseAnonKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;As I'm using Context API, we'll need to create three files to add a context for Auth:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AuthContext.tsx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AuthProvider.tsx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useAuth.ts&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;code&gt;AuthContext.tsx&lt;/code&gt; add this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;User&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;@supabase/supabase-js&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;createContext&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;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nl"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nl"&gt;photo_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AuthContextType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&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="nl"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&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="nl"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Session&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="nl"&gt;loading&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;signInWithGoogle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AuthContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AuthContextType&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The create a file &lt;code&gt;AuthProvider.tsx&lt;/code&gt; add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;User&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;@supabase/supabase-js&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;useEffect&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;supabase&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;../../lib/supabase&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;AuthContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&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;./AuthContext&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;AuthProvider&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="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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSession&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="nx"&gt;Session&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&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="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProfile&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="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&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;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// If you want to store user data in a supabase table as well, for example I have user_data table table example here in upsertProfile&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upsertProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&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="na"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_metadata&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;full_name&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="na"&gt;photo_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_metadata&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;avatar_url&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="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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;saved&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user_data&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="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;onConflict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&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="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;single&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;setProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;saved&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&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="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSession&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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;user&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;upsertProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setLoading&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="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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onAuthStateChange&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;session&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;setSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;user&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;upsertProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;setProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signInWithGoogle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInWithOAuth&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;redirectTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signOut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signOut&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AuthContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt;
      &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signInWithGoogle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signOut&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;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/AuthContext.Provider&lt;/span&gt;&lt;span class="err"&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;and finally the hook, create a file &lt;code&gt;useAuth.ts&lt;/code&gt; and in it add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useContext&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;AuthContext&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;./AuthContext.tsx&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;useAuth&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;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AuthContext&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="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;useAuth must be used within AuthProvider&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ctx&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;Now you are finally ready to add the changes to app. I have seen people putting the auth context directly in &lt;code&gt;App.tsx&lt;/code&gt;, or there are other mechanisms as well, so it depends on your app specific needs. &lt;/p&gt;

&lt;p&gt;In this article, I'll take a simple approach, we'll wrap the whole &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; in the &lt;code&gt;AuthProvider&lt;/code&gt; so open &lt;code&gt;main.tsx&lt;/code&gt; that has your app's &lt;code&gt;...&amp;lt;StrictMode&amp;gt;&amp;lt;App /&amp;gt;...&lt;/code&gt; and wrap the &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; with the &lt;code&gt;AuthProvider&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//... Your imports&lt;/span&gt;

&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&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="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StrictMode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AuthProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/AuthProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/StrictMode&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your routing will be in the &lt;code&gt;App.tsx&lt;/code&gt; file. As an example say you have two pages &lt;code&gt;Home.tsx&lt;/code&gt; and &lt;code&gt;Profile.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Home.tsx&lt;/code&gt; can be accessed by both authenticated and not authenticated users. &lt;em&gt;Some parts of the pages will be available for public.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Profile.tsx&lt;/code&gt; Only accessible by the Authenticated users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;code&gt;Home.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAuth&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;./AuthProvider&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;//... other imports&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isAuthLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;signInWithGoogle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAuth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;//... other code&lt;/span&gt;

&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex items-center justify-between gap-4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;This&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Welcome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;avatarUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Sign&lt;/span&gt; &lt;span class="nx"&gt;Out&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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="p"&gt;(&lt;/span&gt;
               &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;signInWithGoogle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Login&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;Google&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="p"&gt;)}&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;For &lt;code&gt;Profile.tsx&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useNavigate&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-router-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;//... Other imports&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Profile&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAuth&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;navigate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigate&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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;replace&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;navigate&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;loading&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Profile&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Using the above approach in &lt;code&gt;Profile.tsx&lt;/code&gt;, is a common and safe pattern. The only edge case to know about: There's a brief moment where an unauthenticated user could see the page render before the redirect fires — your if (loading || !user) return null handles that by rendering nothing until auth state is resolved, so nothing sensitive is ever shown.&lt;/p&gt;

&lt;p&gt;The loading guard is the key safety net here. As long as you return null while loading and redirect when !user, there's no flash of protected content.&lt;/p&gt;



&lt;h2&gt;
  
  
  Extras
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Getting Supabase Anon Key and other required variables for &lt;code&gt;.env&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In Supabse project goto &lt;strong&gt;Project Settings&lt;/strong&gt; and then &lt;strong&gt;API Keys&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;default&lt;/code&gt; key under &lt;strong&gt;Publishable key&lt;/strong&gt; That is your new "anon" key, Copy that top one and paste it into your &lt;code&gt;.env&lt;/code&gt; as &lt;code&gt;VITE_SUPABASE_ANON_KEY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(You don't need the "Secret key" anywhere so leave it as is).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To get &lt;code&gt;VITE_SUPABASE_URL&lt;/code&gt; click on &lt;strong&gt;Data API&lt;/strong&gt; under &lt;strong&gt;INTEGRATIONS&lt;/strong&gt; menu:&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%2Fvymh88jup5orniualh1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvymh88jup5orniualh1d.png" alt=" " width="800" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what you'll paste for your &lt;code&gt;VITE_SUPABASE_URL&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>supabase</category>
      <category>google</category>
      <category>authjs</category>
    </item>
    <item>
      <title>TLDR: Host your website on GitHub Pages with custom domain</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Wed, 04 Jun 2025 19:52:36 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/tldr-host-your-website-on-github-pages-with-custom-domain-2knm</link>
      <guid>https://dev.to/thechaudhrysab/tldr-host-your-website-on-github-pages-with-custom-domain-2knm</guid>
      <description>&lt;p&gt;Host your static HTML web pages for free on GitHub Pages. This TLDR guide will show a step-by-step process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Have a public repo with an index.html page in it.&lt;br&gt;
&lt;strong&gt;Step 2:&lt;/strong&gt; Go to &lt;strong&gt;Settings&lt;/strong&gt; tab in the repo, and click on &lt;strong&gt;Pages&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewazcszba6gjn8nblbz2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewazcszba6gjn8nblbz2.png" alt="Settings of repository" width="715" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Under "Build and deployment", under "Source", select Deploy from a branch. Under "Build and deployment", under "Branch", use the branch dropdown menu and select a publishing source.&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%2F490z5tygenzcvrg2jlr6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F490z5tygenzcvrg2jlr6.png" alt=" " width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the site is live, you can see the URL appearing as marked above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; To have your domain instead of the one provided by github, here are all the things you need to do:&lt;/p&gt;

&lt;p&gt;4.1 In your repo, wherever &lt;code&gt;index.html&lt;/code&gt; is, add a file named &lt;code&gt;CNAME&lt;/code&gt; (no file extension) in that file, add your domain name without &lt;code&gt;http&lt;/code&gt;, &lt;code&gt;https&lt;/code&gt; or &lt;code&gt;www.&lt;/code&gt; for example, below is how Google will add their domain:&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%2Fy6x2mui12pn1le7smmnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6x2mui12pn1le7smmnz.png" alt=" " width="198" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4.2 Go to your domain registrar and edit the DNS to add all these 4 A records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;185.199.108.153
185.199.109.153
185.199.110.153
185.199.111.153
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fexve5uzfl5vsefy8eaoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexve5uzfl5vsefy8eaoj.png" alt=" " width="800" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4.3 Add a new CNAME record in your domain DNS. You'll need to add .github.io and &lt;code&gt;www&lt;/code&gt; as name. (Delete any current CNAME record “www” as there must be only one)&lt;/p&gt;

&lt;p&gt;So in step 4, you added 4 A records and 1 CNAME record in your DNS and 1 CNAME file in your repo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Go to your GitHub repo Settings --&amp;gt; Pages and add your domain under &lt;strong&gt;Custom domain&lt;/strong&gt; (i.e. google.com) and click &lt;strong&gt;Save&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It'll take a few seconds to check the DNS. After the DNS check is successful, you can refresh the page, and this will allow you to enforce HTTPS if you'd required.&lt;/p&gt;




&lt;p&gt;This is how you can host your static HTML website on github pages easily.&lt;/p&gt;

</description>
      <category>github</category>
      <category>html</category>
    </item>
    <item>
      <title>I just published React Native + Unity 3D Tutorial on Medium https://ibjects.medium.com/react-native-unity-3d-tutorial-6ef230df81a8?source=friends_link&amp;sk=bc90b0e99d2def38de92c713966cd1de</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Sat, 30 Nov 2024 15:32:10 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/i-just-published-react-native-unity-3d-tutorial-on-medium-2c5k</link>
      <guid>https://dev.to/thechaudhrysab/i-just-published-react-native-unity-3d-tutorial-on-medium-2c5k</guid>
      <description></description>
      <category>reactnative</category>
      <category>unity3d</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>React-Native and Three.js</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Tue, 01 Oct 2024 17:06:38 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/react-native-and-threejs-25p4</link>
      <guid>https://dev.to/thechaudhrysab/react-native-and-threejs-25p4</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A more recent code related to this article is available: &lt;a href="https://github.com/thechaudharysab/ThreeJSRNTestProj" rel="noopener noreferrer"&gt;https://github.com/thechaudharysab/ThreeJSRNTestProj&lt;/a&gt; I haven't updated the code in the article according to that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create a new react-native CLI project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx react-native init Learn3DApp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's preferred that you have real devices to see the output. The 3D model will be able to run on an Android emulator, but there are issues with the iOS simulator. The screenshots you'll see in this iOS project are all on a physical device.&lt;/p&gt;

&lt;p&gt;Let's install all the required packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add three @react-three/fiber
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx install-expo-modules@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It'll ask you a maximum of two questions. Below is how I have answered each:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;install-expo-modules @0.10.2
Ok to proceed? (y) y&lt;/li&gt;
&lt;li&gt;Install the Expo CLI integration? … no&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll manually install the Expo CLI in a later step.&lt;/p&gt;

&lt;p&gt;Below is the screenshot of my &lt;code&gt;install-expo-modules&lt;/code&gt; installation:&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%2Fbeo8rb5285lsanvvz48o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbeo8rb5285lsanvvz48o.png" alt="install-expo-modules" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll need expo-cli installed globally to install the package below. If you don't have expo-cli use &lt;code&gt;npm install -g expo-cli&lt;/code&gt; to install it globally on your system first and then run the command below in your project folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expo install expo-gl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above are the basic packages needed to load a 3D model. But we'll install one more supporting package named &lt;strong&gt;Drei&lt;/strong&gt;, that'll help you with three.js all provided by the same &lt;a href="https://docs.pmnd.rs/" rel="noopener noreferrer"&gt;https://docs.pmnd.rs/&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/pmndrs/drei#readme" rel="noopener noreferrer"&gt;Drei&lt;/a&gt;&lt;/strong&gt; provides us with helpers that make it easy to work with 3D. Without Drei, you’ll need to manually set up and configure many common 3D features (e.g., controls, loaders, environment maps), which can be time-consuming and error-prone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install the Drei package do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @react-three/drei
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After all the installations below is how the dependencies look like in my project now: (&lt;code&gt;expo&lt;/code&gt; was installed automatically by &lt;code&gt;install-expo-modules&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6jk1dwj7pboizfmmt7s6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6jk1dwj7pboizfmmt7s6.png" alt="react-native package dependencies" width="308" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, go to &lt;code&gt;metro.config.js&lt;/code&gt; and add this code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  resolver: {
    sourceExts: ['js', 'jsx', 'json', 'ts', 'tsx', 'cjs', 'mjs'],
    assetExts: ['glb', 'gltf', 'png', 'jpg'],
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fiwi4501st0eartvckoqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwi4501st0eartvckoqc.png" alt="metro.config.js file" width="628" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Android just do &lt;code&gt;cd android &amp;amp;&amp;amp; ./gradlew clean&lt;/code&gt; and for iOS do &lt;code&gt;cd ios &amp;amp;&amp;amp; pod install&lt;/code&gt; at this point.&lt;/p&gt;

&lt;p&gt;We'll now run and test if the expo is linked successfully and only then we'll start working with 3D stuff. As &lt;code&gt;expo-gl&lt;/code&gt; is a very important package to be used when trying to run 3D on mobile devices in a react-native environment.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;App.tsx&lt;/code&gt; and remove everything and just have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import Constants from 'expo-constants';

console.log(Constants.systemFonts);

export default function App() {
  return (
    &amp;lt;&amp;gt;&amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the project &lt;code&gt;yarn start --reset-cache&lt;/code&gt;. The &lt;code&gt;console.log(Constants.systemFonts);&lt;/code&gt; should print this for you in the terminal, ensuring a successful install:&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%2Fa2klazhzvryekoerd9ki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2klazhzvryekoerd9ki.png" alt="Constants.systemFonts" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;make sure you see a blank screen without any errors for both iOS and Android.&lt;/p&gt;




&lt;p&gt;Now that the boring stuff is out of the way, let's start 3D work. You'll need a 3D model that you'll be loading in the app.&lt;/p&gt;

&lt;p&gt;There are many websites where you can find 3D models for free. Just like how images have JPG, PNG, and many different formats, the 3D file format you want to download can be either &lt;code&gt;.gltf&lt;/code&gt; or &lt;code&gt;.glb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I know &lt;a href="https://www.cgtrader.com/" rel="noopener noreferrer"&gt;https://www.cgtrader.com/&lt;/a&gt; which is a nice website to find 3D models in &lt;code&gt;.gltf&lt;/code&gt; or &lt;code&gt;.glb&lt;/code&gt; formats, you can apply filters to download free models.&lt;/p&gt;

&lt;p&gt;I'm going to use &lt;a href="https://poly.pizza/bundle/Farm-Animal-Pack-1kUvRTPLzT" rel="noopener noreferrer"&gt;https://poly.pizza/bundle/Farm-Animal-Pack-1kUvRTPLzT&lt;/a&gt; click on &lt;strong&gt;Download GLTF&lt;/strong&gt; and it'll give you &lt;code&gt;.glb&lt;/code&gt; files of different animals.&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%2F0t9e8lvd0fgc6mv49toq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0t9e8lvd0fgc6mv49toq.png" alt="GLB Format" width="234" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the project create &lt;code&gt;src&lt;/code&gt; folder, and inside create a &lt;code&gt;models&lt;/code&gt; folder. Copy the &lt;code&gt;Horse.glb&lt;/code&gt; or any animal file in the &lt;code&gt;models&lt;/code&gt; folder.&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%2F04sc5m7pi3et5qmr6hdl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04sc5m7pi3et5qmr6hdl.png" alt="Copied the horse GLB file in project" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we need to have a JSX of the GLB file as well. To do that go to &lt;a href="https://gltf.pmnd.rs/" rel="noopener noreferrer"&gt;https://gltf.pmnd.rs/&lt;/a&gt; and drop the GLB file and it'll show you a preview with JSX code as shown below:&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%2Fwgz6ootdytbqz6wm986j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgz6ootdytbqz6wm986j.png" alt="GLB to JSX" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the code and create a new file named &lt;code&gt;Horse.tsx&lt;/code&gt; in the Models folder and paste it there.&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%2Fcwzzfo6uew59y9qyst11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwzzfo6uew59y9qyst11.png" alt="Horse.tsx" width="672" height="758"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To solve the errors we'll do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change &lt;code&gt;from '@react-three/drei'&lt;/code&gt; to &lt;code&gt;from '@react-three/drei/native&lt;/code&gt;'&lt;/li&gt;
&lt;li&gt;Remove &lt;code&gt;props&lt;/code&gt; and &lt;code&gt;{...props}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Remove the last line in code &lt;code&gt;useGLTF.preload('/Horse.glb');&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Give file path with &lt;code&gt;require&lt;/code&gt; in &lt;code&gt;const { nodes, materials, animations } = useGLTF(...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Made the Model function &lt;code&gt;export default&lt;/code&gt; and it's name to &lt;code&gt;Horse&lt;/code&gt; from &lt;code&gt;Model&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The screenshot below is how my full &lt;code&gt;Horse.tsx&lt;/code&gt; is looking now:&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%2Fqjttfet2avfy81npjv5r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjttfet2avfy81npjv5r.png" alt="Horse.tsx after changes" width="638" height="711"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't worry about the &lt;code&gt;nodes, materials, animations&lt;/code&gt; red underline as these are just typescript things asking for specific types.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next, open &lt;code&gt;App.tsx&lt;/code&gt; and add the following code in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Suspense } from 'react';
import { Canvas } from '@react-three/fiber/native';
import { OrbitControls } from '@react-three/drei/native';

import { View } from 'react-native';
import Horse from './src/models/Horse';

const App = () =&amp;gt; {
  const renderHorseCanvas = () =&amp;gt; {
    return (
      &amp;lt;Canvas shadows&amp;gt;
        &amp;lt;directionalLight position={[5, 10, 15]} intensity={1} castShadow /&amp;gt;
        &amp;lt;directionalLight position={[-10, 10, 15]} intensity={1} /&amp;gt;
        &amp;lt;directionalLight position={[10, 10, 15]} intensity={1} /&amp;gt;
        &amp;lt;Suspense fallback={null}&amp;gt;
          &amp;lt;Horse /&amp;gt;
          &amp;lt;mesh
            receiveShadow
            rotation={[-Math.PI / 2, 0, 0]}
            position={[0, -1, 0]}&amp;gt;
            &amp;lt;planeGeometry args={[10, 10]} /&amp;gt;
            &amp;lt;shadowMaterial opacity={0.5} /&amp;gt;
          &amp;lt;/mesh&amp;gt;
        &amp;lt;/Suspense&amp;gt;
        &amp;lt;OrbitControls enableZoom={false} /&amp;gt;
      &amp;lt;/Canvas&amp;gt;
    );
  };

  return &amp;lt;View style={{ flex: 1 }}&amp;gt;{renderHorseCanvas()}&amp;lt;/View&amp;gt;;
};

export default App;

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

&lt;/div&gt;



&lt;p&gt;Re-run the project and you'll see the horse model being rendered.&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%2Fskuttdq2kand2maske0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fskuttdq2kand2maske0a.png" alt="First render of the horse" width="800" height="1644"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It seems like there is a divide between the shadow and the actual horse body. But it's nothing that a minor position repositioning cannot fix. Let's change the &lt;code&gt;renderHorseCanvas&lt;/code&gt; code to the one below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const renderHorseCanvas = () =&amp;gt; {
    return (
      &amp;lt;Canvas shadows&amp;gt;
       //... remaining code
          &amp;lt;Horse position={[0, -1, 0]} /&amp;gt;
          //... remaining code
      &amp;lt;/Canvas&amp;gt;
    );
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fq2yoppsbbslcd9te8rrs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2yoppsbbslcd9te8rrs.png" alt="Position fixed of the render" width="346" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how you render a 3D using three js in your react-native app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus: Animations
&lt;/h3&gt;

&lt;p&gt;The horse we've added is still and doesn't do anything. This &lt;code&gt;glb&lt;/code&gt; file includes animations like Idle, Jump, Run, Walk, etc.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Horse.tsx&lt;/code&gt; we had a line of code &lt;code&gt;const { actions } = useAnimations(animations, group);&lt;/code&gt; which we'll use.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Horse.tsx&lt;/code&gt; before the main &lt;code&gt;return (&lt;/code&gt; add this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//... remaining code
  const { actions, names } = useAnimations(animations, group);
  console.log('animations names: ', names);
  // animations names:  ["Armature|Death", "Armature|Idle", "Armature|Jump", "Armature|Run", "Armature|Walk", "Armature|WalkSlow"]
  useEffect(() =&amp;gt; {
    // Play the "Idle" animation
    const idleAction = actions['Armature|WalkSlow'];
    if (idleAction) {
      idleAction
        .reset()
        .setLoop(LoopRepeat, Infinity) // Set loop mode and infinite repetitions
        .fadeIn(0.5)
        .play();
    }
    return () =&amp;gt; {
      // Stop the "Idle" animation when the component is unmounted
      if (idleAction) idleAction.fadeOut(0.5);
    };
  }, [actions]);
//... remaining code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the full code:&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%2Fkym431bpudd8bgze0wwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkym431bpudd8bgze0wwg.png" alt="Full code of animation" width="800" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see all the available animations of any GLB or GLTF file with the &lt;code&gt;console.log('animations names: ', names);&lt;/code&gt;. I have the player &lt;code&gt;Armature|WalkSlow&lt;/code&gt; animation on &lt;code&gt;LoopRepeat&lt;/code&gt; to give it a cool walking horse feel which you can see below, you can also add a different name from the &lt;strong&gt;animations names&lt;/strong&gt; and see how they look.&lt;/p&gt;

&lt;p&gt;Opening on an Android device I see this cool animation:&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%2F6omgwz188ouaghkp4no9.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%2F6omgwz188ouaghkp4no9.gif" alt="Animation preview" width="346" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Extras:
&lt;/h3&gt;

&lt;p&gt;Here are some things and additional resources that might be of help:&lt;/p&gt;




&lt;p&gt;I was constantly getting this print in the terminal as soon as the 3D model renders:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;LOG  EXGL: gl.pixelStorei() doesn't support this parameter yet!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is okay as it'll not impact anything for production like it'll not crash that's for sure. If your app is crashing there must be some other issue. I found a solution &lt;a href="https://github.com/expo/expo/issues/11063" rel="noopener noreferrer"&gt;https://github.com/expo/expo/issues/11063&lt;/a&gt; I would not say it's ideal but it works.&lt;/p&gt;

&lt;p&gt;The solution states that in &lt;code&gt;App.tsx&lt;/code&gt; or the file where you have the &lt;code&gt;Canvas&lt;/code&gt; from &lt;code&gt;@react-three/fiber&lt;/code&gt; add a prop to it as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      &amp;lt;Canvas
        shadows={true}
        onCreated={state =&amp;gt; {
          const _gl = state.gl.getContext();
          const pixelStorei = _gl.pixelStorei.bind(_gl);
          _gl.pixelStorei = function (...args) {
            const [parameter] = args;
            switch (parameter) {
              case _gl.UNPACK_FLIP_Y_WEBGL:
                return pixelStorei(...args);
            }
          };
        }}&amp;gt;
//... rest of the code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Finqyxo4jq7f6x9tpmsrv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finqyxo4jq7f6x9tpmsrv.png" alt="Full code of gl.pixelStorei log" width="569" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This magic potion will make the log go away.&lt;/p&gt;




&lt;p&gt;I did a POC for these two as well if you're interested in exploring alternatives to the React-Native + ThreeJS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@ibjects/getting-started-with-babylonjs-in-a-react-native-mobile-app-ee1b82d67e03" rel="noopener noreferrer"&gt;React-Native + BabylonJS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@ibjects/react-native-unity-3d-tutorial-6ef230df81a8" rel="noopener noreferrer"&gt;React-Native + Unity3D
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Here is a resource to find 3D models for free: &lt;a href="https://www.cgtrader.com/free-3d-models" rel="noopener noreferrer"&gt;https://www.cgtrader.com/free-3d-models&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Have a project and want me to look at, you can hire me on upwork: &lt;a href="https://www.upwork.com/freelancers/%7E01e4982cf39ced7048" rel="noopener noreferrer"&gt;https://www.upwork.com/freelancers/~01e4982cf39ced7048&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you'd like to support you can do so via &lt;a href="https://buymeacoffee.com/chaudhrytalha" rel="noopener noreferrer"&gt;https://buymeacoffee.com/chaudhrytalha&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also write on medium so you can follow me there too: &lt;a href="https://ibjects.medium.com/" rel="noopener noreferrer"&gt;https://ibjects.medium.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>threejs</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>TLDR; Add adaptive app icon of your android app</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Sat, 10 Aug 2024 16:51:42 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/tldr-add-adaptive-app-icon-of-your-android-app-mcd</link>
      <guid>https://dev.to/thechaudhrysab/tldr-add-adaptive-app-icon-of-your-android-app-mcd</guid>
      <description>&lt;p&gt;Weather you're building using native android (kotlin or java), or react-native and even flutter use this technique to add adaptive app icon for your android app. Adaptive icons will adapt to the device look and feel i.e. if it's a circle, or rounded square on others adaptive icons will adapt.&lt;/p&gt;

&lt;p&gt;Open your android project in Android Studio. Go to &lt;code&gt;/app/res/drawable&lt;/code&gt; folder and right click &lt;strong&gt;New -&amp;gt; Image Asset&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjafprdgd2eaz4efw8ncp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjafprdgd2eaz4efw8ncp.png" alt="o to app/res/drawable folder and right click, then select new and then image asset" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll see an &lt;strong&gt;Asset Studio&lt;/strong&gt; window will open:&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%2Ffpikuwwkvxch1mgglsik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpikuwwkvxch1mgglsik.png" alt="Asset Studio window" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the quick info about the options you have in this window:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Icon type&lt;/strong&gt; depending on the type of app you're building it'll be generating the assets. Like if you're building an android app for the TV then it'll have it's own icon sizes. As I'm creating for mobile app so I'll keep the options selected &lt;strong&gt;Launched Icons (Adaptive and Legacy)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As the name is already written &lt;code&gt;ic_launcher&lt;/code&gt; which is the name of the icon Android Studio has already set by default. &lt;strong&gt;Keep it as it is&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, you have three tabs, &lt;strong&gt;Foreground Layer&lt;/strong&gt;, &lt;strong&gt;Background Layer&lt;/strong&gt; and &lt;strong&gt;Options&lt;/strong&gt;.&lt;br&gt;
As the names suggest we're going to have a background layer which can be a colour or an image and same goes for foreground layer.&lt;br&gt;
We'll keep the &lt;code&gt;Options&lt;/code&gt; as it is, but you can explore it to see what options suits for your use-case.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is the icon that I'll be adding:&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%2Fwuz7uysthenzoto7tu9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwuz7uysthenzoto7tu9j.png" alt="Moonect Logo" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've select the above PNG as foreground layer and adjusted the &lt;strong&gt;Resize&lt;/strong&gt; option to make sure the layer is within the circles in the &lt;code&gt;Preview&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1p44rgweorqki2umujjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1p44rgweorqki2umujjz.png" alt="Asset Studio Foreground Layer" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the background layer I'll be adding white color.&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%2F6qiiycr71f81rrqelxu8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qiiycr71f81rrqelxu8.png" alt="Asset Studio Background Layer" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that press &lt;code&gt;Next&lt;/code&gt; and it'll show you which files will be created, overwritten or removed. As I kept the name same i.e. &lt;code&gt;ic_launcher&lt;/code&gt; so this is going to replace the current default Android app icon, so I'll just press &lt;strong&gt;Finish&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdqv314iim0nere0xvhn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdqv314iim0nere0xvhn.png" alt="Asset Studio Final Review" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's completely safe to add all the files it has created to Git.&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%2F2lhhgovavid7e2w5jxma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lhhgovavid7e2w5jxma.png" alt="Android Studio Git" width="800" height="1041"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For my app icon, there were 33 changes in the git.&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%2F3zyf876npuaj4bit5yxr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zyf876npuaj4bit5yxr.png" alt="Github Preview" width="714" height="1324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clean and run the project and you'll see a pixel perfect logo, adaptive to all android phones.&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>5 Helpful Developer Productivity Tools</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Tue, 16 Jul 2024 02:20:22 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/5-helpful-developer-productivity-tools-168k</link>
      <guid>https://dev.to/thechaudhrysab/5-helpful-developer-productivity-tools-168k</guid>
      <description>&lt;h3&gt;
  
  
  Easy README editor tool
&lt;/h3&gt;

&lt;p&gt;I like to create good README files for the projects I work on, and it can get hectic if you're writing markdown and then previewing it and then fixing any mistakes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://readme.so/" rel="noopener noreferrer"&gt;readme.so&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Build, test, and debug regex
&lt;/h3&gt;

&lt;p&gt;Regex can be a PITA sometimes. Here is a tool I use to build a regex or test regex in code reviews.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://regex101.com/" rel="noopener noreferrer"&gt;regex101&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Create secure tunnels for your local development
&lt;/h3&gt;

&lt;p&gt;Imagine you’re working on a website on your computer and you want to show it to someone else who’s not nearby. Normally, they can’t see it because it’s only on your local machine. Ngrok creates a secure tunnel from your computer to the internet, giving you a temporary web address that anyone can use to access your site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt; &lt;/p&gt;



&lt;h3&gt;
  
  
  Check the cost of adding npm packages
&lt;/h3&gt;

&lt;p&gt;As I am a javascript developer, so adding a new &lt;code&gt;npm&lt;/code&gt; packages in my project comes every now and then. This tools tell you what would be the cost of adding a package in your project is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bundlephobia.com/" rel="noopener noreferrer"&gt;bundlephobia&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Create mock APIs with temporary data
&lt;/h3&gt;

&lt;p&gt;Sometimes you need to create demo data while the backend is still working on the API OR you want to have a mock API in place that return that temporary data as a placeholder. This tool will help you do all of that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mockaroo.com/" rel="noopener noreferrer"&gt;mockaroo&lt;/a&gt; OR &lt;a href="https://designer.mocky.io/" rel="noopener noreferrer"&gt;mocky&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developers</category>
      <category>programming</category>
      <category>productivity</category>
      <category>coding</category>
    </item>
    <item>
      <title>Google SignIn in react-native using firebase auth</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Thu, 13 Jun 2024 19:14:42 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/google-signin-in-react-native-using-firebase-auth-2nop</link>
      <guid>https://dev.to/thechaudhrysab/google-signin-in-react-native-using-firebase-auth-2nop</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;If you're looking for a solution without firebase, I've a medium article for that: &lt;a href="https://medium.com/@ibjects/google-signin-tutorial-for-react-native-81a57fb67b18" rel="noopener noreferrer"&gt;https://medium.com/@ibjects/google-signin-tutorial-for-react-native-81a57fb67b18&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Straight-forward way of implementing a google sign-in in a react native app using firebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Firebase Console
&lt;/h2&gt;

&lt;p&gt;Add Google from the &lt;strong&gt;Additional Providers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffikwv29mgu4dzn8rj7v6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffikwv29mgu4dzn8rj7v6.png" alt="Choose Google as option for auth providers" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note down your &lt;code&gt;Web client ID&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdwqw8xajqrlw7eu9yq14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdwqw8xajqrlw7eu9yq14.png" alt="Not down the web client ID" width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once it's done it should look 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%2Fq6zkp372vd45huh7mhn2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq6zkp372vd45huh7mhn2.png" alt="It will show Google as enabled" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  React-Native
&lt;/h2&gt;

&lt;p&gt;Let's install the required libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @react-native-firebase/app @react-native-firebase/auth
yarn add @react-native-google-signin/google-signin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;For Android&lt;/strong&gt;, clean the project and build once from android studio to avoid any unexpected errors.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;Login.tsx&lt;/code&gt; screen. There are a few things that work together here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checking &lt;code&gt;onAuthStatusChanged&lt;/code&gt; using &lt;code&gt;auth&lt;/code&gt; from &lt;code&gt;@react-native-firebase/auth&lt;/code&gt; to check the current status of the user authentication.&lt;/li&gt;
&lt;li&gt;Configure &lt;code&gt;GoogleSignin&lt;/code&gt; using &lt;code&gt;GoogleSignin.configure&lt;/code&gt; where we'll provide &lt;code&gt;webClientId&lt;/code&gt; which you should have at the time of the firebase console side configuration.&lt;/li&gt;
&lt;li&gt;Handle &lt;code&gt;onGoogleButtonPress&lt;/code&gt; and &lt;code&gt;renderGoogleSigninButton&lt;/code&gt; as we'll be creating our own button to trigger a &lt;code&gt;GoogleSignin&lt;/code&gt; request.&lt;/li&gt;
&lt;li&gt;Once a user is logged in then rendering a &lt;code&gt;renderLogoutView&lt;/code&gt; and &lt;code&gt;return&lt;/code&gt; main components.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is the code for &lt;code&gt;Login.tsx&lt;/code&gt; broken down as per the number list above:&lt;br&gt;
&lt;/p&gt;

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

import auth, { FirebaseAuthTypes } from '@react-native-firebase/auth';

// other imports and code

    const [user, setUser] = React.useState&amp;lt;FirebaseAuthTypes.User | null&amp;gt;();

    function onAuthStatusChanged(user: FirebaseAuthTypes.User | null) {
        setUser(user);
    }

    useEffect(() =&amp;gt; {
        const subscriber = auth().onAuthStateChanged(onAuthStatusChanged);
        return subscriber; // unsubscribe on unmount
    }, []);

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

&lt;/div&gt;





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

import { GoogleSignin } from "@react-native-google-signin/google-signin";

//... other imports and everything in 1.

    GoogleSignin.configure({
        webClientId: 'ADD_YOUR_KEY_HERE',
        offlineAccess: true,
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If required, look for &lt;code&gt;Web client ID&lt;/code&gt; reference above to know where to get it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 3a. onGoogleButtonPress

async function onGoogleButtonPress(user: FirebaseAuthTypes.User | null) {
  if (user) {
    // user is already logged in so no need to do anything
    return null;
  }

  try {
    // Check if your device supports Google Play
    await GoogleSignin.hasPlayServices({
      showPlayServicesUpdateDialog: true,
    });

    const { type, data } = await GoogleSignin.signIn();

    /**
     * @type can be "cancelled" in which can @data will be 'null'; 
     * If @type is "success" then @data will be:
     * user: {
            id: string;
            name: string | null;
            email: string;
            photo: string | null;
            familyName: string | null;
            givenName: string | null;
        };
        scopes: string[];
        idToken: string | null;
        serverAuthCode: string | null;
     */

    if (type === 'success') {
      // const { id, name, email, photo, familyName, givenName } = data.user;

      // Create a Google credential with the token
      const googleCredential = auth.GoogleAuthProvider.credential(data.idToken);

      // Sign-in the user with the credential
      return auth().signInWithCredential(googleCredential);
    } else if (type === 'cancelled') {
      // When the user cancels the flow for any operation that requires user interaction.
      return; // do nothing
    }
  } catch (error) {
    console.error('ERROR: ', error);
    return error;
  }
}

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

&lt;/div&gt;



&lt;p&gt;With a simple &lt;code&gt;GoogleSignin.signIn()&lt;/code&gt; it'll automatically handles everything.&lt;/p&gt;

&lt;p&gt;Now we'll implement the google sign in button component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// 3b. renderGoogleSigninButton

import {
    GoogleSignin, // already imported before
    isErrorWithCode,
    statusCodes,
} from "@react-native-google-signin/google-signin";

//... other code

const renderGoogleSigninButton = () =&amp;gt; {

        const buttonTitle = user ? `Signed in as: ${user.displayName}` : 'Continue with Google'

        return (
            &amp;lt;Pressable style={styles.buttonContainer} onPress={() =&amp;gt; onGoogleButtonPress().then((value: FirebaseAuthTypes.UserCredential | null) =&amp;gt; {
                    // The onGoogleButtonPress will update the setUser state, so no action needed here
                if (value) {
                    console.log('value.additionalInnfo: ', value.additionalUserInfo);
                    console.log('value.user: ', value.user);
                }
            }).catch((error) =&amp;gt; {
                if (isErrorWithCode(error)) {
                    switch (error.code) {
                        case statusCodes.SIGN_IN_CANCELLED:
                            // user cancelled the login flow
                            Alert.alert("User cancelled the login flow. Please try again.");
                            break;
                        case statusCodes.IN_PROGRESS:
                            // operation (eg. sign in) already in progress
                            Alert.alert("Sign In already in progress. Please wait.");
                            break;
                        case statusCodes.PLAY_SERVICES_NOT_AVAILABLE:
                            // play services not available or outdated
                            Alert.alert("Play services not available or outdated. Please update your play services.");
                            break;
                        default:
                            // some other error happened
                            Alert.alert("An unknown error occurred. Please try again later.");
                    }
                } else {
                    // an error that's not related to google sign in occurred
                    Alert.alert("An error that's not related to google sign in occurred. Please try again later.");
                }
            })}&amp;gt;
                &amp;lt;Text&amp;gt;{buttonTitle}&amp;lt;/Text&amp;gt;
            &amp;lt;/Pressable&amp;gt;
        )
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The step 4, let's divide it into smaller parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement &lt;code&gt;signOut&lt;/code&gt; using &lt;code&gt;auth&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;implement a &lt;code&gt;renderLogoutView&lt;/code&gt; to implement logout.&lt;/li&gt;
&lt;li&gt;Main screen &lt;code&gt;Components&lt;/code&gt; that include login and logout buttons
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 4a.Implement `signOut` using `auth`
// src/api/FirebaseAuthUtils.ts
import auth from '@react-native-firebase/auth';

export function userLogout(): Promise&amp;lt;string&amp;gt; {
    return new Promise((resolve, reject) =&amp;gt; {
        auth()
            .signOut()
            .then(() =&amp;gt; {
                resolve('Logout Successful');
            })
            .catch(error =&amp;gt; {
                reject({
                    title: 'Error',
                    desc: error.message,
                });
            });
    });
}

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

&lt;/div&gt;



&lt;p&gt;Created a new file in &lt;code&gt;src/api/FirebaseAuthUtils.ts&lt;/code&gt; and added a logout function.&lt;/p&gt;

&lt;p&gt;Everything below is in &lt;code&gt;Login.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 4b. Implement a `renderLogoutView` to implement logout.

import { userLogout } from "../api/FirebaseAuthUtils";
//... other imports

    const renderLogoutView = () =&amp;gt; {
        if (user) {
            return (
                &amp;lt;Pressable onPress={() =&amp;gt; {
                    userLogout().then((message) =&amp;gt; {
                        Alert.alert(message);
                    }).catch(error =&amp;gt; {
                        Alert.alert(error.title, error.desc);
                    });
                }}&amp;gt;
                    &amp;lt;Text style={styles.buttonTitle}&amp;gt;Logout&amp;lt;/Text&amp;gt;
                &amp;lt;/Pressable&amp;gt;
            )
        }
    }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 4c. Main screen `Components` that include login and logout buttons

return (
        &amp;lt;ScrollView&amp;gt;
                {!user &amp;amp;&amp;amp; &amp;lt;&amp;gt;
                    &amp;lt;Text style={styles.descriptionText}&amp;gt;
                        New or returning user, press{'\n'}
                        &amp;lt;Text style={styles.boldText}&amp;gt;Continue with Google
                        &amp;lt;/Text&amp;gt; to continue
                    &amp;lt;/Text&amp;gt;
                    {renderGoogleSigninButton()}
                &amp;lt;/&amp;gt;}
                {renderLogoutView()}
        &amp;lt;/ScrollView&amp;gt;
)

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

&lt;/div&gt;



&lt;p&gt;That's all the code that is needed. Next let's test it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;I tested on simulator and device, it works.&lt;/p&gt;

&lt;p&gt;I am not logged in, so it shows the Login button:&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%2F7op71vzkdhwom2xjf1wt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7op71vzkdhwom2xjf1wt.png" alt="I am not logged in" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am logged in, so it shows the Logout button:&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%2Fqeubkx9puxgmpyx8mkeu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqeubkx9puxgmpyx8mkeu.png" alt="I am logged in" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It'll take user to Google Sign In page for verification.&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%2Fgmei0gnjxuv9d57riwo6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmei0gnjxuv9d57riwo6.png" alt="Takes me to google sign in page" width="800" height="1644"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Logout test and it works as expected.&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%2F26r2rp69on7369azurrt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26r2rp69on7369azurrt.png" alt="Logout Test" width="800" height="860"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Errors
&lt;/h3&gt;

&lt;p&gt;If you're getting this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; LOG  ERROR:  [Error: DEVELOPER_ERROR]
 LOG  ERROR:  10 DEVELOPER_ERROR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the &lt;strong&gt;SHA-1&lt;/strong&gt; and &lt;strong&gt;SHA-256&lt;/strong&gt;. If you only have &lt;code&gt;debug&lt;/code&gt; build then just add for that otherwise add total 4; 2 for &lt;code&gt;debug&lt;/code&gt; and 2 for &lt;code&gt;release&lt;/code&gt;:&lt;/p&gt;

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

&lt;p&gt;Below is the command you can run to get all the available SHA fingerprints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd android &amp;amp;&amp;amp; ./gradlew signingReport
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scroll down to find &lt;code&gt;&amp;gt; Task :app:signingReport&lt;/code&gt;. Here you can find all the available SHA fingerprints. I only have &lt;code&gt;debug&lt;/code&gt; so for me &lt;code&gt;release&lt;/code&gt; and &lt;code&gt;debug&lt;/code&gt; keys are the same, so in the above screenshot you see only two SHA fingerprints.&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%2Fz79qa2te2g4pqm3vuusz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz79qa2te2g4pqm3vuusz.png" alt="how to find SHA-1 and SHA-256 of android app" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This solves the &lt;code&gt;10 DEVELOPER_ERROR&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;If you're getting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Error: SIGN_IN_REQUIRED]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure that your &lt;code&gt;signOut&lt;/code&gt; is properly configured. Try deleting the app and installing again.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>firebase</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>TLDR; Suspense in react-query</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Sat, 01 Jun 2024 19:48:41 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/tldr-suspense-in-react-query-5f4c</link>
      <guid>https://dev.to/thechaudhrysab/tldr-suspense-in-react-query-5f4c</guid>
      <description>&lt;p&gt;In React Query, Suspense is a way to handle loading states for asynchronous data fetching. It essentially lets your components "pause" until the data they need is available. For example if your data is bing fetched react loads a temporary component instead until the data becomes available.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Suspense requires React 18 or later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Without Suspense:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You typically use a state variable (e.g., &lt;code&gt;isLoading&lt;/code&gt;) to indicate if data is being fetched.&lt;/li&gt;
&lt;li&gt;You conditionally render loading indicators while the data is being fetched.&lt;/li&gt;
&lt;li&gt;This can lead to a lot of conditional logic and potentially messy code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  With Suspense:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Wrap your component in a Suspense boundary: This signals to React that your component might need to wait for data.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;useQuery&lt;/code&gt;: This hook fetches data asynchronously and provides information about the data fetching state (&lt;em&gt;loading&lt;/em&gt;, &lt;em&gt;error&lt;/em&gt;, &lt;em&gt;data&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;React Query throws a promise: When data is being fetched, useQuery internally throws a promise. This "&lt;strong&gt;suspends&lt;/strong&gt;" rendering.&lt;/li&gt;
&lt;li&gt;Suspense boundary catches the promise: The Suspense boundary catches the promise thrown by &lt;code&gt;useQuery&lt;/code&gt; and renders a fallback component (e.g., a loading indicator) while the data is being fetched.&lt;/li&gt;
&lt;li&gt;Data arrives and rendering resumes: Once the promise resolves with the data, React continues rendering your component with the actual data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Benefits of Suspense:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Cleaner code: You avoid repetitive conditional logic for loading states.&lt;/li&gt;
&lt;li&gt;Improved user experience: Users see a clear loading indicator while data is being fetched.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  React Query and Suspense work together seamlessly:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;React Query manages data fetching and provides the "suspending" behavior.&lt;/li&gt;
&lt;li&gt;You can use Suspense boundaries to handle loading states in a cleaner way.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Code example:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://tanstack.com/query/v5/docs/framework/react/examples/suspense" rel="noopener noreferrer"&gt;https://tanstack.com/query/v5/docs/framework/react/examples/suspense&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>react</category>
      <category>reactnative</category>
      <category>reactquery</category>
    </item>
    <item>
      <title>TLDR; gcTime &amp; staleTime in react-query</title>
      <dc:creator>Chaudhry Talha 🇵🇸</dc:creator>
      <pubDate>Wed, 22 May 2024 17:41:23 +0000</pubDate>
      <link>https://dev.to/thechaudhrysab/simple-understanding-of-gctime-staletime-in-react-query-35be</link>
      <guid>https://dev.to/thechaudhrysab/simple-understanding-of-gctime-staletime-in-react-query-35be</guid>
      <description>&lt;p&gt;Here is a simple understanding of two very important concepts in react-query caching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites: Will be good if you have a very basic idea of what react-query is..&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In React Query v5, the &lt;code&gt;cacheTime&lt;/code&gt; option in React Query has been renamed to &lt;code&gt;gcTime&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;gcTime&lt;/code&gt; and &lt;code&gt;staleTime&lt;/code&gt; options in React Query serve different purposes in managing and controlling the cached data lifecycle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLDR;&lt;/strong&gt; In summary, &lt;code&gt;gcTime&lt;/code&gt; manages how long data can remain in the cache after it becomes unused before being garbage collected to free up memory, while &lt;code&gt;staleTime&lt;/code&gt; determines how long data can be considered fresh before triggering a refetch to ensure data currency and accuracy. Both options play crucial roles in optimizing data caching, memory management, and data freshness in React Query applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  gcTime:
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;gcTime&lt;/code&gt; (Garbage Collect Time) is used to determine how long data will remain in the cache after a query becomes unused. &lt;/p&gt;

&lt;p&gt;By setting &lt;code&gt;gcTime&lt;/code&gt; to a specific duration (in milliseconds), you control how long data stays in the cache after it is no longer actively used. Once the &lt;code&gt;gcTime&lt;/code&gt; duration has passed, the data is considered eligible for garbage collection, effectively managing the cache size and memory consumption.&lt;/p&gt;

&lt;p&gt;Once the specified &lt;code&gt;gcTime&lt;/code&gt; duration elapses, the data is marked for garbage collection to prevent the cache from growing indefinitely. &lt;code&gt;gcTime&lt;/code&gt; focuses on managing memory and ensuring that outdated or unused data is eventually removed from the cache to maintain optimal performance and memory usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  staleTime:
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;staleTime&lt;/code&gt; is used to specify the duration for which data is considered fresh before it becomes stale and triggers a refetch. When a query result is accessed, React Query checks if the data is stale based on the &lt;code&gt;staleTime&lt;/code&gt; value. &lt;/p&gt;

&lt;p&gt;If the data is stale (i.e., the specified time has passed since the data was fetched), React Query initiates a background refetch to update the data (&lt;em&gt;isFetching can be used to detect when the background refresh&lt;/em&gt;). &lt;code&gt;staleTime&lt;/code&gt; is primarily used to control how often React Query should automatically refetch data to ensure it remains up to date. By default, if no staleTime is provided (or set to 0), the query will immediately refetch when it mounts. &lt;/p&gt;

&lt;p&gt;If you provide a staleTime value (in milliseconds), the data will be considered fresh for that duration before a refetch is triggered. If you also want to handle scenarios where the initialData might not be totally fresh, you can use the initialDataUpdatedAt option. This option allows you to pass a JS timestamp indicating when the initialData was last updated. This allows React Query to make a decision on whether the data needs to be refetched based on both the staleTime and the timestamp of when the initialData was last updated.&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>reactquery</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
