<?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: Irwan Phan</title>
    <description>The latest articles on DEV Community by Irwan Phan (@irwanphan).</description>
    <link>https://dev.to/irwanphan</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F137488%2Faf41ff4d-ad06-4a37-9489-6780392f2b62.jpeg</url>
      <title>DEV Community: Irwan Phan</title>
      <link>https://dev.to/irwanphan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/irwanphan"/>
    <language>en</language>
    <item>
      <title>Voice News Summary - AI-Powered News Summaries Read Aloud in Seconds with Redis</title>
      <dc:creator>Irwan Phan</dc:creator>
      <pubDate>Sat, 02 Aug 2025 07:46:27 +0000</pubDate>
      <link>https://dev.to/irwanphan/voice-news-summary-ai-powered-news-summaries-read-aloud-in-seconds-with-redis-1lhi</link>
      <guid>https://dev.to/irwanphan/voice-news-summary-ai-powered-news-summaries-read-aloud-in-seconds-with-redis-1lhi</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/redis-2025-07-23"&gt;Redis AI Challenge&lt;/a&gt;: Beyond the Cache&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Voice News Summary solves a common problem: information overload. Reading through dozens of articles every day can be time-consuming, and not everyone has time to skim long news posts. This app lets users type any topic, get an AI-generated summary of the latest news, and listen to it immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AI-Generated Summaries: Uses OpenAI GPT to produce concise, high-quality summaries.&lt;/li&gt;
&lt;li&gt;Text-to-Speech Output: Converts summaries to natural-sounding voice with ElevenLabs TTS.&lt;/li&gt;
&lt;li&gt;Redis Caching: Speeds up subsequent requests by storing summaries and audio URLs in Redis.&lt;/li&gt;
&lt;li&gt;Serverless Deployment: Built on Next.js and deployed on Vercel for fast, scalable delivery.&lt;/li&gt;
&lt;li&gt;Clean UI: Built with TailwindCSS for a minimal and responsive design.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Frontend: React 19 with Vite, TailwindCSS&lt;/li&gt;
&lt;li&gt;AI APIs: Google Generative AI (for summarization)&lt;/li&gt;
&lt;li&gt;Database &amp;amp; Cache: Redis using ioredis for connection and caching&lt;/li&gt;
&lt;li&gt;Deployment: Vercel (for frontend) + Redis Cloud (for caching &amp;amp; vector storage)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live Demo&lt;/strong&gt;: &lt;a href="https://voice-news-summary.vercel.app" rel="noopener noreferrer"&gt;https://voice-news-summary.vercel.app&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Type any topic, get AI-generated summaries, and listen to them instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Redis 8
&lt;/h2&gt;

&lt;p&gt;Redis powers the core experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caching Summaries: Once an article summary is generated and converted to audio, it’s stored in Redis for fast future retrieval.&lt;/li&gt;
&lt;li&gt;Redis Vector Sets: Planned future upgrade for semantic search, allowing related news retrieval beyond exact keyword matching.&lt;/li&gt;
&lt;li&gt;Real-time Speed: With Redis Cloud, the app responds in milliseconds, even when handling multiple concurrent requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why It Matters
&lt;/h2&gt;

&lt;p&gt;In a world of &lt;strong&gt;information overload&lt;/strong&gt;, Voice News Summary makes news consumption:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster: Get to the core of a story in seconds.&lt;/li&gt;
&lt;li&gt;Accessible: Listen to summaries instead of reading long text.&lt;/li&gt;
&lt;li&gt;Scalable: Uses AI + Redis to deliver near-instant response times.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What’s Next
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vector Search&lt;/strong&gt;: Use Redis Vector Sets for semantic search and related topic discovery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personalized Feeds&lt;/strong&gt;: Customize summaries and voices based on user preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile PWA&lt;/strong&gt;: Turn this into a progressive web app for on-the-go usage.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Built for the Redis AI Challenge to showcase how Redis can power the next generation of AI-driven, real-time applications.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>redischallenge</category>
      <category>devchallenge</category>
      <category>database</category>
      <category>ai</category>
    </item>
    <item>
      <title>Getting Started With Git? A Complete Git Beginner.</title>
      <dc:creator>Irwan Phan</dc:creator>
      <pubDate>Wed, 15 Mar 2023 09:16:29 +0000</pubDate>
      <link>https://dev.to/irwanphan/getting-started-with-git-a-complete-git-beginner-5cfe</link>
      <guid>https://dev.to/irwanphan/getting-started-with-git-a-complete-git-beginner-5cfe</guid>
      <description>&lt;p&gt;I try to recall my first time using git. I was not a tech-guy back then, not even close. Pencil, Pen, and Photoshop was my daily tools back then. &lt;/p&gt;

&lt;p&gt;Later I jumped into web development. When my peer told me about collaboration using git, it overwhelmed me with command-line-stuff. I thought it was a really complicated stuff. But my peer just gave me some simple commands for daily use. And I only use those some-simple lines until now, except sometimes-unexpected things happened.&lt;/p&gt;

&lt;p&gt;I am writing these down, since I had to share how to use git to my class. And I just gonna &lt;strong&gt;skip&lt;/strong&gt; the complicated parts. Hope it helps&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Git, If It's Not Installed Yet
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gHgD1a0Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/33zwa9kth7xu7nt8ynzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gHgD1a0Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/33zwa9kth7xu7nt8ynzc.png" alt="Site to Download Git" width="880" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Download the installer from &lt;a href="https://git-scm.com/download/win"&gt;https://git-scm.com/download/win&lt;/a&gt;, ran the installer, and if you don't understand anything the provided options presented, just go with the default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Git
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_tUiUApU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kglfu8hocxjrs73q4y2n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_tUiUApU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kglfu8hocxjrs73q4y2n.png" alt="Terminal in VSCode" width="880" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Git commands can be directly used from VSCode terminal, you can open the terminal by pressing &lt;strong&gt;Ctrl&lt;/strong&gt; + &lt;strong&gt;Shift&lt;/strong&gt; + &lt;strong&gt;`&lt;/strong&gt;. Or you can open it from the top menu &lt;strong&gt;Terminal&lt;/strong&gt;, then choose &lt;strong&gt;New Terminal&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  If It Is An Existing Repository
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Clone The Repo
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LlcCro6s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rf2lixpmz7f0r20hvwv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LlcCro6s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rf2lixpmz7f0r20hvwv.png" alt="Github Repository" width="880" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If-it is an existing Repository, go to the repository on Github, click the &lt;strong&gt;"Code"&lt;/strong&gt; button, and copy the git url (you can just click the right side button). then go back to the terminal and type &lt;strong&gt;git clone&lt;/strong&gt; command like this. (using the developer-roadmap repo as example)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git clone https://github.com/kamranahmedse/developer-roadmap.git&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Config - One time only
&lt;/h4&gt;

&lt;p&gt;This command actually write the config file inside the hidden .git folder. We'll skip it, just remember that you can always re-config using this command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git config user.email "tapas@someemail.com"&lt;br&gt;
git config user.name "Irwan Phan"&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Add and Commit Changes
&lt;/h4&gt;

&lt;p&gt;To add the files changed to staging, we use the &lt;strong&gt;git add&lt;/strong&gt; command follow by file name or directory/folder name. But we can also just add all the changed files by using . like below.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git add .&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The next thing to do after added the changes to staging area is to commit it using &lt;strong&gt;git commit&lt;/strong&gt; command, and remember to always makes the commit title as clear as possible.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git commit -m "change the x part with x2y"&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Push To Repo (Remote Repository)
&lt;/h4&gt;

&lt;p&gt;Push the committed changes to the remote repo by using &lt;strong&gt;git push&lt;/strong&gt; command follow by &lt;strong&gt;remote&lt;/strong&gt; and branch name, e.g &lt;strong&gt;main&lt;/strong&gt;. If it's a cloned repository, you'll only need to type &lt;strong&gt;git push&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git push&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  If It Is A New Repository
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Initiate A Repo
&lt;/h4&gt;

&lt;p&gt;To create a new repository, we can use the &lt;strong&gt;git init&lt;/strong&gt; command followed by repository name, or just &lt;strong&gt;git init&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git init repo-name&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Config
&lt;/h4&gt;

&lt;p&gt;Use &lt;strong&gt;git config&lt;/strong&gt; for user name and email used in your Github like mentioned in step #2 above.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git config user.email "tapas@someemail.com"&lt;br&gt;
git config user.name "Irwan Phan"&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Add And Commit Changes
&lt;/h4&gt;

&lt;p&gt;Use &lt;strong&gt;git add&lt;/strong&gt; to add to staging and &lt;strong&gt;git commit&lt;/strong&gt; to commit the changes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git add .&lt;br&gt;
git commit -m "change the x part with x2y"&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Push To Repo (Remote Repository)
&lt;/h4&gt;

&lt;p&gt;To push to a new remote repository use &lt;strong&gt;git push_ command followed by __-u&lt;/strong&gt;, &lt;strong&gt;remote&lt;/strong&gt;, and branch name.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git push -u remote main&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapped
&lt;/h3&gt;

&lt;p&gt;I hope this note could be of help for anyone. I tried to make it as simple as possible. For more information on how to use git, you can visit here &lt;a href="https://training.github.com/downloads/github-git-cheat-sheet/"&gt;https://training.github.com/downloads/github-git-cheat-sheet/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>howto</category>
      <category>windows</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Implement Sign in with Google using Supabase Auth in NextJS</title>
      <dc:creator>Irwan Phan</dc:creator>
      <pubDate>Sun, 26 Feb 2023 08:32:07 +0000</pubDate>
      <link>https://dev.to/irwanphan/implement-sign-in-with-google-using-supabase-auth-in-nextjs-1jj1</link>
      <guid>https://dev.to/irwanphan/implement-sign-in-with-google-using-supabase-auth-in-nextjs-1jj1</guid>
      <description>&lt;p&gt;I'm writing this as my personal documentation also, because I was having a hard time when I tried re-implementing this in another project. Feels free to give me advice for better way to implement this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get Your Google Credential
&lt;/h3&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%2Fezg2uj5xk8i7vdybhpww.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%2Fezg2uj5xk8i7vdybhpww.png" alt="Get Google Credential" width="800" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First of all, sign in to cloud.google.com. &lt;/li&gt;
&lt;li&gt;Create or select a project&lt;/li&gt;
&lt;li&gt;Go to APIs &amp;amp; Services, Credentials&lt;/li&gt;
&lt;li&gt;Create Credentials, and pick OAuth client ID&lt;/li&gt;
&lt;li&gt;Copy the CLIENT_ID and CLIENT_SECRET to your local .env or note&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enter Google Credentials On Supabase
&lt;/h3&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%2Fxhb93e2r9mcx6femnj1i.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%2Fxhb93e2r9mcx6femnj1i.png" alt="Google Auth Provider in Supabase" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to your Supabase project, on the left menu pick Authentication&lt;/li&gt;
&lt;li&gt;On menu Providers, look for Google, then enable it&lt;/li&gt;
&lt;li&gt;Paste Google's CLIENT_ID and CLIENT_SECRET then hit save&lt;/li&gt;
&lt;li&gt;Copy the redirect URL and paste to cloud.google.com project, in your previous Credentials, paste to Authorized redirect URIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Local ENV
&lt;/h3&gt;

&lt;p&gt;Go to your Supabase Project, to Project Settings, API&lt;br&gt;
copy your Project URL to local ENV and name it SUPABASE_URL&lt;br&gt;
copy your Anon Public Key in Project API Keys to local ENV and name it SUPABASE_ANON_KEY&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a Sign In module
&lt;/h3&gt;

&lt;p&gt;First, install Supabase Client, using npm or yarn&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;supabase&lt;/span&gt;&lt;span class="sr"&gt;/supabase-j&lt;/span&gt;&lt;span class="err"&gt;s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then connect to Supabase, and make sure the URL is available&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="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="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="nx"&gt;process&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;SUPABASE_URL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&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="nx"&gt;process&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;SUPABASE_ANON_KEY&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&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="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="s1"&gt;Supabase URL not found.&lt;/span&gt;&lt;span class="dl"&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;supabaseAnonKey&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="s1"&gt;Supabase Anon key not found.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;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;I create a connections folder and create a signIn.ts file inside, for first test run, I do not use any options on the function.&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="c1"&gt;// ./connections/signIn.ts&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;./supabase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&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="kd"&gt;const&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="nx"&gt;error&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="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="s1"&gt;google&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// options: {&lt;/span&gt;
        &lt;span class="c1"&gt;//     // redirectTo: getURL() // function to get your URL&lt;/span&gt;
        &lt;span class="c1"&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;then create the signOut.ts&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="c1"&gt;// ./connections/signOut.ts&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;./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;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&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="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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can apply the signInWithGoogle() and the signOut() to your preferable trigger.&lt;br&gt;
here's an example, I am using Chakra-UI, you so the theming with Button was preset in theme and there's the Box element, with the react icon &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%2Fku0xq96v6maq6xbkcbzg.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%2Fku0xq96v6maq6xbkcbzg.png" alt="Login with Google Button" width="615" height="160"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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="nf"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Redirecting...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Box&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;FcGoogle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;mr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;fontSize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;Logi&lt;/span&gt;&lt;span class="err"&gt;n
&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;/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%2F6408795xx6b2z0q5exht.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%2F6408795xx6b2z0q5exht.png" alt="Authenticated Example" width="481" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I created a component to replace the button after checking the authentication that shown like above.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>howto</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
