<?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: Majd Hemud</title>
    <description>The latest articles on DEV Community by Majd Hemud (@m3cv1no).</description>
    <link>https://dev.to/m3cv1no</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%2F886038%2Ff4f7db3f-af63-4016-a1e9-b31ccdaf5a20.JPEG</url>
      <title>DEV Community: Majd Hemud</title>
      <link>https://dev.to/m3cv1no</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/m3cv1no"/>
    <language>en</language>
    <item>
      <title>useActionState hook in react 19</title>
      <dc:creator>Majd Hemud</dc:creator>
      <pubDate>Sat, 27 Jul 2024 19:27:27 +0000</pubDate>
      <link>https://dev.to/m3cv1no/useactionstate-hook-in-react-19-597f</link>
      <guid>https://dev.to/m3cv1no/useactionstate-hook-in-react-19-597f</guid>
      <description>&lt;p&gt;React 19 is finally here! Bringing new features and APIs to the frontend world and for all React lovers. To create smoother, faster, and more efficient React apps.&lt;/p&gt;

&lt;p&gt;In this Article we will talk about &lt;code&gt;useActionState&lt;/code&gt; hook in React 19 😁&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;useActionState&lt;/code&gt; hook is currently only available in React’s Canary and experimental channels. Learn more about &lt;a href="https://react.dev/community/versioning-policy#all-release-channels" rel="noopener noreferrer"&gt;release channels here&lt;/a&gt;. In addition, you need to use a framework that supports &lt;a href="https://react.dev/reference/rsc/use-client" rel="noopener noreferrer"&gt;React Server Components to get the full benefit&lt;/a&gt; of &lt;code&gt;useActionState&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The useActionState hook
&lt;/h3&gt;

&lt;p&gt;This is a new React hook that helps us update state based on the result of a form action.&lt;/p&gt;

&lt;p&gt;In addition, the &lt;code&gt;useActionState&lt;/code&gt; hook offers benefits such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Simplified state management:&lt;/strong&gt; Automatically updates state based on action results, and reducing boilerplate code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced user experience:&lt;/strong&gt; Provides loading indicators and error handling for smoother interactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved performance:&lt;/strong&gt; Optimizes state updates and works seamlessly with React Server Components.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useActionState } from 'react';

async function updateName(name) {
    await new Promise((resolve) =&amp;gt; setTimeout(resolve, 4000));
    return name;
}

export default function UpdateNameForm() {
    const [name, updateNameAction, isPending] = useActionState(
        async (previousName, formData) =&amp;gt; {
            const newName = await updateName(formData.get('name'));
            return result;
        },
        '',
    );
    return (
        &amp;lt;form action={updateNameAction}&amp;gt;
            Current Name is {name}
            &amp;lt;input name='name' /&amp;gt;
            &amp;lt;button type='submit' disabled={isPending}&amp;gt;
                {isPending ? 'Updating...' : 'Update'}
            &amp;lt;/button&amp;gt;
        &amp;lt;/form&amp;gt;
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In the example above:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First we imported the &lt;code&gt;useActionState&lt;/code&gt; hook from the React library.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We defined an asynchronous function called &lt;code&gt;updateName&lt;/code&gt; to update the name. It takes a name parameter. Inside the function we added a promise to simulate a delay of 4 seconds before resolving the promise. After that it returns the new name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As well we defined a functional component named &lt;code&gt;UpdateNameForm&lt;/code&gt;. Inside the component we used the useActionState hook to manage the component's state.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;useActionState&lt;/code&gt; hook returns an array with three values:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt;: The current name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;updateNameAction&lt;/code&gt;: A function to trigger the form action and the subsequent state update.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;isPending&lt;/code&gt;: Is a boolean flag indicating whether the action is in progress.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;useActionState&lt;/code&gt; hook takes three arguments:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fn&lt;/code&gt;: An asynchronous function that handles the form submission logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;initialState&lt;/code&gt;: The value you want the state to be initially. It can be any serializable value. This argument is ignored after the action is first invoked.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;optional&lt;/strong&gt; &lt;code&gt;permalink&lt;/code&gt;: Is a string representing a unique URL associated with the form. It's primarily used in progressive enhancement scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example with &lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt;. If the JavaScript bundle hasn't loaded yet when a user submits the form, React will redirect the user to the specified permalink URL instead of the current page.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;So for the first parameter in the &lt;code&gt;useActionState&lt;/code&gt; hook. We added an asynchronous function and it takes two parameters:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;previousName&lt;/code&gt;: It's the previous state for the name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;formData&lt;/code&gt;: Which includes the submitted data from the form.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;And after we added the asynchronous function as a first parameter in the &lt;code&gt;useActionState&lt;/code&gt; hook. Within this function we get the new name from the &lt;code&gt;formData&lt;/code&gt; and update the name through the &lt;code&gt;updateName&lt;/code&gt; function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the second parameter we added an empty string to be the &lt;code&gt;initialState&lt;/code&gt; for the name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And finally it returns the new name to update the state for the name.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📝 Things to Keep in Mind
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Experimental Feature:&lt;/strong&gt; useActionState is currently an experimental feature and its behavior might change in future React versions. Use it with caution and be prepared for potential API changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;React Server Components (RSC):&lt;/strong&gt; To fully leverage the benefits of useActionState, it's recommended to use it with React Server Components. This combination can significantly improve performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error Handling:&lt;/strong&gt; While useActionState simplifies state management, you'll still need to handle errors gracefully within your action function. Consider using try-catch blocks or returning error objects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimistic Updates:&lt;/strong&gt; You might want to implement optimistic updates to provide a better user experience. This involves updating the UI immediately after a form submission and then correcting it if necessary.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I hope you enjoyed reading the article. If you have any questions, thoughts, or just want to say hello, I'd be thrilled to hear from you. Here's how you can reach out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drop me an Email:&lt;/strong&gt; &lt;a href="//mailto:majd.hemud@gmail.com"&gt;majd.hemud@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow me 🥰&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/majd-hemud1996/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MajdHemud" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mecvino-coding.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/m3cv1no"&gt;DEV Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Explore My Portfolio
&lt;/h3&gt;

&lt;p&gt;If you want to see more of my work, don't forget to check out my &lt;a href="https://www.visionarydev.dev/" rel="noopener noreferrer"&gt;portfolio website&lt;/a&gt;! There, you'll find a curated collection of my projects, creative endeavors, and a deeper dive into my skills and passions 🔥.&lt;/p&gt;

&lt;p&gt;Whether you're looking for design inspiration, curious about my past projects, or just want to connect, my portfolio is the place to be.&lt;/p&gt;

&lt;p&gt;Until next time peace ✌️🥰.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>useTransition hook in React 19</title>
      <dc:creator>Majd Hemud</dc:creator>
      <pubDate>Thu, 25 Jul 2024 10:48:57 +0000</pubDate>
      <link>https://dev.to/m3cv1no/usetransition-hook-in-react-19-4if</link>
      <guid>https://dev.to/m3cv1no/usetransition-hook-in-react-19-4if</guid>
      <description>&lt;p&gt;React 19 is finally here! Bringing new features and APIs to the frontend world and for all React lovers. To create smoother, faster, and more efficient React apps.&lt;/p&gt;

&lt;p&gt;In this Article we will talk about &lt;code&gt;useTransition&lt;/code&gt; hook in React 19 😁&lt;/p&gt;

&lt;h3&gt;
  
  
  The useTransition hook
&lt;/h3&gt;

&lt;p&gt;This hook is your secret weapon to handle slow state updates without freezing the UI. Which is really cool when dealing with data fetching or expensive computations.&lt;/p&gt;

&lt;p&gt;In React 19 you can now directly pass an asynchronous function (like &lt;code&gt;async/await&lt;/code&gt;) to &lt;code&gt;startTransition&lt;/code&gt; function. This allows you to perform an asynchronous operation(e.g., API call) within the transition itself, simplifying your code and making it easier to manage the transition state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useTransition } from 'react';

async function fetchCarsData() {
  try {
    // Simulate delay
    await new Promise((resolve) =&amp;gt; setTimeout(resolve, 4000));

    // Replace this with your actual static data
    return [
      { id: 1, name: "BMW" },
      { id: 2, name: "Nissan" },
      { id: 3, name: "Honda" },
    ];
  } catch (error) {
    throw error;
  }
}

function CarList() {
  const [error, setError] = useState(null);
  const [cars, setCars] = useState([]);
  const [isPending, startTransition] = useTransition();

  const handleClick = async () =&amp;gt; {
    startTransition(async () =&amp;gt; {
      fetchCarsData().then((data) =&amp;gt; setCars(data))
      .catch((error) =&amp;gt; setError(error.message)); 
    });
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;button disabled={isPending} onClick={handleClick}&amp;gt;
        {isPending ? "Loading..." : "Load Cars"}
      &amp;lt;/button&amp;gt;
      {error ? (
        &amp;lt;p style={{ color: "red" }}&amp;gt;Error: {error}&amp;lt;/p&amp;gt;
      ) : isPending ? (
        &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;
      ) : cars.length &amp;gt; 0 ? (
        &amp;lt;ul&amp;gt;
          {cars.map((car) =&amp;gt; (
            &amp;lt;li key={car.id}&amp;gt;{car.name}&amp;lt;/li&amp;gt;
          ))}
        &amp;lt;/ul&amp;gt;
      ) : (
        &amp;lt;p&amp;gt;No cars loaded yet.&amp;lt;/p&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
}

export default CarList;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, the &lt;code&gt;fetchCarsData&lt;/code&gt; function is wrapped in &lt;code&gt;startTransition&lt;/code&gt; function. This ensures that the UI remains responsive even during the API call. Plus we used the &lt;code&gt;isPending&lt;/code&gt; flag to know if there is a pending transition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Things to avoid when using useTransition hook
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Avoid using &lt;code&gt;useTransition&lt;/code&gt; hook for state changes that control input elements (text fields, etc.). These need immediate updates for a good user experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;useTransition&lt;/code&gt; hook strategically for non-critical tasks that might cause lags, not for everything.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be aware that currently multiple transitions might run together, which could affect their timing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profile your app to identify bottlenecks before applying &lt;code&gt;useTransition&lt;/code&gt; hook. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User interactions always take priority over transitions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;While the &lt;code&gt;useTransition&lt;/code&gt; hook offers performance benefits, it requires careful consideration. It functions like a queue for non-critical updates, prioritizing responsiveness during user interactions.&lt;/p&gt;

&lt;p&gt;Excessive use can overload this queue, leading to delayed updates for both queued tasks and the overall application. It's best to use it strategically for tasks that can genuinely benefit from a slight delay without impacting the user experience.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed reading the article. If you have any questions, thoughts, or just want to say hello, I'd be thrilled to hear from you. Here's how you can reach out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drop me an Email:&lt;/strong&gt; &lt;a href="//mailto:majd.sami1996@gmail.com"&gt;majd.hemud@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow me 🥰&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/majd-hemud1996/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MajdHemud" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mecvino-coding.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/m3cv1no"&gt;DEV Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Explore My Portfolio
&lt;/h3&gt;

&lt;p&gt;If you want to see more of my work, don't forget to check out my &lt;a href="https://www.visionarydev.dev/" rel="noopener noreferrer"&gt;portfolio website&lt;/a&gt;! There, you'll find a curated collection of my projects, creative endeavors, and a deeper dive into my skills and passions 🔥.&lt;/p&gt;

&lt;p&gt;Whether you're looking for design inspiration, curious about my past projects, or just want to connect, my portfolio is the place to be.&lt;/p&gt;

&lt;p&gt;Until next time peace ✌️🥰.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>How to add Passage Authentication in Nextjs</title>
      <dc:creator>Majd Hemud</dc:creator>
      <pubDate>Mon, 26 Jun 2023 07:24:59 +0000</pubDate>
      <link>https://dev.to/m3cv1no/how-to-add-passage-authentication-in-nextjs-4b5b</link>
      <guid>https://dev.to/m3cv1no/how-to-add-passage-authentication-in-nextjs-4b5b</guid>
      <description>&lt;p&gt;First, I want to thank &lt;a href="https://1password.com/developers?utm_source=hashnode&amp;amp;utm_medium=landing-page&amp;amp;utm_campaign=hashnode-hackathon" rel="noopener noreferrer"&gt;&lt;strong&gt;1Password&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://hashnode.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Hashnode&lt;/strong&gt;&lt;/a&gt; for hosting this amazing hackathon. It's my first time entering hackathons and it's awesome to join the Hashnode community that has innovation and lovely vibes 🥰.&lt;/p&gt;

&lt;h3&gt;
  
  
  So What is Passage?
&lt;/h3&gt;

&lt;p&gt;Passage is a secure and Complete User Authentication solution. That helps you integrate secure login and registration with biometrics or magic links instead of passwords into your applications plus providing the smoothest login experience possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  How did I use it in my Nextjs App?
&lt;/h3&gt;

&lt;p&gt;So I used Passage to implement user Authentication in my Nextjs app, which was a bit challenging because I used Nextjs 13 with experimental features like using the &lt;strong&gt;app directory&lt;/strong&gt; and adding custom styling to the &lt;strong&gt;passage-auth&lt;/strong&gt; element but the result was great 😁.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's start adding Passage in your Nextjs app
&lt;/h3&gt;

&lt;p&gt;First, you'll need to install the &lt;a href="https://www.npmjs.com/package/@passageidentity/passage-elements" rel="noopener noreferrer"&gt;passage-elements&lt;/a&gt; package from npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i --save @passageidentity/passage-elements
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Passage Console
&lt;/h3&gt;

&lt;p&gt;To use Passage, you have to signup &lt;a href="https://passage.1password.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt; first, go to &lt;strong&gt;My Apps&lt;/strong&gt; , then create a new app&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2RAroUsG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687678591997/2371c877-d39b-457c-9d8a-c710b400f664.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2RAroUsG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687678591997/2371c877-d39b-457c-9d8a-c710b400f664.png" alt="passage console" width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can give any name for your app, for the domain in Nextjs it will be &lt;strong&gt;localhost:3000,&lt;/strong&gt; and the redirect URL is the URL that will be used to redirect the user after a successful login or registration, like /dashboard or /home.&lt;/p&gt;

&lt;p&gt;After creating your app, you will be redirected to the app dashboard. A new &lt;strong&gt;App ID&lt;/strong&gt; will be generated to use it in your app.&lt;/p&gt;

&lt;p&gt;To find it, head to the settings section then general&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vx6q7c7U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687681359965/b2a111d8-6791-43ec-a686-8fc332821f45.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vx6q7c7U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687681359965/b2a111d8-6791-43ec-a686-8fc332821f45.png" alt="passage console - settings section" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Plus you need the API Key to do API requests like checking if the passage auth token is still valid or not. To generate one, head to the settings section then API Keys&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rjOaOp74--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687689090364/8eb872d4-b23e-4cfc-8f1e-796323302289.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rjOaOp74--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687689090364/8eb872d4-b23e-4cfc-8f1e-796323302289.png" alt="passage console - settings section - api keys" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can give it any name and click the Create Key&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fl5ixjvd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687689205991/0d490b3d-15f8-46dd-968a-f27cbc336b03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fl5ixjvd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687689205991/0d490b3d-15f8-46dd-968a-f27cbc336b03.png" alt="passage console - create api key" width="453" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating the API Key, you need to copy it somewhere safe because it will be displayed once&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SK67LjDl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687689396784/b30adebf-a927-4a16-a6f2-c528fdd2820e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SK67LjDl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687689396784/b30adebf-a927-4a16-a6f2-c528fdd2820e.png" alt="passage console - api key created" width="458" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Passage Authentication😁
&lt;/h3&gt;

&lt;p&gt;After creating your app and getting the &lt;strong&gt;App ID&lt;/strong&gt; and the &lt;strong&gt;API Key&lt;/strong&gt; , you will need to create a .env file and insert these Environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PASSAGE_APP_ID= Your_app_id
PASSAGE_API_KEY= Your_api_key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Typescript Support
&lt;/h3&gt;

&lt;p&gt;If you are using TypeScript with your Next.js app, youll need to add the following type declaration to your &lt;code&gt;typings.d.ts&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;declare namespace JSX {
  import {
    PassageElement,
    PassageProfileElement,
  } from "@passageidentity/passage-elements";
  interface IntrinsicElements {
    "passage-auth": PassageElement;
    "passage-profile": PassageProfileElement;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating the sign-in page
&lt;/h3&gt;

&lt;p&gt;By using the App directory you will create a new page called &lt;strong&gt;signIn&lt;/strong&gt; under the auth folder&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pCob-MYl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687691505759/65529c08-f4e8-4078-815b-d51f089eef6d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pCob-MYl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687691505759/65529c08-f4e8-4078-815b-d51f089eef6d.png" alt="nextjs - create sign-in page" width="265" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then inside the sign-in page, you will need to render the &lt;code&gt;passage-auth&lt;/code&gt; element as follows:&lt;br&gt;
&lt;/p&gt;

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

import { useEffect, useState } from "react";

type PassageAuthEnvValuesType = {
  appID?: string;
  apiKey?: string;
};

export default function SignIn() {
  const [passageAuthEnvValues, setPassageAuthEnvValues] =
    useState&amp;lt;PassageAuthEnvValuesType&amp;gt;({});

/* isMounted state is added to insure that the 
   passage-auth element is getting the appID */
  const [isMounted, setIsMounted] = useState(false);

  useEffect(() =&amp;gt; {
    setIsMounted(true);
    require("@passageidentity/passage-elements/passage-auth");

    const fetechEnvValues = async () =&amp;gt; {
      const response = await fetch("/api/auth/passageAuth/envValues");
      const data = await response.json();
      setPassageAuthEnvValues(data);
    };
    fetechEnvValues();
  }, []);

  return isMounted &amp;amp;&amp;amp; passageAuthEnvValues.appID ? (
    &amp;lt;passage-auth app-id={passageAuthEnvValues.appID}&amp;gt;&amp;lt;/passage-auth&amp;gt;
  ) : null;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  API endpoint for Passage Authentication
&lt;/h3&gt;

&lt;p&gt;For the API endpoint, you will need to create an endpoint called envValues to get the Environment variables for Passage Authentication&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6s4DJEIf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687695027417/c79f566f-72d8-4d1d-bc68-f21117f07658.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6s4DJEIf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687695027417/c79f566f-72d8-4d1d-bc68-f21117f07658.png" alt="nextjs - api endpoint for passage authentication" width="232" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside the envValues route add the following endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const GET = async () =&amp;gt; {
  return new Response(
    JSON.stringify({
      appID: process.env.PASSAGE_APP_ID!,
      apiKey: process.env.PASSAGE_API_KEY!,
    }),
    { status: 200 }
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After adding the sign-in page and the endpoint for getting the Environment variables. The &lt;code&gt;passage-auth&lt;/code&gt; element will be rendered as expected in the sign-in page&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iaScXOHL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687700970358/1d307cd0-d970-4e3e-ba2d-bcc55c6079fe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iaScXOHL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1687700970358/1d307cd0-d970-4e3e-ba2d-bcc55c6079fe.png" alt="nextjs - passage-auth element - sign-in page" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was the basic implementation of Passage Authentication. But I made a cool implementation with this Authentication in my Nextjs app and it's called &lt;strong&gt;Promptopia&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Promptopia
&lt;/h3&gt;

&lt;p&gt;Promptopia is an open-source AI prompting tool for the modern world to discover, create and share creative prompts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Packages that I used in my project
&lt;/h3&gt;

&lt;p&gt;In this Nextjs app, I used a lot of cool packages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1- Framer Motion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Framer Motion is a powerful and easy-to-use animation library for React that helps you create smooth, responsive animations and interactions in your web applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2- Zustand&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Zustand is a simple and lightweight state management library for React applications that allows you to easily manage and share state across components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3- Tailwind CSS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tailwind CSS is a utility-first CSS framework for rapidly building custom user interfaces in web applications. It provides a set of pre-built CSS classes that you can use to style your HTML elements, making it easier and faster to design responsive and visually appealing web pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4- Mongoose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. It provides a simple and straightforward way to model your application data, manage database connections, and perform database operations like validation, querying, and schema management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final result
&lt;/h3&gt;

&lt;p&gt;You can check out the final result of the Nextjs app &lt;a href="https://promptopia-ten-sage.vercel.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, plus I deployed it to Vercel. The deployment process was incredibly smooth and blazingly fast 😁.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project code
&lt;/h3&gt;

&lt;p&gt;I have shared the project code on &lt;a href="https://github.com/MajdAbuHmoud/project_promptopia" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, so if you run into any issues while cloning, just let me know in the comments below 👍.&lt;/p&gt;

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

&lt;p&gt;And once again, I am truly grateful to &lt;a href="https://1password.com/developers?utm_source=hashnode&amp;amp;utm_medium=landing-page&amp;amp;utm_campaign=hashnode-hackathon" rel="noopener noreferrer"&gt;1Password&lt;/a&gt; and &lt;a href="https://hashnode.com/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt; for organizing such an inspiring event that led to the discovery of a groundbreaking approach to user authentication for any app or website. This innovative method holds the potential to revolutionize our digital experiences and create a brighter, more secure future 🙌.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed reading the article. If you have any questions, thoughts, or just want to say hello, I'd be thrilled to hear from you. Here's how you can reach out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drop me an Email&lt;/strong&gt;: &lt;strong&gt;&lt;a href="http://mailto:majd.sami1996@gmail.com/" rel="noopener noreferrer"&gt;majd.sami1996@gmail.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow me 🥰&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.linkedin.com/in/majd-abu-hmoud1996/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://twitter.com/MajdAbuHmoud" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/MajdAbuHmoud" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Explore My Portfolio
&lt;/h3&gt;

&lt;p&gt;If you want to see more of my work, don't forget to check out my &lt;a href="https://www.visionarydev.dev/" rel="noopener noreferrer"&gt;portfolio website&lt;/a&gt;! There, you'll find a curated collection of my projects, creative endeavors, and a deeper dive into my skills and passions 🔥.&lt;/p&gt;

&lt;p&gt;Whether you're looking for design inspiration, curious about my past projects, or just want to connect, my portfolio is the place to be.&lt;/p&gt;

&lt;p&gt;Until next time peace ✌️🥰.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hashnode.com/n/1password" rel="noopener noreferrer"&gt;&lt;strong&gt;#1Password&lt;/strong&gt;&lt;/a&gt; &lt;a href="https://hashnode.com/n/buildwith1password" rel="noopener noreferrer"&gt;&lt;strong&gt;#BuildWith1Password&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>1password</category>
      <category>buildwith1password</category>
      <category>nextjs</category>
      <category>nextjs13</category>
    </item>
  </channel>
</rss>
