<?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: Mykhaylo Ryechkin 🇺🇦</title>
    <description>The latest articles on DEV Community by Mykhaylo Ryechkin 🇺🇦 (@mryechkin).</description>
    <link>https://dev.to/mryechkin</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%2F27624%2F2327d716-dc97-464e-b9eb-784264070dd0.jpg</url>
      <title>DEV Community: Mykhaylo Ryechkin 🇺🇦</title>
      <link>https://dev.to/mryechkin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mryechkin"/>
    <language>en</language>
    <item>
      <title>All about React Server Components</title>
      <dc:creator>Mykhaylo Ryechkin 🇺🇦</dc:creator>
      <pubDate>Wed, 04 Oct 2023 20:33:00 +0000</pubDate>
      <link>https://dev.to/mryechkin/all-about-react-server-components-2nmd</link>
      <guid>https://dev.to/mryechkin/all-about-react-server-components-2nmd</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;React Server Components&lt;/strong&gt; are a new concept in the React ecosystem, and if you're wondering what all the fuss is about, then this article is for you.&lt;/p&gt;

&lt;p&gt;So... what are &lt;strong&gt;React Server Components&lt;/strong&gt; anyway?&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;React Server Components (often referred to as just &lt;strong&gt;Server Components&lt;/strong&gt; or &lt;strong&gt;RSC&lt;/strong&gt;) are a new paradigm coming to the React ecosystem, and signify what can be thought of as the &lt;strong&gt;3rd Age of React&lt;/strong&gt; - where there is a significant shift in how we write and architect our React code. The last time this happened was with introduction of hooks in function components.&lt;/p&gt;

&lt;p&gt;Server Components introduce a new way to architect React applications and libraries, and bring along a signficant change to our React mental model and how we think about a React component's lifecycle.&lt;/p&gt;

&lt;p&gt;You see, through most of React's lifetime (up until recently), the majority of applications built with it were what we consider &lt;strong&gt;client-side&lt;/strong&gt;. Let's call this era "the age of client-side React". This is every app that was built with the &lt;a href="https://create-react-app.dev"&gt;create-react-app&lt;/a&gt; scaffold (now legacy), or a myriad of other custom &lt;a href="https://webpack.js.org"&gt;Webpack&lt;/a&gt; configurations since React's inception.&lt;/p&gt;

&lt;p&gt;This is your typical app where you have a &lt;code&gt;&amp;lt;div id="root"&amp;gt;&lt;/code&gt; in your root HTML page, and your entire application bundle (including React itself) is shipped to the browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- index.html --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/dist/bundle.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the browser loads that page, your application is initialized and React renders it into that &lt;code&gt;root&lt;/code&gt; element using React DOM. From there, your application runs on the client side (meaning in the browser). This includes things like routing when using libraries like &lt;a href="https://reactrouter.com/"&gt;React Router&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This means that the browser needs to download all of the code necessary to render a particular page, and that carries a performance cost. Now, there are techniques like code-splitting to help mitigate the bundle size needed for a particular page, but that only takes you so far. At the end of the day there is still code that the browser needs to download, and then subsequently run, in order to get the final HTML output.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Server Components&lt;/strong&gt;, a server can do a lot of that work before sending a response to the browser - and have React do all the rendering &lt;em&gt;entirely&lt;/em&gt; on the server. The resulting HTML is then &lt;a href="https://www.patterns.dev/posts/streaming-ssr"&gt;streamed&lt;/a&gt; into the browser, which it knows exactly what to do with.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; In reality, it's more complex than that - but we'll keep it simple for the purposes of this explanation. See Further Reading for a list of much more detailed explanations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But wait, isn't that called "server-side rendering"? Well, not quite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server-Side Rendering (SSR) and RSC
&lt;/h2&gt;

&lt;p&gt;When a React app runs on the client, the first thing a user will see is a blank screen. That's because the initial HTML is just an empty &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element, and React hasn't had a chance to render anything yet. We see a result on the screen only once the browser downloads the JavaScript bundle, and React initializes the app. Depending on the network speed, application bundle size and other factors, this may take a varying amount of time. That's not the greatest user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server-Side Rendering&lt;/strong&gt; (or "SSR") is a way to address this problem. It is a mechanism through which a server can "pre-render" React components before the result is sent to the browser. The catch is, in order for these components to be fully interactive and work as expected, they need to be &lt;a href="https://react.dev/reference/react-dom/client/hydrateRoot"&gt;"hydrated"&lt;/a&gt; on the client - so the server needs to send an additional payload alongside the HTML for it to fully work. Additionally, SSR only happens on the initial page load.&lt;/p&gt;

&lt;p&gt;Prior to &lt;strong&gt;Server Components&lt;/strong&gt;, all React components were considered "client" components, because they all run in the browser (ie. the "client"). So even though SSR gives us pre-rendering of the static HTML, our React components aren't truly finished rendering until they've run on the client.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;RSC&lt;/strong&gt;, that all changes. Server Components render &lt;em&gt;entirely on the server&lt;/em&gt;. The result of this render is a special data format called the &lt;strong&gt;React Server Component Payload&lt;/strong&gt; (or &lt;strong&gt;RSC Payload&lt;/strong&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What is the React Server Component Payload (RSC)?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The RSC Payload is a compact binary representation of the rendered React Server Components tree. It's used by React on the client to update the browser's DOM. The RSC Payload contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The rendered result of Server Components&lt;/li&gt;
&lt;li&gt;Placeholders for where Client Components should be rendered and references to their JavaScript files&lt;/li&gt;
&lt;li&gt;Any props passed from a Server Component to a Client Component&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://nextjs.org/docs/app/building-your-application/rendering/server-components"&gt;Next.js Docs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the case of Next.js, the RSC Payload is then used to pre-render the initial HTML to send to the browser, as well as make subsequent updates to the UI after the initial page render (triggered by a route change, for example).&lt;/p&gt;

&lt;p&gt;Since RSC run on the server, they allow us to execute server-only code right there in body of the main rendering function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ServerComponent&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;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// connect directly to database&lt;/span&gt;
  &lt;span class="c1"&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;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* show data */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;table&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;That includes all of your favourite Node methods. Want to read from the file system? No problem - Node's &lt;code&gt;fs&lt;/code&gt; is readily available. You couldn't do this before in regular React components.&lt;/p&gt;

&lt;p&gt;This comes with caveats, however, as Server Components aren't without their limitations. As mentioned earlier, for components to be fully interactive, they need to be hydrated on the client. So, any attempt to run code like this on the server will result in an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ServerComponent&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleOnClick&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="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&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="nx"&gt;handleOnClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click Me&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&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;Additionally, Server Components can't run hooks and effects, so any attempt to &lt;code&gt;useEffect&lt;/code&gt; or &lt;code&gt;useState&lt;/code&gt; will also result in an error.&lt;/p&gt;

&lt;p&gt;If a React component requires any of the above, it will need to be declared a &lt;strong&gt;Client Component&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Client Components
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Client Components&lt;/strong&gt; are just regular React components we all use and love - they're essentially what all React components were prior to the introduction of &lt;strong&gt;RSC&lt;/strong&gt;. The name "Client Component" is simply to distinguish them from the new Server Components, and doesn't introduce anything new in itself.&lt;/p&gt;

&lt;p&gt;To declare a component as a Client Component, we need to add a &lt;code&gt;"use client"&lt;/code&gt; directive at the very top of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ClientComponent&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="nx"&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="c1"&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;function&lt;/span&gt; &lt;span class="nx"&gt;handleOnClick&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="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// this now works!&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;button&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="nx"&gt;handleOnClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click Me&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&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;This will tell React to treat anything in this file as a Client Component, and it will work exactly as you would expect a regular React component to work.&lt;/p&gt;

&lt;p&gt;Now, this entire mechanism requires some pretty deep integration with the bundler, since our app now crosses the client / server boundary. For this and other reasons, React team recommends &lt;a href="https://react.dev/learn/start-a-new-react-project"&gt;using a metaframework&lt;/a&gt; like &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt;, &lt;a href="https://remix.run/"&gt;Remix&lt;/a&gt; or &lt;a href="https://react.dev/learn/start-a-new-react-project#production-grade-react-frameworks"&gt;others&lt;/a&gt; when starting a new React project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js and RSC
&lt;/h2&gt;

&lt;p&gt;As of the writing of this article, &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; is the &lt;strong&gt;only&lt;/strong&gt; production-ready framework which supports RSC, and thus anything discussed here relating to React behaviour is within the context of Next.js implementation and handling of Server Components.&lt;/p&gt;

&lt;p&gt;It's important to know that Next.js uses a special &lt;strong&gt;canary&lt;/strong&gt; build of React (&lt;code&gt;18.3&lt;/code&gt; as of October 2023) to enable support of Server Components. Though many things are pretty well finalized on the Server Component API front, there may still be some changes introduced as React team finalizes this new paradigm, and other frameworks start to adopt RSC.&lt;/p&gt;

&lt;p&gt;To use Server Components in Next.js, one must use the new &lt;a href="https://nextjs.org/docs/app"&gt;App Router&lt;/a&gt;. As of Next 13.4, it's now the default when running &lt;code&gt;create-next-app&lt;/code&gt;, so if you haven't tried it out yet - it's really easy to do.&lt;/p&gt;

&lt;p&gt;Simply 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 create-next-app my-next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Server Component Characteristics
&lt;/h2&gt;

&lt;p&gt;Server Components have a few characteristics and gotchas to be aware of (see the official &lt;a href="https://github.com/josephsavona/rfcs/blob/server-components/text/0188-server-components.md#capabilities--constraints-of-server-and-client-components"&gt;RFC&lt;/a&gt; for more details):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server Components &lt;strong&gt;can't&lt;/strong&gt; use client-only features like event handlers, React context, state, hooks, and effects&lt;/li&gt;
&lt;li&gt;Server Components run &lt;strong&gt;once per request&lt;/strong&gt; on the server, which is why they &lt;strong&gt;can't&lt;/strong&gt; support client-only features like event handlers and component state&lt;/li&gt;
&lt;li&gt;Server Components &lt;strong&gt;can't&lt;/strong&gt; use browser API's&lt;/li&gt;
&lt;li&gt;Server Components &lt;strong&gt;can&lt;/strong&gt; render other Server Components, Client Components and native HTML elements&lt;/li&gt;
&lt;li&gt;Server Components &lt;strong&gt;can&lt;/strong&gt; be asynchronous (you &lt;strong&gt;can&lt;/strong&gt; use &lt;code&gt;await&lt;/code&gt; in the body of the component):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ServerComponent&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;note&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's also worthwhile to mention that using a &lt;code&gt;"use client"&lt;/code&gt; directive will mark &lt;strong&gt;everything&lt;/strong&gt; in that specific module as a Client Component. For that reason it's important to put Client Components in their own separate files.&lt;/p&gt;

&lt;p&gt;Another characteristic to keep in mind is that unlike regular React Components, &lt;strong&gt;Server Components cannot dot into a Client module&lt;/strong&gt;. What exactly does that mean?&lt;/p&gt;

&lt;p&gt;Say we have a Client Component like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Select.jsx&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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;Select&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="c1"&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;Item&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="c1"&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;default&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component exports the sub-component &lt;code&gt;Item&lt;/code&gt; by including it together with the &lt;code&gt;default&lt;/code&gt; export (via &lt;code&gt;Object.assign()&lt;/code&gt;) of the &lt;code&gt;Select&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Normally, that would allow us to use &lt;code&gt;Item&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;Select&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="s1"&gt;@acme/components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&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;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if we try this inside a Server Component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/page.jsx&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;Select&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="s1"&gt;@acme/components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&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;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll run into an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Cannot access .Item on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This has to do with how Client Components are bundled for the browser, and the server / client boundary. Without going into specifics of the &lt;em&gt;why&lt;/em&gt; (check out Further Reading for the nitty gritty) - to use this pattern we must denote the component as a Client Component, with the &lt;code&gt;"use client"&lt;/code&gt; directive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/page.jsx&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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;Select&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="s1"&gt;@acme/components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&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;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, everything will work as expected.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; If curious, there is an &lt;a href="https://github.com/vercel/next.js/issues/51593"&gt;open issue&lt;/a&gt; right now to provide clarity from the Next.js team on this pattern.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Note on Client Components
&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, Client Components are basically just a fancy name for regular React components, prior to introduction of Server Components. However, there is one &lt;strong&gt;very important&lt;/strong&gt; thing to keep in mind when it comes to using them alongside RSC.&lt;/p&gt;

&lt;p&gt;Client Components &lt;strong&gt;cannot&lt;/strong&gt; simply import Server Components - they must pass them along as &lt;strong&gt;serializable props&lt;/strong&gt;. This means that the following won't work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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="nx"&gt;useMemo&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="s1"&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="nx"&gt;ServerComponent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ServerComponent&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;Context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createContext&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;ClientComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ServerComponent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, pass the &lt;code&gt;ServerComponent&lt;/code&gt; as a child (or another prop) to the &lt;code&gt;ClientComponent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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="nx"&gt;useMemo&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="s1"&gt;react&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;Context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createContext&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;ClientComponent&lt;/span&gt; &lt;span class="o"&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;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;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&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;Why is this important? Well, since Server Components can run code that's only meant to be run on the server, they may very well include 3rd party packages or Node internals that &lt;strong&gt;cannot&lt;/strong&gt; run in the browser. In addition, this would bloat the client bundle (as everything from the Server Component would need to be included) - which is one of the things we're trying to avoid in the first place.&lt;/p&gt;

&lt;p&gt;It's a weird concept at first, but just remember it as a rule (kind of like we did with the rules of hooks).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should you care?
&lt;/h2&gt;

&lt;p&gt;So now that we know what React Server Components are and their basic characteristics, the big question is: "Why should I care?".&lt;/p&gt;

&lt;p&gt;Here are just some of the reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows you to run server-side code and make API requests right in the body of the component (no more relying on &lt;code&gt;useEffect&lt;/code&gt; to fetch the data)&lt;/li&gt;
&lt;li&gt;Helps prevent client-side data fetching waterfalls by resolving data dependencies server-side&lt;/li&gt;
&lt;li&gt;Server Components can be asynchronous, so you can use &lt;code&gt;await&lt;/code&gt; directly in the component body&lt;/li&gt;
&lt;li&gt;Having access to the server means you can access server secrets and use them in your React component, without exposing them to the client&lt;/li&gt;
&lt;li&gt;Helps save on client bundle size, since there is no need to send a large chunk of additional JavaScript anymore&lt;/li&gt;
&lt;li&gt;Allows you to keep the React component composition mental model, but apply it on the server&lt;/li&gt;
&lt;li&gt;Enables &lt;a href="https://nextjs.org/docs/app/building-your-application/rendering/server-components#streaming"&gt;Streaming&lt;/a&gt; and React &lt;a href="https://react.dev/reference/react/Suspense"&gt;Suspense&lt;/a&gt; - Server Components allow you to split the rendering work into chunks and stream them to the client as they become ready, allowing the user to see parts of the page earlier without having to wait for the entire page to be rendered on the server&lt;/li&gt;
&lt;li&gt;Faster initial page load and &lt;a href="https://web.dev/fcp/"&gt;First Contentful Paint (FCP)&lt;/a&gt;, since the initial static HTML can be shown to the user right away, without waiting for the client to download, parse and execute the JavaScript needed to render the page&lt;/li&gt;
&lt;li&gt;Improved &lt;strong&gt;SEO&lt;/strong&gt; (Search Engine Optimization) - the rendered HTML can be used by search engine bots to index pages (as opposed to when everything is rendered on the client)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to get started?
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, as of the writing of this article (October 2023), the main way to get started with Server Components is through Next.js &lt;a href="https://nextjs.org/docs/app"&gt;App Router&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Simply run &lt;code&gt;npx create-next-app@latest my-app&lt;/code&gt; which will ask you a few questions and scaffold a new Next.js application. By default, the App Router is used (via the &lt;code&gt;app&lt;/code&gt; folder). Now, any React components you write inside the &lt;code&gt;app&lt;/code&gt; folder will be considered Server Components by default, unless the &lt;code&gt;"use client"&lt;/code&gt; directive is present in the file.&lt;/p&gt;

&lt;p&gt;One important thing to keep in mind is that the &lt;a href="https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#root-layout-required"&gt;Root Layout&lt;/a&gt; in the &lt;code&gt;src/app/layout.jsx&lt;/code&gt; file &lt;strong&gt;must&lt;/strong&gt; be a Server Component. However, any of its children or &lt;a href="https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#nesting-layouts"&gt;nested layouts&lt;/a&gt; can be Client Components if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;This article covers the basics of RSC, but if you're curious to learn more there is a lot more material available.&lt;/p&gt;

&lt;p&gt;These are some of the best resources I've come across when learning about Server Components - check them out for a more in-depth look at RSC behaviour and its specifics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.plasmic.app/blog/how-react-server-components-work"&gt;How React Server Components Work (Plasmic Blog)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vercel.com/blog/understanding-react-server-components"&gt;Understanding React Server Components (Vercel Blog)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components"&gt;React Server Components (React Labs)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.joshwcomeau.com/react/server-components/"&gt;Making sense of React Server Components (Josh Comeau)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dagster.io/blog/dbt-docs-on-react"&gt;Speeding up the dbt™ docs by 20x with React Server Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/josephsavona/rfcs/blob/server-components/text/0188-server-components.md"&gt;RFC: React Server Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=fFIHZLiFYzE"&gt;Server-side rendering vs. Server Components (FrontEnd First Podcast, EP 169)&lt;/a&gt; (this discussion really helped understand some of the intricacies of RSCs)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mux.com/blog/what-are-react-server-components"&gt;Everything I wish I knew before moving 50k lines of code to RSC (Mux Blog)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; If you're looking to build a library that supports both Client and Server Components in one package, then check out my post about &lt;a href="https://dev.to/mryechkin/react-server-components-and-client-components-with-rollup-3c05"&gt;React Server Components and Client Components with Rollup&lt;/a&gt; for a setup that I've found to work well for me.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks for reading, and see you next time!&lt;/p&gt;

</description>
      <category>react</category>
      <category>servercomponents</category>
      <category>rsc</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Authentication in Next.js with Supabase Auth and PKCE</title>
      <dc:creator>Mykhaylo Ryechkin 🇺🇦</dc:creator>
      <pubDate>Tue, 08 Aug 2023 02:37:00 +0000</pubDate>
      <link>https://dev.to/mryechkin/authentication-in-nextjs-with-supabase-auth-and-pkce-45pk</link>
      <guid>https://dev.to/mryechkin/authentication-in-nextjs-with-supabase-auth-and-pkce-45pk</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Seems like just the other day I published an &lt;a href="https://dev.to/mryechkin/authentication-in-nextjs-with-supabase-and-next-13-36le"&gt;update&lt;/a&gt; to my original &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12"&gt;article&lt;/a&gt; on using &lt;strong&gt;Supabase Auth&lt;/strong&gt; with &lt;a href="https://nextjs.org" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;, and yet here we are with the 3rd installment in the series.&lt;/p&gt;

&lt;p&gt;So why another article? Well, as much as I was being a bit tongue-in-cheek about libraries changing all the time, it certainly seems to be the case with &lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt;. Their &lt;a href="https://supabase.com/docs/guides/auth/auth-helpers/nextjs" rel="noopener noreferrer"&gt;Next.js Auth Helpers&lt;/a&gt; has recently undergone several significant updates, and they are worth talking about.&lt;/p&gt;

&lt;p&gt;On the Next.js front, the &lt;a href="https://nextjs.org/docs/app/building-your-application/routing" rel="noopener noreferrer"&gt;&lt;code&gt;app&lt;/code&gt;&lt;/a&gt; router is now stable in release &lt;a href="https://nextjs.org/blog/next-13-4" rel="noopener noreferrer"&gt;13.4&lt;/a&gt;, which means a lot more projects starting to use React Server Components. Having been spending more time with RSC's myself, I'm finding certain patterns to work well, and wanted to share how I've applied those in this project.&lt;/p&gt;

&lt;p&gt;As the saying goes, "third time's the charm"? I sure hope so 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;A few months ago Supabase introduced support for &lt;a href="https://supabase.com/blog/supabase-auth-sso-pkce#introducing-pkce" rel="noopener noreferrer"&gt;Proof Key for Code Exchange&lt;/a&gt; flow (or &lt;strong&gt;PKCE&lt;/strong&gt; for short, pronounced "pixy").&lt;/p&gt;

&lt;p&gt;PKCE provides applications with a more robust and secure authorization process, protecting against various types of attacks and vulnerabilities that can arise in public client environments.&lt;/p&gt;

&lt;p&gt;The PKCE flow introduces a code &lt;strong&gt;verifier&lt;/strong&gt; (a randomly generated secret) and a code &lt;strong&gt;challenge&lt;/strong&gt; (the hash of the code verifier). The authorization code is returned as a query parameter so it's accessible on the server.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Learn more about &lt;strong&gt;Proof Key for Code Exchange&lt;/strong&gt; authentication flow &lt;a href="https://oauth.net/2/pkce" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alongside this came release &lt;a href="https://github.com/supabase/auth-helpers/releases/tag/%40supabase%2Fauth-helpers-nextjs%400.7.0" rel="noopener noreferrer"&gt;&lt;code&gt;0.7.0&lt;/code&gt;&lt;/a&gt; of the Next.js Auth Helpers library, which introduced some breaking changes in order to support the new PKCE flow.&lt;/p&gt;

&lt;p&gt;In this article, I'm going to share with you the patterns I've landed on for using &lt;strong&gt;PKCE&lt;/strong&gt; with Supabase Auth in Next.js 13+. The final solution ends up being much cleaner than the &lt;a href="https://dev.to/mryechkin/authentication-in-nextjs-with-supabase-and-next-13-36le"&gt;previous iteration&lt;/a&gt;, thanks to the recent updates in Supabase and the power of React Server Components.&lt;/p&gt;

&lt;p&gt;As a recap (or if you're reading this for the first time), here is what we're building:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13-pkce%2Fapp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13-pkce%2Fapp.png" alt="App Screens"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project has two authenticated pages - &lt;strong&gt;Home&lt;/strong&gt; and &lt;strong&gt;Profile&lt;/strong&gt;. Unauthenticated users can &lt;strong&gt;Sign In&lt;/strong&gt;, &lt;strong&gt;Sign Up&lt;/strong&gt;, &lt;strong&gt;Reset Password&lt;/strong&gt; and &lt;strong&gt;Update Password&lt;/strong&gt;. All of this is powered by Next.js &lt;code&gt;app&lt;/code&gt; router, with usage of both Client and Server Components, and Supabase handling all of the authentication related functionality. Forms are built using &lt;a href="https://formik.org/" rel="noopener noreferrer"&gt;Formik&lt;/a&gt; and &lt;a href="https://github.com/jquense/yup" rel="noopener noreferrer"&gt;Yup&lt;/a&gt; for field validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Page Structure
&lt;/h2&gt;

&lt;p&gt;Aiming to take full advantage of RSC's, I've decided to have each authentication flow have its own route (ie. &lt;code&gt;/sign-in&lt;/code&gt;, &lt;code&gt;/sign-up&lt;/code&gt;, &lt;code&gt;/reset-password&lt;/code&gt;, etc.). This is different from the &lt;a href="https://misha.wtf/blog/supabase-auth-next-13#pages-and-routes" rel="noopener noreferrer"&gt;previous implementation&lt;/a&gt;, where the Home route (&lt;code&gt;/&lt;/code&gt;) was rendering both authenticated &lt;em&gt;and&lt;/em&gt; unauthenticated state.&lt;/p&gt;

&lt;p&gt;One of the reasons for this is to have the &lt;strong&gt;Reset&lt;/strong&gt; and &lt;strong&gt;Update Password&lt;/strong&gt; flow work with PKCE. I've also found this approach to result in cleaner page code, without the extra logic for determining which view to show.&lt;/p&gt;

&lt;p&gt;So, our page routes will be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt; (authenticated &lt;strong&gt;Home&lt;/strong&gt; page)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/profile&lt;/code&gt; (authenticated &lt;strong&gt;Profile&lt;/strong&gt; page)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/sign-in&lt;/code&gt; (&lt;strong&gt;Sign In&lt;/strong&gt; page)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/sign-up&lt;/code&gt; (&lt;strong&gt;Sign Up&lt;/strong&gt; page)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/reset-password&lt;/code&gt; (&lt;strong&gt;Reset Password&lt;/strong&gt; page)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/update-password&lt;/code&gt; (&lt;strong&gt;Update Password&lt;/strong&gt; page)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Auth Forms
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://misha.wtf/blog/supabase-auth-next-13#auth-component" rel="noopener noreferrer"&gt;previous iteration&lt;/a&gt; of this guide, the individual auth forms were provided in a single &lt;code&gt;&amp;lt;Auth /&amp;gt;&lt;/code&gt; component, which had some internal state and used a &lt;code&gt;view&lt;/code&gt; prop for showing a specific form (or "view").&lt;/p&gt;

&lt;p&gt;Since each authentication flow will now have its own unique route, there isn't really a need for this single &lt;code&gt;&amp;lt;Auth /&amp;gt;&lt;/code&gt; component anymore. We can simply use the individual form components (&lt;code&gt;&amp;lt;SignIn /&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;SignUp /&amp;gt;&lt;/code&gt;, etc.) instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/sign-in/page.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SignIn&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/components/Auth/SignIn&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;default&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;SignInPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&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="nc"&gt;SignIn&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;The individual auth form components can be found in &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/blob/main/src/components/Auth" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. These were built using &lt;a href="https://formik.org/" rel="noopener noreferrer"&gt;Formik&lt;/a&gt;, following one of their examples in the docs. See the &lt;a href="https://dev.to/blog/supabase-auth-next-13#auth-component"&gt;previous post&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supabase Client
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, the Supabase &lt;a href="https://supabase.com/docs/guides/auth/auth-helpers/nextjs" rel="noopener noreferrer"&gt;Auth Helpers&lt;/a&gt; library for Next.js release &lt;a href="https://github.com/supabase/auth-helpers/releases/tag/%40supabase%2Fauth-helpers-nextjs%400.7.0" rel="noopener noreferrer"&gt;&lt;code&gt;0.7.0&lt;/code&gt;&lt;/a&gt; brought with it some substantial changes. In particular, these changes affected how we create and use the Supabase Client. Let's take a look at what those are and how they affect our project structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client Components
&lt;/h3&gt;

&lt;p&gt;One of the big changes is that Client Component Supabase clients are now &lt;strong&gt;singleton&lt;/strong&gt; instances, which was not the case before. Previously, we had to ensure that a single instance of Supabase was shared across Client Components. We did that using React &lt;a href="https://react.dev/learn/passing-data-deeply-with-context" rel="noopener noreferrer"&gt;Context&lt;/a&gt; and the &lt;code&gt;AuthProvider&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Now, thanks to the clients being singletons, we can simply import &lt;code&gt;createClientSupabaseClient&lt;/code&gt; and call it wherever we need a Supabase instance (in a Client Component):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;createClientSupabaseClient&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="s1"&gt;@supabase/auth-helpers-nextjs&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;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ClientComponent&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;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClientSupabaseClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This results in &lt;em&gt;much&lt;/em&gt; cleaner code in our Client Components, since we no longer need to keep track of the client-side session manually, allowing us to essentially ditch the provider pattern (well, almost... more on that below).&lt;/p&gt;

&lt;h3&gt;
  
  
  Server Components
&lt;/h3&gt;

&lt;p&gt;When it comes to Server Components, the pattern is pretty much the same. Except the function is named &lt;code&gt;createServerComponentClient&lt;/code&gt;, and we also need to pass it &lt;a href="https://nextjs.org/docs/app/api-reference/functions/cookies" rel="noopener noreferrer"&gt;&lt;code&gt;cookies&lt;/code&gt;&lt;/a&gt; from &lt;code&gt;next/headers&lt;/code&gt; so it can properly store the session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;createServerComponentClient&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="s1"&gt;@supabase/auth-helpers-nextjs&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;cookies&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="s1"&gt;next/headers&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;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ServerComponent&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;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createServerComponentClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;cookies&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above changes means that we no longer need to have a separate module for our Supabase clients like we did &lt;a href="https://dev.to/blog/supabase-auth-next-13#supabase-client"&gt;before&lt;/a&gt;, and can instead use the provided functions directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auth Provider
&lt;/h2&gt;

&lt;p&gt;In the previous version of this guide, we used React Context and the &lt;a href="https://react.dev/reference/react/createContext#provider" rel="noopener noreferrer"&gt;Provider&lt;/a&gt; pattern by wrapping our application in an &lt;code&gt;AuthProvider&lt;/code&gt; component, to ensure that a single instance of Supabase client was being used by our Client Components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/layout.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&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;RootLayout&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="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&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;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to the recent updates described above, that's no longer needed. But does that mean we can get rid of the &lt;code&gt;AuthProvider&lt;/code&gt; completely? Well, not quite.&lt;/p&gt;

&lt;p&gt;There is still a good reason to use it, and that's to trigger a &lt;a href="https://nextjs.org/docs/app/building-your-application/caching#routerrefresh" rel="noopener noreferrer"&gt;router refresh&lt;/a&gt; whenever the current &lt;code&gt;session&lt;/code&gt; changes. So long as we setup our pages to handle authenticated / unauthenticated state correctly, this will ensure that if a user signs out, they don't stay on the authenticated page, and similarly that they don't stay on an unauthenticated page after logging in. We'll see how to do that later on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling auth state changes
&lt;/h3&gt;

&lt;p&gt;To handle the above, we can &lt;a href="https://supabase.com/docs/reference/javascript/auth-onauthstatechange" rel="noopener noreferrer"&gt;listen to auth state changes&lt;/a&gt; inside a &lt;code&gt;useEffect&lt;/code&gt; in the &lt;code&gt;AuthProvider&lt;/code&gt; component, and trigger Next.js &lt;a href="https://nextjs.org/docs/app/building-your-application/caching#routerrefresh" rel="noopener noreferrer"&gt;&lt;code&gt;router.refresh()&lt;/code&gt;&lt;/a&gt; if the new session's &lt;code&gt;access_token&lt;/code&gt; doesn't match the existing one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/AuthProvider.js&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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="nx"&gt;useEffect&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="s1"&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;createClientComponentClient&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="s1"&gt;@supabase/auth-helpers-nextjs&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;useRouter&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="s1"&gt;next/navigation&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;AuthContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&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;AuthProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;accessToken&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;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;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClientComponentClient&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&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="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="na"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authListener&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="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;access_token&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;authListener&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;accessToken&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;router&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;children&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="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;accessToken&lt;/code&gt; is passed in from our root layout (&lt;code&gt;src/app/layout.js&lt;/code&gt;), where we read &lt;code&gt;access_token&lt;/code&gt; from the initial session, and pass it to 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 jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/layout.js&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;createServerComponentClient&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="s1"&gt;@supabase/auth-helpers-nextjs&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;cookies&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="s1"&gt;next/headers&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;AuthProvider&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/components/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;// ...&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&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;RootLayout&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="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;createServerComponentClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;cookies&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;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;=&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;getSession&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;accessToken&lt;/span&gt; &lt;span class="o"&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;access_token&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&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;AuthProvider&lt;/span&gt; &lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, any time the session changes or becomes invalid, our application will refresh.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, in order for this to fully work, we will also need to add logic in each page to handle the specific scenario (ie. should the user be redirected to the Home or Sign In page?).&lt;/p&gt;

&lt;h3&gt;
  
  
  Protected Routes and Redirecting
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Authenticated Pages
&lt;/h4&gt;

&lt;p&gt;For the &lt;strong&gt;Home&lt;/strong&gt; and &lt;strong&gt;Profile&lt;/strong&gt; pages, we want to ensure that only authenticated users have access. For this, we can check if a &lt;a href="https://supabase.com/docs/reference/javascript/auth-getuser" rel="noopener noreferrer"&gt;user exists&lt;/a&gt; in the current session, and &lt;a href="https://nextjs.org/docs/app/api-reference/functions/redirect" rel="noopener noreferrer"&gt;redirect&lt;/a&gt; to the &lt;code&gt;/sign-in&lt;/code&gt; page if not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/page.js&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;createServerComponentClient&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="s1"&gt;@supabase/auth-helpers-nextjs&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;cookies&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="s1"&gt;next/headers&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;redirect&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="s1"&gt;next/navigation&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;default&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;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="nx"&gt;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createServerComponentClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;cookies&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;user&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="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;getUser&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sign-in&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Unauthenticated Pages
&lt;/h4&gt;

&lt;p&gt;Similarly, we can ensure that the unauthenticated routes are only accessible if there is no current valid session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/sign-in/page.js&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;createServerComponentClient&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="s1"&gt;@supabase/auth-helpers-nextjs&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;cookies&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="s1"&gt;next/headers&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;redirect&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="s1"&gt;next/navigation&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;SignIn&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/components/Auth/SignIn&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;default&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;SignInPage&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;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createServerComponentClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;cookies&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="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;getSession&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;data&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="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SignIn&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;Here, we're checking for an existing session, and if one is found we redirect our user to the &lt;strong&gt;Home&lt;/strong&gt; page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Middleware and Refreshing Session
&lt;/h2&gt;

&lt;p&gt;Next up, we need to ensure that the user's session does not time out or become stale, as outlined in the &lt;a href="https://supabase.com/docs/guides/auth/auth-helpers/nextjs#managing-session-with-middleware" rel="noopener noreferrer"&gt;docs&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"When using the Supabase client on the server, you must perform extra steps to ensure the user's auth session remains active. Since the user's session is tracked in a cookie, we need to read this cookie and update it if necessary. Next.js Server Components allow you to read a cookie but not write back to it. Middleware on the other hand allow you to both read and write to cookies. Next.js &lt;a href="https://nextjs.org/docs/app/building-your-application/routing/middleware" rel="noopener noreferrer"&gt;Middleware&lt;/a&gt; runs immediately before each route is rendered. We'll use Middleware to refresh the user's session before loading Server Component routes."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To use Next.js Middleware, we'll need to create an &lt;code&gt;src/middleware.js&lt;/code&gt; file at the root of our source folder (NOT the &lt;code&gt;app&lt;/code&gt;, this is a common mistake!). In there we'll fetch the current session, and let Supabase client take care of updating the cookie.&lt;/p&gt;

&lt;p&gt;Similar to Server and Client Components, there is a separate function to create Supabase client in Middleware called &lt;code&gt;createMiddlewareClient&lt;/code&gt;. Add the following to &lt;code&gt;src/middleware.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/middleware.js&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;createMiddlewareClient&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="s1"&gt;@supabase/auth-helpers-nextjs&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;NextResponse&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="s1"&gt;next/server&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;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&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;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMiddlewareClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;getSession&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;res&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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;matcher&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="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/profile&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we really only need this to run on authenticated routes, so we're using path &lt;a href="https://nextjs.org/docs/app/building-your-application/routing/middleware#matching-paths" rel="noopener noreferrer"&gt;&lt;code&gt;matcher&lt;/code&gt;&lt;/a&gt; to ensure this code runs only for &lt;strong&gt;Home&lt;/strong&gt; and &lt;strong&gt;Profile&lt;/strong&gt; pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Code Exchange for PKCE flow
&lt;/h2&gt;

&lt;p&gt;Supabase Auth supports two authentication flows: &lt;strong&gt;Implicit&lt;/strong&gt; and &lt;strong&gt;PKCE&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;PKCE&lt;/strong&gt; flow is what we're using in this guide, and is generally preferred when on the server. It introduces a few additional steps which guard against replay and URL capture attacks. Unlike the &lt;strong&gt;Implicit&lt;/strong&gt; flow, it also allows users to access the &lt;code&gt;access_token&lt;/code&gt; and &lt;code&gt;refresh_token&lt;/code&gt; on the server.&lt;/p&gt;

&lt;p&gt;The Next.js Auth Helpers are configured to use the PKCE auth flow as of version &lt;code&gt;0.7.0&lt;/code&gt;, and require us to setup a Code Exchange route in order to exchange an auth &lt;code&gt;code&lt;/code&gt; for the user's session, which is set as a cookie for future requests made to Supabase.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
For security purposes, the code has a validity of 5 minutes and can only be exchanged for an access token once. You will need to restart the authentication flow from scratch if you wish to obtain a new access token.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To setup the code exchange, let's create a &lt;a href="https://nextjs.org/docs/app/building-your-application/routing/route-handlers" rel="noopener noreferrer"&gt;Route Handler&lt;/a&gt; at the &lt;code&gt;/auth/callback&lt;/code&gt; route. Create a file &lt;code&gt;src/app/auth/callback/route.js&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/auth/callback/route.js&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;createRouteHandlerClient&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="s1"&gt;@supabase/auth-helpers-nextjs&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;cookies&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="s1"&gt;next/headers&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;NextResponse&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="s1"&gt;next/server&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;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&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;requestUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;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;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;requestUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;code&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="nx"&gt;code&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;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRouteHandlerClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;cookies&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;exchangeCodeForSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// URL to redirect to after sign in process completes&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestUrl&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now anytime a user successfully signs in, Supabase will be able to store that session, and we'll have access to it through Supabase clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Auth Flows
&lt;/h2&gt;

&lt;p&gt;Now that we have Supabase configured, the next piece of the puzzle is to hook up our auth forms to handle the relevant authentication flows: &lt;strong&gt;Sign In&lt;/strong&gt;, &lt;strong&gt;Sign Up&lt;/strong&gt;, &lt;strong&gt;Reset Password&lt;/strong&gt; and &lt;strong&gt;Update Password&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;All of the forms will follow a similar pattern. We'll let &lt;a href="https://formik.org/" rel="noopener noreferrer"&gt;Formik&lt;/a&gt; handle all the form-related functionality (field validation, reading the form data), and on form submit we'll create a handler function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Formik&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sign In
&lt;/h3&gt;

&lt;p&gt;For &lt;strong&gt;Sign In&lt;/strong&gt;, we'll use email and password credentials, and the &lt;a href="https://supabase.com/docs/reference/javascript/auth-signinwithpassword" rel="noopener noreferrer"&gt;&lt;code&gt;signInWithPassword&lt;/code&gt;&lt;/a&gt; method.&lt;/p&gt;

&lt;p&gt;Add the following to the &lt;code&gt;SignIn&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Auth/SignIn.js&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SignIn&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="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;createClientComponentClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&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;signIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&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;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;signInWithPassword&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;formData&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="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// handle error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sign Up
&lt;/h3&gt;

&lt;p&gt;Similarly for &lt;strong&gt;Sign Up&lt;/strong&gt;, create a handler that will call the &lt;a href="https://supabase.com/docs/reference/javascript/auth-signup" rel="noopener noreferrer"&gt;&lt;code&gt;signUp&lt;/code&gt;&lt;/a&gt; method.&lt;/p&gt;

&lt;p&gt;Add the following in the &lt;code&gt;SignUp&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Auth/SignUp.js&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SignUp&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="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;createClientComponentClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&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;signUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&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;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;signUp&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;formData&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="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setErrorMsg&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="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setSuccessMsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Success! Please check your email for further instructions.&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="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reset Password
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Reset Password&lt;/strong&gt; flow consists of 2 main steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Allow the user to login via the password reset link&lt;/li&gt;
&lt;li&gt;Update the user's password&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When the user clicks the reset link in the email they are redirected back to our application. We'll need to specify the URL for that via the &lt;code&gt;redirectTo&lt;/code&gt; option in the &lt;a href="https://supabase.com/docs/reference/javascript/auth-resetpasswordforemail" rel="noopener noreferrer"&gt;&lt;code&gt;resetPasswordForEmail&lt;/code&gt;&lt;/a&gt; method.&lt;/p&gt;

&lt;p&gt;This URL will be a new route handler that will handle the authentication request from the email, and will essentially allow the user to be "logged in" in order to set a new password. That part we'll handle in the next step.&lt;/p&gt;

&lt;p&gt;First, in our &lt;code&gt;ResetPassword&lt;/code&gt; component, create a handler with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Auth/ResetPassword.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ResetPassword&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="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;createClientComponentClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&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;resetPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&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;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;resetPasswordForEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&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="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="s2"&gt;`&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="s2"&gt;/auth/update-password`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// handle error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// handle success&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;/auth/update-password&lt;/code&gt; will be the route that users will be redirected to. Note the use of &lt;code&gt;window.location.origin&lt;/code&gt; as well, which is an easy way to ensure the base path is always matching your environment (ie. local development vs production).&lt;/p&gt;

&lt;p&gt;Since this handler is always called on the client side (ie. in the browser), it's safe to use &lt;code&gt;window&lt;/code&gt; this way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Password
&lt;/h3&gt;

&lt;p&gt;When a user gets the Reset Password email and click on the link, they'll be redirected to the &lt;code&gt;/auth/update-password&lt;/code&gt; route in our app. This will be a route handler that will sign the user in (using the auth &lt;code&gt;code&lt;/code&gt; from the email), and once a session is created, redirect them to the &lt;code&gt;/update-password&lt;/code&gt; page so that they can set the new password.&lt;/p&gt;

&lt;p&gt;The mechanism here is very much the same as what we had setup for the &lt;code&gt;/auth/callback&lt;/code&gt; route, only this time after exchanging the &lt;code&gt;code&lt;/code&gt; for a session, we will redirect the user to &lt;code&gt;/update-password&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create a new file under &lt;code&gt;src/app/auth/update-password/route.js&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/auth/update-password/route.js&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;createRouteHandlerClient&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="s1"&gt;@supabase/auth-helpers-nextjs&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;cookies&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="s1"&gt;next/headers&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;NextResponse&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="s1"&gt;next/server&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;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&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;requestUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;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;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;requestUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;code&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="nx"&gt;code&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;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRouteHandlerClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;cookies&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;exchangeCodeForSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;requestUrl&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="s2"&gt;/update-password`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;ERROR: Invalid auth code or no auth code 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;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;requestUrl&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="s2"&gt;/sign-in`&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;Here, if the code exchange is successful, we're redirecting the user to &lt;code&gt;/update-password&lt;/code&gt; page, otherwise we send them back to &lt;code&gt;/sign-in&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next up, let's update our &lt;code&gt;UpdatePassword&lt;/code&gt; component to handle the actual password update itself. For this, we'll use &lt;a href="https://supabase.com/docs/reference/javascript/auth-updateuser" rel="noopener noreferrer"&gt;&lt;code&gt;updateUser&lt;/code&gt;&lt;/a&gt; method.&lt;/p&gt;

&lt;p&gt;Add the following to &lt;code&gt;src/components/Auth/UpdatePassword.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Auth/UpdatePassword.js&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UpdatePassword&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="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;createClientComponentClient&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&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;errorMsg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setErrorMsg&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;null&lt;/span&gt;&lt;span class="p"&gt;);&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;updatePassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&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;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;updateUser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// handle error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Go to Home page&lt;/span&gt;
      &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also want to make sure that only authenticated users can access the &lt;code&gt;/update-password&lt;/code&gt; route, so let's add that logic in our page code in &lt;code&gt;src/app/update-password/page.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/update-password/page.js&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;createServerComponentClient&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="s1"&gt;@supabase/auth-helpers-nextjs&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;cookies&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="s1"&gt;next/headers&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;redirect&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="s1"&gt;next/navigation&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;UpdatePassword&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/components/Auth/UpdatePassword&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;default&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;UpdatePasswordPage&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;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createServerComponentClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;cookies&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;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;=&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;getSession&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;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sign-in&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;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UpdatePassword&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;And that's it! Now our users can successfully update their password.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;The complete project can be found in GitHub: &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth" rel="noopener noreferrer"&gt;github.com/mryechkin/nextjs-supabase-auth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm pretty happy with the patterns I've landed on here, and plan on using this setup if I'm working with Supabase for the foreseeable future (or at least until Supabase decides to change things around again 😅)&lt;/p&gt;

&lt;p&gt;Jokes aside, this will (probably) be the last I wrote on this topic for some time. If you haven't yet, check out my previous two articles in this series for more background and the history of my explorations with Supabase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 1: &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12"&gt;User Authentication in Next.js with Supabase&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 2: &lt;a href="https://dev.to/mryechkin/authentication-in-nextjs-with-supabase-and-next-13-36le"&gt;Authentication in Next.js with Supabase and Next 13&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading! Until next time.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>supabase</category>
      <category>authentication</category>
      <category>pkce</category>
    </item>
    <item>
      <title>React Server Components and Client Components with Rollup</title>
      <dc:creator>Mykhaylo Ryechkin 🇺🇦</dc:creator>
      <pubDate>Sat, 18 Mar 2023 14:10:18 +0000</pubDate>
      <link>https://dev.to/mryechkin/react-server-components-and-client-components-with-rollup-3c05</link>
      <guid>https://dev.to/mryechkin/react-server-components-and-client-components-with-rollup-3c05</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;With the release of &lt;a href="https://nextjs.org/blog/next-13" rel="noopener noreferrer"&gt;Next 13&lt;/a&gt; and introduction of the beta &lt;a href="https://beta.nextjs.org/docs/app-directory-roadmap" rel="noopener noreferrer"&gt;&lt;code&gt;app/&lt;/code&gt;&lt;/a&gt; directory, we now have support for React &lt;a href="https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html" rel="noopener noreferrer"&gt;Server Components&lt;/a&gt;, and can start building applications using these new React paradigms.&lt;/p&gt;

&lt;p&gt;Awhile back I &lt;a href="https://dev.to/mryechkin/rollup-library-starter-7ab"&gt;wrote about&lt;/a&gt; packaging your JavaScript library code into a dual-module bundle (ESM + CommonJS) using &lt;a href="https://rollupjs.org" rel="noopener noreferrer"&gt;Rollup&lt;/a&gt; module bundler. Make sure to check it out (it's been updated for Rollup v3!).&lt;/p&gt;

&lt;p&gt;A starter template for React using the setup covered in that post is available here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✨ &lt;a href="https://github.com/mryechkin/rollup-library-starter" rel="noopener noreferrer"&gt;github.com/mryechkin/rollup-library-starter&lt;/a&gt; ✨&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, that template is great. I've used it in several libraries that have been published to production for several years now without problems.&lt;/p&gt;

&lt;p&gt;However, when trying to import a component from a library built using that starter template in a Next 13 &lt;code&gt;app&lt;/code&gt; directory, you get the following error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Frollup-server-components%2Fimport-error.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Frollup-server-components%2Fimport-error.png" alt="Server Component import error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Next 13 pages inside &lt;code&gt;app&lt;/code&gt; directory are &lt;a href="https://beta.nextjs.org/docs/rendering/server-and-client-components#server-components" rel="noopener noreferrer"&gt;React Server Components&lt;/a&gt; by default. In fact, anything deemed a React component, when consumed within the &lt;code&gt;app&lt;/code&gt; directory, is considered to be a &lt;strong&gt;Server Component&lt;/strong&gt; by default.&lt;/p&gt;

&lt;p&gt;To make a React component into a &lt;strong&gt;Client Component&lt;/strong&gt; (ie. our regular old React components with effects and state that we all use and love), you need to denote it with a &lt;code&gt;'use client'&lt;/code&gt; directive at the top of the component file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ClientComponent.js&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ClientComponent&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="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;Client Components are any components that rely on client-side only features, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React &lt;a href="https://react.dev/learn/passing-data-deeply-with-context" rel="noopener noreferrer"&gt;context&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;React &lt;a href="https://react.dev/reference/react" rel="noopener noreferrer"&gt;hooks&lt;/a&gt; (&lt;code&gt;useEffect&lt;/code&gt;, &lt;code&gt;useState&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Event handlers&lt;/li&gt;
&lt;li&gt;Animations&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;window&lt;/code&gt; object&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, when I tried to import a &lt;code&gt;Button&lt;/code&gt; component (which has event handlers and is "interactive") inside a Server Component, React had no idea that it was supposed to be a Client Component. It didn't see a &lt;code&gt;'use client'&lt;/code&gt; anywhere in the library code, so it assumed that it's a Server Component.&lt;/p&gt;

&lt;p&gt;This is something that component libraries will need to start addressing soon, as Server Components start to gain ground (and some already have). I wanted to make sure that my starter template supported Server Components properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Possible Solution
&lt;/h2&gt;

&lt;p&gt;One way to address this would be to mark all components in our library as Client Components. This would mean having a top-level &lt;code&gt;'use client'&lt;/code&gt; directive in each file (or at the top of the bundled file if not using directories).&lt;/p&gt;

&lt;p&gt;To do this, include a &lt;code&gt;banner&lt;/code&gt; option in your &lt;code&gt;output&lt;/code&gt; options inside the &lt;code&gt;rollup.config.js&lt;/code&gt;, and add &lt;code&gt;'use client'&lt;/code&gt; at the very end of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// rollup.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outputOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;named&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;preserveModules&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="na"&gt;banner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/*
 * Rollup Library Starter
 * {@link https://github.com/mryechkin/rollup-library-starter}
 * @copyright Mykhaylo Ryechkin (@mryechkin)
 * @license MIT
 */
'use client';`&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, if you leave it as is, the &lt;code&gt;terser&lt;/code&gt; plugin will remove it, so we need to tell it to preserve directives by setting the &lt;code&gt;compress.directives&lt;/code&gt; option to &lt;code&gt;false&lt;/code&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="c1"&gt;// rollup.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&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="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nf"&gt;terser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;compress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;directives&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="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 now if you run the &lt;code&gt;build&lt;/code&gt; script, you'll see that our bundled files have that included at the top.&lt;/p&gt;

&lt;p&gt;Great!&lt;/p&gt;

&lt;p&gt;...or is it? 🤔&lt;/p&gt;

&lt;h2&gt;
  
  
  Better Solution
&lt;/h2&gt;

&lt;p&gt;While the above solution works, it's not very elegant.&lt;/p&gt;

&lt;p&gt;We don't necessarily want every component to be a Client Component. There can be components in your library that don't rely on state or use any effects, and can very well benefit from being Server Components.&lt;/p&gt;

&lt;p&gt;Well, we've already configured Rollup to output separate files for each of our modules. What if we simply add &lt;code&gt;'use client'&lt;/code&gt; to the component files themselves?&lt;/p&gt;

&lt;p&gt;A-ha! 💡&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Button/Button.js&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="cm"&gt;/* */&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However... If we try to run the &lt;code&gt;build&lt;/code&gt;, we'll see a warning like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Frollup-server-components%2Fmodule-warning.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Frollup-server-components%2Fmodule-warning.png" alt="Rollup build warning"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rollup will simply ignore this directory and not include it in our final bundle. And this is a good thing, in general. However, in this case we &lt;em&gt;want&lt;/em&gt; this directive to be included. This is where Rollup community comes to the rescue 🎉&lt;/p&gt;

&lt;p&gt;While searching for a solution, I came across &lt;a href="https://github.com/rollup/rollup/issues/4699" rel="noopener noreferrer"&gt;this issue&lt;/a&gt;. Ironically, one of the suggested solutions in there was the initial solution described earlier above. However, there was also another suggestion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Ephem" rel="noopener noreferrer"&gt;Fredrik Höglund&lt;/a&gt; shared his plugin that solves our exact problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Ephem/rollup-plugin-preserve-directives" rel="noopener noreferrer"&gt;&lt;code&gt;rollup-preserve-directives&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This plugin, as its name implies, preserves any directives written at the top of our files:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This plugin preserves directives when &lt;code&gt;preserveModules: true&lt;/code&gt; is set in the Rollup config.&lt;/p&gt;

&lt;p&gt;Rollup by default always removes directives like &lt;code&gt;'use client'&lt;/code&gt; from the top of files. This makes sense when bundling files because directives should be applied per file, which is not possible when bundling.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;preserveModules: true&lt;/code&gt; is set, because each module is a separate output file, it's possible to keep directives, which is exactly what this plugin does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because we're already using the &lt;code&gt;preserveModules&lt;/code&gt; option in our Rollup config, this will work great.&lt;/p&gt;

&lt;p&gt;With this plugin, we can safely leave the &lt;code&gt;'use client'&lt;/code&gt; directives in our component files (where they belong), and Rollup won't remove them from our bundled files.&lt;/p&gt;

&lt;p&gt;To use the plugin, first install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; rollup-plugin-preserve-directives
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add it to the &lt;code&gt;plugins&lt;/code&gt; array in your &lt;code&gt;rollup.config.js&lt;/code&gt; (before &lt;code&gt;terser&lt;/code&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="c1"&gt;// rollup.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;preserveDirectives&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-plugin-preserve-directives&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&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="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nf"&gt;preserveDirectives&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;terser&lt;/span&gt;&lt;span class="p"&gt;(),&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;Running the &lt;code&gt;build&lt;/code&gt; again, we can see that the &lt;code&gt;'use client'&lt;/code&gt; directive is preserved in the output files:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Frollup-server-components%2Fuse-client.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Frollup-server-components%2Fuse-client.png" alt="Preserved "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now we can import it in a Server Component and use without any issues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/index.js&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;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&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="s1"&gt;rollup-library-starter&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;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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Disabling the warning
&lt;/h3&gt;

&lt;p&gt;Currently the &lt;code&gt;rollup-preserve-directives&lt;/code&gt; plugin doesn't suppress that Rollup warning we saw earlier. Its README &lt;a href="https://github.com/Ephem/rollup-plugin-preserve-directives#rollup-warning" rel="noopener noreferrer"&gt;suggests&lt;/a&gt; to add a custom &lt;code&gt;onwarn&lt;/code&gt; handler to the Rollup config if desired.&lt;/p&gt;

&lt;p&gt;Let's do that. Add the following to &lt;code&gt;rollup.config.js&lt;/code&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="c1"&gt;// rollup.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="nf"&gt;onwarn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MODULE_LEVEL_DIRECTIVE&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;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;warning&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;This will suppress any &lt;code&gt;MODULE_LEVEL_DIRECTIVE&lt;/code&gt; warnings, and throw all others. See &lt;a href="https://rollupjs.org/configuration-options/#onwarn" rel="noopener noreferrer"&gt;Rollup docs&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starter Template
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/mryechkin/rollup-library-starter" rel="noopener noreferrer"&gt;&lt;code&gt;rollup-library-starter&lt;/code&gt;&lt;/a&gt; template has been updated to use this plugin, and is available in GitHub for your reference:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✨ &lt;a href="https://github.com/mryechkin/rollup-library-starter" rel="noopener noreferrer"&gt;github.com/mryechkin/rollup-library-starter&lt;/a&gt; ✨&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;

</description>
      <category>rollup</category>
      <category>javascript</category>
      <category>bundling</category>
      <category>rsc</category>
    </item>
    <item>
      <title>Authentication in Next.js with Supabase and Next 13</title>
      <dc:creator>Mykhaylo Ryechkin 🇺🇦</dc:creator>
      <pubDate>Wed, 25 Jan 2023 23:51:51 +0000</pubDate>
      <link>https://dev.to/mryechkin/authentication-in-nextjs-with-supabase-and-next-13-36le</link>
      <guid>https://dev.to/mryechkin/authentication-in-nextjs-with-supabase-and-next-13-36le</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT:&lt;/strong&gt; Note that this guide is now outdated, and is using an older version of the &lt;strong&gt;Next.js Auth Helpers&lt;/strong&gt; (pinned at &lt;code&gt;0.6.1&lt;/code&gt;). Please see the &lt;a href="https://dev.to/mryechkin/authentication-in-nextjs-with-supabase-auth-and-pkce-45pk"&gt;updated guide&lt;/a&gt; for the latest version that utilizes the &lt;strong&gt;Proof Key for Code Exchange&lt;/strong&gt; (PKCE) flow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Awhile back I wrote an &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12"&gt;article&lt;/a&gt; on using &lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; to implement user authentication in a &lt;a href="https://nextjs.org" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; app. As it often goes in the world of open-source web, things evolve quickly and a lot can change in just over a year, and so is the case with Supabase.&lt;/p&gt;

&lt;p&gt;In this post, I would like to bring you an updated guide on implementing user auth with Supabase and Next.js in &lt;strong&gt;2023&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Make sure to read the &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12"&gt;original post&lt;/a&gt; first if you haven't yet, as we'll be building on the main concepts covered there. Code for the Supabase &lt;strong&gt;v1&lt;/strong&gt; implementation can be found under the &lt;code&gt;v1&lt;/code&gt; branch in &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/tree/v1" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What's New?
&lt;/h2&gt;

&lt;p&gt;So, what all has changed? Let's start with the big stuff.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next 13
&lt;/h3&gt;

&lt;p&gt;In October 2022, Next.js team announced &lt;a href="https://nextjs.org/blog/next-13" rel="noopener noreferrer"&gt;Next 13&lt;/a&gt;, and with it came the new &lt;a href="https://beta.nextjs.org/docs/app-directory-roadmap" rel="noopener noreferrer"&gt;&lt;code&gt;app&lt;/code&gt; directory&lt;/a&gt; architecture.&lt;/p&gt;

&lt;p&gt;Though officially still in beta (as of January 2023), the &lt;code&gt;app&lt;/code&gt; directory offers a great new way of architecting our apps, and introduces new features like &lt;a href="https://beta.nextjs.org/docs/routing/pages-and-layouts#layouts" rel="noopener noreferrer"&gt;nested layouts&lt;/a&gt; and support for React &lt;a href="https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html" rel="noopener noreferrer"&gt;Server Components&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I wanted to explore how this new paradigm would work with Supabase, and try some of the capabilities in a familiar project. Happy to say that this exploration went well, and we'll go over one approach of using the new &lt;code&gt;app&lt;/code&gt; architecture in this guide.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supabase v2
&lt;/h3&gt;

&lt;p&gt;Next up, Supabase released &lt;a href="https://supabase.com/blog/supabase-js-v2" rel="noopener noreferrer"&gt;v2&lt;/a&gt; of their JavaScript client library (&lt;a href="https://github.com/supabase/supabase-js" rel="noopener noreferrer"&gt;supabase-js&lt;/a&gt;), which brought with it a number of developer experience type improvements, and streamlined how we use some of the API's. A number of methods were also deprecated in this new release, which we'll cover later in this guide.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supabase Auth Helpers
&lt;/h3&gt;

&lt;p&gt;In addition to the new version of the client library, Supabase also introduced new &lt;a href="https://supabase.com/docs/guides/auth/auth-helpers" rel="noopener noreferrer"&gt;Auth Helpers&lt;/a&gt; earlier this year, which is a collection of libraries and framework-specific utilities for working with user authentication in Supabase.&lt;/p&gt;

&lt;p&gt;These utilities eliminate the need to keep writing the same boilerplate code over and over (e.g. initializing Supabase client, setting cookies, etc.), and let us focus on our application code instead. We'll be utilizing their &lt;a href="https://supabase.com/docs/guides/auth/auth-helpers/nextjs" rel="noopener noreferrer"&gt;Next.js helpers&lt;/a&gt; library in our project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supabase UI (Deprecated)
&lt;/h3&gt;

&lt;p&gt;Lastly, the &lt;code&gt;Auth&lt;/code&gt; component from the &lt;strong&gt;Supabase UI&lt;/strong&gt; library which we were using to render our auth screens, and handle all the related flows and UI logic (Sign In, Sign Up, Reset Password, etc.) &lt;strong&gt;has been deprecated&lt;/strong&gt;. Components from the original &lt;a href="https://github.com/supabase/ui" rel="noopener noreferrer"&gt;@supabase/ui&lt;/a&gt; package were moved into the main &lt;a href="https://github.com/supabase/supabase" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; repo, and the package is now deprecated.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://ui.supabase.io/components/auth" rel="noopener noreferrer"&gt;Auth&lt;/a&gt; component itself now has a new name "&lt;strong&gt;Auth UI&lt;/strong&gt;", and lives in its own separate &lt;a href="https://github.com/supabase/auth-ui" rel="noopener noreferrer"&gt;repo&lt;/a&gt;. Though originally intending to use it, as I began migrating the code I've found this new component to not work quite as well as I'd hoped, getting in the way more than helping. For that reason, I've decided to abandon it in this guide, and build one instead.&lt;/p&gt;

&lt;p&gt;Fortunately, building a component like this from scratch isn't all that difficult thanks to libraries like &lt;a href="https://formik.org/" rel="noopener noreferrer"&gt;Formik&lt;/a&gt;, so we'll use that to help us handle all of our form logic. This has the added benefit of giving us full control of the auth flow, and the ability to customize the form UI however we'd like, without being limited by Supabase's customization options.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;In the interest of saving some time, we'll start with the project from the &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12"&gt;original post&lt;/a&gt;, as we do end up re-using a bunch of existing code.&lt;/p&gt;

&lt;p&gt;The code for that is in &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/tree/v1" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; for your reference. If you're doing this for the first time, clone the &lt;code&gt;v1&lt;/code&gt; branch as your starting point.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating Dependencies
&lt;/h3&gt;

&lt;p&gt;First things first, we'll need to update Next.js and &lt;a href="https://github.com/supabase/supabase-js" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; to the latest versions, and install &lt;a href="https://github.com/jaredpalmer/formik" rel="noopener noreferrer"&gt;Formik&lt;/a&gt; (+ related dependencies) and the &lt;a href="https://github.com/supabase/auth-helpers" rel="noopener noreferrer"&gt;Next.js Auth Helpers&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;next@latest react@latest react-dom@latest @supabase/supabase-js@2.21.0 @supabase/auth-helpers-nextjs@0.6.1 classnames formik yup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll also utilize Tailwind's &lt;a href="https://github.com/tailwindlabs/tailwindcss-forms" rel="noopener noreferrer"&gt;Forms Plugin&lt;/a&gt; to make it easier to style our &lt;code&gt;Auth&lt;/code&gt; component, so let's install that 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;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; @tailwindcss/forms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also remove &lt;code&gt;@supabase/ui&lt;/code&gt;, since we won't be using it anymore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm uninstall @supabase/ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With dependencies updated, we'll need to configure Next to use the new &lt;code&gt;app&lt;/code&gt; directory (make sure you're on version 13 or above). To enable this, add (or update) &lt;code&gt;next.config.js&lt;/code&gt; in the project's root folder:&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;// next.config.js&lt;/span&gt;
&lt;span class="cm"&gt;/** @type {import('next').NextConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;reactStrictMode&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="na"&gt;experimental&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;appDir&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;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will allow us to start moving some of our existing code from the &lt;code&gt;pages&lt;/code&gt; directory to the &lt;code&gt;app&lt;/code&gt; folder. Note that putting the &lt;code&gt;app&lt;/code&gt; folder under &lt;code&gt;src&lt;/code&gt; also works, which is how the previous project was setup.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure to &lt;a href="https://nextjs.org/docs/app/building-your-application/routing#the-app-directory" rel="noopener noreferrer"&gt;read more&lt;/a&gt; about the new &lt;code&gt;app&lt;/code&gt; directory if you aren't familiar with the new features.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Updating Tailwind Config
&lt;/h3&gt;

&lt;p&gt;Last thing we need to do is specify the &lt;code&gt;@tailwindcss/forms&lt;/code&gt; plugin in our Tailwind config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tailwind.config.js&lt;/span&gt;
&lt;span class="cm"&gt;/** @type {import('tailwindcss').Config} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;forms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tailwindcss/forms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;content&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="s1"&gt;./src/**/*.{js,ts,jsx,tsx}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;media&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;forms&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;h3&gt;
  
  
  Supabase API keys
&lt;/h3&gt;

&lt;p&gt;To use Supabase, we'll need to have our Supabase API key and URL setup.&lt;/p&gt;

&lt;p&gt;If you haven't already, create an &lt;code&gt;.env&lt;/code&gt; file and specify the corresponding values from Supabase &lt;a href="https://app.supabase.io" rel="noopener noreferrer"&gt;dashboard&lt;/a&gt; (refer to the &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12#supabase-setup"&gt;previous post&lt;/a&gt; for more details):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;// .env&lt;/span&gt;
&lt;span class="s"&gt;NEXT_PUBLIC_SUPABASE_URL=&lt;/span&gt;
&lt;span class="s"&gt;NEXT_PUBLIC_SUPABASE_ANON_KEY=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Supabase Client
&lt;/h3&gt;

&lt;p&gt;With API keys setup, let's now create the Supabase Client so that we can interact with Supabase API's. We'll be using the &lt;strong&gt;Next.js Auth Helpers&lt;/strong&gt; library installed earlier for this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT:&lt;/strong&gt; The instructions below are using &lt;code&gt;@supabase/auth-helpers-nextjs@0.6.1&lt;/code&gt;. At the time of writing, there is an issue with password reset flow in the latest version. Additionally, some of the methods used in this guide have been renamed in version &lt;a href="https://github.com/supabase/auth-helpers/releases/tag/%40supabase%2Fauth-helpers-nextjs%400.7.0" rel="noopener noreferrer"&gt;&lt;code&gt;0.7.0&lt;/code&gt;&lt;/a&gt;. See the project repo in &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; for any future changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In order to support both the new Server Components and the Client Components, we'll need to have two different kinds of a Supabase Client:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser&lt;/strong&gt; Client: for use with Client Components in the browser, for example within a &lt;code&gt;useEffect&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Component&lt;/strong&gt; Client: for use specifically with Server Components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create two files - &lt;code&gt;supabase-browser.js&lt;/code&gt; and &lt;code&gt;supabase-server.js&lt;/code&gt; - one for each type of client. We'll put these in the &lt;code&gt;src/lib&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└──src/
    └── lib/
         ├── supabase-browser.js
         └── supabase-server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Browser Client
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/supabase-browser.js&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;createBrowserSupabaseClient&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="s1"&gt;@supabase/auth-helpers-nextjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// NOTE: `createBrowserSupabaseClient` has been renamed to `createPagesBrowserClient` in version `0.7.0`&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;createBrowserSupabaseClient&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;default&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Server Component Client
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/supabase-server.js&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;createServerComponentSupabaseClient&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="s1"&gt;@supabase/auth-helpers-nextjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// NOTE: `createServerComponentSupabaseClient` has been renamed to `createServerComponentClient` in version `0.7.0`&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;cookies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&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="s1"&gt;next/headers&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;default &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;createServerComponentSupabaseClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this needs to export a function, as the &lt;code&gt;headers&lt;/code&gt; and &lt;code&gt;cookies&lt;/code&gt; are not populated with values until the Server Component is requesting data (according to &lt;a href="https://supabase.com/docs/guides/auth/auth-helpers/nextjs-server-components#creating-a-supabase-client" rel="noopener noreferrer"&gt;Supabase docs&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;With the clients setup, we can now import them in our pages and components to interact with Supabase.&lt;/p&gt;

&lt;p&gt;E.g. in a &lt;strong&gt;Client Component&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/lib/supabase-browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ClientComponent&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getData&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="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;getSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;getData&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E.g. in a &lt;strong&gt;Server Component&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;createClient&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/lib/supabase-server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;ServerComponent&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;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="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="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;getSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Application Structure
&lt;/h2&gt;

&lt;p&gt;The overall page structure and routes will largely remain &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12#application-structure"&gt;the same as before&lt;/a&gt;, so we'll get to re-use a bunch of existing code. The biggest change will be moving all page code from the &lt;code&gt;pages&lt;/code&gt; folder to the new &lt;code&gt;app&lt;/code&gt; directory. As we do that, we'll also need to refactor some things to align with this new paradigm.&lt;/p&gt;

&lt;p&gt;Our project folder structure will look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└── src/
    ├── app/
    │   ├── profile/
    │   │   └── page.js
    │   ├── head.js
    │   ├── layout.js
    │   └── page.js
    ├── components/
    │   ├── Auth/
    │   │   ├── index.js
    │   │   ├── ResetPassword.js
    │   │   ├── SignIn.js
    │   │   ├── SignUp.js
    │   │   └── UpdatePassword.js
    │   └── AuthProvider.js
    └── middleware.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go through what each of these are.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pages and Routes
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Home: &lt;code&gt;/&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This is the main &lt;strong&gt;Home&lt;/strong&gt; page, showing the &lt;code&gt;Auth&lt;/code&gt; component if no session is found (ie. user needs to sign-in), or a link to the &lt;strong&gt;Profile&lt;/strong&gt; page if there is an active session with a valid user.&lt;/p&gt;

&lt;p&gt;This page also handles the "Update Password" flow, and will be redirected to from the link in the reset password email sent by Supabase (this URL is configurable in case you'd like to use a different route).&lt;/p&gt;

&lt;p&gt;Previously in &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/blob/v1/src/pages/index.js" rel="noopener noreferrer"&gt;src/pages/index.js&lt;/a&gt;, this page will now be in &lt;code&gt;src/app/page.js&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Profile: &lt;code&gt;/profile&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This is an authenticated &lt;strong&gt;Profile&lt;/strong&gt; page, showing some basic user info for the current user. If no session is found, it will redirect to &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Previously in &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/blob/v1/src/pages/profile.js" rel="noopener noreferrer"&gt;src/pages/profile.js&lt;/a&gt;, this page code will now be in &lt;code&gt;src/app/profile/page.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And that's it as far as page routes go.&lt;/p&gt;

&lt;p&gt;Note that in Next 13, pages are &lt;a href="https://beta.nextjs.org/docs/rendering/server-and-client-components" rel="noopener noreferrer"&gt;Server Components&lt;/a&gt; by default, but can be set to &lt;a href="https://beta.nextjs.org/docs/rendering/server-and-client-components#client-components" rel="noopener noreferrer"&gt;Client Components&lt;/a&gt; via the &lt;code&gt;'use client'&lt;/code&gt; directive. More on this and how it impacts our code a bit later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Layout
&lt;/h3&gt;

&lt;p&gt;In the previous solution, we built our own &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/tree/v1/src/components/Layout.js" rel="noopener noreferrer"&gt;Layout&lt;/a&gt; component, and used it as the top-level wrapper for each individual page, ie:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/components/Layout&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;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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/** Page content */&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;Layout&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;With Next 13 and the &lt;code&gt;app&lt;/code&gt; directory, this can now be done using &lt;a href="https://beta.nextjs.org/docs/routing/pages-and-layouts" rel="noopener noreferrer"&gt;shared layouts&lt;/a&gt; ✨&lt;/p&gt;

&lt;p&gt;Since we only have a single layout shared across the whole app, we can just create a single root &lt;code&gt;layout.js&lt;/code&gt; file in &lt;code&gt;src/app&lt;/code&gt;, which will be shared by all children routes and pages. We'll call this &lt;code&gt;RootLayout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using the existing &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/tree/v1/src/components/Layout.js" rel="noopener noreferrer"&gt;Layout&lt;/a&gt; component as our starting point, create &lt;code&gt;src/app/layout.js&lt;/code&gt; and paste the following (feel free to adjust styling as needed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/layout.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/styles/globals.css&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;default&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;RootLayout&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&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;"flex min-h-screen flex-col items-center justify-center py-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&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;"flex w-full flex-1 shrink-0 flex-col items-center justify-center px-8 text-center sm:px-20"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&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;"mb-12 text-5xl font-bold sm:text-6xl"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              Next.js with &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&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;"font-black text-green-400"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Supabase&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how we need to include &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tags here as well. If you'd like to think of it in terms of the old &lt;code&gt;pages&lt;/code&gt; directory, the root &lt;code&gt;layout.js&lt;/code&gt; essentially combines the concepts of &lt;code&gt;_app.js&lt;/code&gt; and &lt;code&gt;_document.js&lt;/code&gt; together into one.&lt;/p&gt;

&lt;p&gt;One big benefit of a root layout is that state is preserved on route changes, and the layout doesn't unnecessarily rerender. Layouts can also be nested, though we won't be needing that in this project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT:&lt;/strong&gt; Root layout is a Server Component by default, and can &lt;strong&gt;NOT&lt;/strong&gt; be set to a Client Component. Any parts of your layout that require interactivity will need to be moved into separate Client Components (which can be marked with the &lt;code&gt;'use client'&lt;/code&gt; directive).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Read more on this in &lt;a href="https://nextjs.org/docs/getting-started/react-essentials#moving-client-components-to-the-leaves" rel="noopener noreferrer"&gt;"moving Client Components to the leaves"&lt;/a&gt; in Next.js docs for additional information.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Auth Provider
&lt;/h3&gt;

&lt;p&gt;To handle our auth-related logic on the client side, we need an &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12#authentication-provider"&gt;AuthProvider&lt;/a&gt;, which is essentially a React &lt;a href="https://reactjs.org/docs/context.html" rel="noopener noreferrer"&gt;context&lt;/a&gt; provider.&lt;/p&gt;

&lt;p&gt;This component is a top-level wrapper in our application, providing things like &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;session&lt;/code&gt; objects, &lt;code&gt;signOut&lt;/code&gt; method and a &lt;code&gt;useAuth&lt;/code&gt; hook to its children components.&lt;/p&gt;

&lt;p&gt;Previously found in the &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/blob/v1/src/lib/auth.js" rel="noopener noreferrer"&gt;&lt;code&gt;src/lib/auth.js&lt;/code&gt;&lt;/a&gt; file in the original implementation, we'll move this to &lt;code&gt;src/components/AuthProvider.js&lt;/code&gt; to keep our folder and naming structure consistent. For now, keep all of the existing code - we'll update it as we go along.&lt;/p&gt;

&lt;p&gt;In the original implementation, this component was used in the &lt;code&gt;_app.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/_app.js&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AuthProvider&lt;/span&gt; &lt;span class="na"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the move to &lt;code&gt;app&lt;/code&gt; directory, we'll need to find it a new home. Considering that this will be shared by all pages, the best place for it is in the &lt;code&gt;RootLayout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;src/app/layout.js&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/layout.js&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;AuthProvider&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="s1"&gt;src/components/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;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/styles/globals.css&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;default&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;RootLayout&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&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;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important thing to note from Next.js &lt;a href="https://beta.nextjs.org/docs/rendering/server-and-client-components#context" rel="noopener noreferrer"&gt;beta docs&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In Next.js 13, context is fully supported within Client Components, but it cannot be created or consumed directly within Server Components. This is because Server Components have no React state (since they're not interactive), and context is primarily used for rerendering interactive components deep in the tree after some React state has been updated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Given the above, we'll need to make &lt;code&gt;AuthProvider&lt;/code&gt; a Client Component, since it uses React context.&lt;/p&gt;

&lt;p&gt;To do this, add &lt;code&gt;'use client'&lt;/code&gt; at the very top of the &lt;code&gt;src/components/AuthProvider.js&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;'use client';

import { createContext, useContext, useEffect, useMemo, useState } from 'react';

// ...

export const AuthProvider = (props) =&amp;gt; {
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that even though &lt;code&gt;AuthProvider&lt;/code&gt; is now a Client Component, it can still be imported and used in the &lt;code&gt;RootLayout&lt;/code&gt; (which is a Server Component).&lt;/p&gt;

&lt;h3&gt;
  
  
  Middleware
&lt;/h3&gt;

&lt;p&gt;Next.js &lt;a href="https://nextjs.org/docs/advanced-features/middleware" rel="noopener noreferrer"&gt;middleware&lt;/a&gt; is used to run code before a request is completed, and can be configured to run that code only on specific routes. From Supabase docs we learn that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Since we don't have access to set cookies or headers from Server Components, we need to create a Middleware Supabase client and refresh the user's session by calling &lt;code&gt;getSession()&lt;/code&gt;. Any Server Component route that uses a Supabase client must be added to this middleware's &lt;code&gt;matcher&lt;/code&gt; array. Without this, the Server Component may try to make a request to Supabase with an expired &lt;code&gt;access_token&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, we'll need to add Next.js middleware in our app. Create a &lt;code&gt;middleware.js&lt;/code&gt; file at the root of our &lt;code&gt;src&lt;/code&gt; folder, and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createMiddlewareSupabaseClient } from '@supabase/auth-helpers-nextjs';
import { NextResponse } from 'next/server';

export async function middleware(req) {
  const res = NextResponse.next();

  const supabase = createMiddlewareSupabaseClient({ req, res });

  const {
    data: { session },
  } = await supabase.auth.getSession();

  return res;
}

export const config = {
  matcher: ['/profile'],
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we're using the &lt;code&gt;createMiddlewareSupabaseClient()&lt;/code&gt; function from the &lt;strong&gt;Next.js Auth Helpers&lt;/strong&gt; to create a middleware Supabase client, and we're also configuring the &lt;code&gt;matcher&lt;/code&gt; array to run this code on the &lt;code&gt;/profile&lt;/code&gt; route, as that's the only route using Server Components in our case. If you have additional routes utilizing Server Components, you'll need to specify them here as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating to Supabase v2
&lt;/h2&gt;

&lt;p&gt;With the core of our &lt;code&gt;app&lt;/code&gt; code now in place, it's time to make some updates.&lt;/p&gt;

&lt;p&gt;There were a few methods deprecated in Supabase v2, so we'll need to update how we use those in our &lt;code&gt;AuthProvider&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Session Listener
&lt;/h3&gt;

&lt;p&gt;If you recall, we have a &lt;code&gt;useEffect&lt;/code&gt; inside our &lt;code&gt;AuthProvider&lt;/code&gt; that retrieves the current session, as well as an event listener for any auth events fired by Supabase client.&lt;/p&gt;

&lt;p&gt;The methods for these have changed in Supabase &lt;strong&gt;v2&lt;/strong&gt;, so we'll need to update how they're used.&lt;/p&gt;

&lt;p&gt;First, remove the deprecated &lt;code&gt;session()&lt;/code&gt; method and use &lt;a href="https://supabase.com/docs/reference/javascript/auth-getsession" rel="noopener noreferrer"&gt;getSession()&lt;/a&gt; instead.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because this new method returns a Promise, we need to call it from within an async function in our &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create an async &lt;code&gt;getActiveSession&lt;/code&gt; method, and invoke it from within the &lt;code&gt;useEffect&lt;/code&gt;. In the &lt;code&gt;AuthProvider&lt;/code&gt; component, update the &lt;code&gt;useEffect&lt;/code&gt; from this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  const activeSession = supabase.auth.session();
  setSession(activeSession);
  setUser(activeSession?.user ?? null);
  // ...
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  async function getActiveSession() {
    const {
      data: { session: activeSession },
    } = await supabase.auth.getSession();
    setSession(activeSession);
    setUser(activeSession?.user ?? null);
  }
  getActiveSession();
  // ...
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to update the &lt;code&gt;onAuthStateChange&lt;/code&gt; handler.&lt;/p&gt;

&lt;p&gt;To get the &lt;code&gt;authListener&lt;/code&gt; for our effect cleanup, we now need to read it from &lt;code&gt;data.subscription&lt;/code&gt; in the returned object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  // ...
  const {
    data: { subscription: authListener },
  } = supabase.auth.onAuthStateChange((event, currentSession) =&amp;gt; {
    setSession(currentSession);
    setUser(currentSession?.user ?? null);
  });
  // ...
  return () =&amp;gt; {
    authListener?.unsubscribe();
  };
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Managing Cookies
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;setAuthCookie&lt;/code&gt; and &lt;code&gt;getUserByCookie&lt;/code&gt; methods have also been deprecated. Recommended solution for managing cookies in Next.js is now the &lt;a href="https://supabase.com/docs/guides/auth/auth-helpers/nextjs" rel="noopener noreferrer"&gt;Next.js Auth Helpers&lt;/a&gt; library, which we had installed earlier. We'll be using that alongside Next.js middleware (more on that below).&lt;/p&gt;

&lt;p&gt;This means that we won't need to manually create or delete a cookie whenever auth state changes, and the &lt;code&gt;/api/auth&lt;/code&gt; API routes are no longer required. We can delete &lt;code&gt;pages/api/auth&lt;/code&gt; altogether, and remove the fetch call to &lt;code&gt;/api/auth&lt;/code&gt; in our &lt;code&gt;onAuthStateChange&lt;/code&gt; handler as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  // ...
  const { data: authListener } = supabase.auth.onAuthStateChange(
    (event, currentSession) =&amp;gt; {
      // fetch('/api/auth', {
      //   method: 'POST',
      //   headers: new Headers({ 'Content-Type': 'application/json' }),
      //   credentials: 'same-origin',
      //   body: JSON.stringify({ event, session: currentSession }),
      // }).then((res) =&amp;gt; res.json());
    }
  );
  //...
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; in &lt;code&gt;AuthProvider&lt;/code&gt; should now look 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;//...
useEffect(() =&amp;gt; {
    async function getActiveSession() {
      const {
        data: { session: activeSession },
      } = await supabase.auth.getSession();
      setSession(activeSession);
      setUser(activeSession?.user ?? null);
    }
    getActiveSession();

    const {
      data: { subscription: authListener },
    } = supabase.auth.onAuthStateChange((event, currentSession) =&amp;gt; {
      setSession(currentSession);
      setUser(currentSession?.user ?? null);

      switch (event) {
        case EVENTS.PASSWORD_RECOVERY:
          setView(VIEWS.UPDATE_PASSWORD);
          break;
        case EVENTS.SIGNED_OUT:
        case EVENTS.USER_UPDATED:
          setView(VIEWS.SIGN_IN);
          break;
        default:
      }
    });

    return () =&amp;gt; {
      authListener?.unsubscribe();
    };
  }, []);
// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Auth Component
&lt;/h3&gt;

&lt;p&gt;With Supabase setup, and &lt;code&gt;AuthProvider&lt;/code&gt; updated to use Supabase &lt;strong&gt;v2&lt;/strong&gt;, it's time to build our authentications forms. This is what will replace the &lt;a href="https://ui.supabase.io/components/auth" rel="noopener noreferrer"&gt;Auth&lt;/a&gt; component from the (now deprecated) &lt;a href="https://github.com/supabase/ui" rel="noopener noreferrer"&gt;Supabase UI&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;Let's make each form an individual component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sign In&lt;/strong&gt;: &lt;code&gt;SignIn.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign Up&lt;/strong&gt;: &lt;code&gt;SignUp.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reset Password&lt;/strong&gt;: &lt;code&gt;ResetPassword.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update Password&lt;/strong&gt;: &lt;code&gt;UpdatePassword.js&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, create a parent &lt;code&gt;Auth&lt;/code&gt; component that will display the corresponding screen based on the current &lt;code&gt;view&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;'use client';

import { useAuth, VIEWS } from 'src/components/AuthProvider';

import ResetPassword from './ResetPassword';
import SignIn from './SignIn';
import SignUp from './SignUp';
import UpdatePassword from './UpdatePassword';

const Auth = ({ view: initialView }) =&amp;gt; {
  let { view } = useAuth();

  if (initialView) {
    view = initialView;
  }

  switch (view) {
    case VIEWS.UPDATE_PASSWORD:
      return &amp;lt;UpdatePassword /&amp;gt;;
    case VIEWS.FORGOTTEN_PASSWORD:
      return &amp;lt;ResetPassword /&amp;gt;;
    case VIEWS.SIGN_UP:
      return &amp;lt;SignUp /&amp;gt;;
    default:
      return &amp;lt;SignIn /&amp;gt;;
  }
};

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

&lt;/div&gt;



&lt;p&gt;Here, we're checking the value of &lt;code&gt;view&lt;/code&gt; from our &lt;code&gt;AuthProvider&lt;/code&gt; via the &lt;code&gt;useAuth()&lt;/code&gt; hook, and display the corresponding component for the given auth flow. The &lt;code&gt;Auth&lt;/code&gt; component also accepts an optional &lt;code&gt;view&lt;/code&gt; prop, in case we need to manually override it (as is the case with "Update Password" flow, but more on that later).&lt;/p&gt;

&lt;p&gt;The individual forms all follow the same basic structure, which looks like this for &lt;strong&gt;Sign In&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;'use client';

import { useState } from 'react';
import cn from 'classnames';
import { Field, Form, Formik } from 'formik';
import * as Yup from 'yup';

import { useAuth, VIEWS } from 'src/components/AuthProvider';
import supabase from 'src/lib/supabase-browser';

const SignInSchema = Yup.object().shape({
  email: Yup.string().email('Invalid email').required('Required'),
  password: Yup.string().required('Required'),
});

const SignIn = () =&amp;gt; {
  const { setView } = useAuth();
  const [errorMsg, setErrorMsg] = useState(null);

  async function signIn(formData) {
    const { error } = await supabase.auth.signInWithPassword({
      email: formData.email,
      password: formData.password,
    });

    if (error) {
      setErrorMsg(error.message);
    }
  }

  return (
    &amp;lt;div className="card"&amp;gt;
      &amp;lt;h2 className="w-full text-center"&amp;gt;Sign In&amp;lt;/h2&amp;gt;
      &amp;lt;Formik
        initialValues={{
          email: '',
          password: '',
        }}
        validationSchema={SignInSchema}
        onSubmit={signIn}
      &amp;gt;
        {({ errors, touched }) =&amp;gt; (
          &amp;lt;Form className="column w-full"&amp;gt;
            &amp;lt;label htmlFor="email"&amp;gt;Email&amp;lt;/label&amp;gt;
            &amp;lt;Field
              className={cn('input', errors.email &amp;amp;&amp;amp; touched.email &amp;amp;&amp;amp; 'bg-red-50')}
              id="email"
              name="email"
              placeholder="jane@acme.com"
              type="email"
            /&amp;gt;
            {errors.email &amp;amp;&amp;amp; touched.email ? (
              &amp;lt;div className="text-red-600"&amp;gt;{errors.email}&amp;lt;/div&amp;gt;
            ) : null}

            &amp;lt;label htmlFor="email"&amp;gt;Password&amp;lt;/label&amp;gt;
            &amp;lt;Field
              className={cn('input', errors.password &amp;amp;&amp;amp; touched.password &amp;amp;&amp;amp; 'bg-red-50')}
              id="password"
              name="password"
              type="password"
            /&amp;gt;
            {errors.password &amp;amp;&amp;amp; touched.password ? (
              &amp;lt;div className="text-red-600"&amp;gt;{errors.password}&amp;lt;/div&amp;gt;
            ) : null}

            &amp;lt;button
              className="link w-full"
              type="button"
              onClick={() =&amp;gt; setView(VIEWS.FORGOTTEN_PASSWORD)}
            &amp;gt;
              Forgot your password?
            &amp;lt;/button&amp;gt;

            &amp;lt;button className="button-inverse w-full" type="submit"&amp;gt;
              Submit
            &amp;lt;/button&amp;gt;
          &amp;lt;/Form&amp;gt;
        )}
      &amp;lt;/Formik&amp;gt;
      {errorMsg &amp;amp;&amp;amp; &amp;lt;div className="text-red-600"&amp;gt;{errorMsg}&amp;lt;/div&amp;gt;}
      &amp;lt;button
        className="link w-full"
        type="button"
        onClick={() =&amp;gt; setView(VIEWS.SIGN_UP)}
      &amp;gt;
        Don&amp;amp;apos;t have an account? Sign Up.
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

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

&lt;/div&gt;



&lt;p&gt;Here, we're using &lt;a href="https://formik.org" rel="noopener noreferrer"&gt;Formik&lt;/a&gt; to build out the form, and &lt;a href="https://github.com/jquense/yup" rel="noopener noreferrer"&gt;Yup&lt;/a&gt; for schema validation (as &lt;a href="https://formik.org/docs/guides/validation#validationschema" rel="noopener noreferrer"&gt;recommended&lt;/a&gt; by Formik). The same pattern is applied for all forms.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Check out the full &lt;strong&gt;Formik&lt;/strong&gt; &lt;a href="https://formik.org/docs/tutorial" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt; for more details on how it works.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Similarly, the remaining auth flows are also implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/blob/main/src/components/Auth/SignUp.js" rel="noopener noreferrer"&gt;SignUp.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/blob/main/src/components/Auth/ResetPassword.js" rel="noopener noreferrer"&gt;ResetPassword.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/blob/main/src/components/Auth/UpdatePassword.js" rel="noopener noreferrer"&gt;UpdatePassword.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the linked files for reference.&lt;/p&gt;

&lt;p&gt;We'll put all these in the &lt;code&gt;src/components/Auth&lt;/code&gt; folder, where &lt;code&gt;index.js&lt;/code&gt; is the parent &lt;code&gt;Auth&lt;/code&gt; component, and then each individual form is a separate component file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
└── components/
    └── Auth/
        ├── index.js
        ├── ResetPassword.js
        ├── SignIn.js
        ├── SignUp.js
        └── UpdatePassword.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Code for the complete &lt;code&gt;Auth&lt;/code&gt; component can be found in &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/blob/main/src/components/Auth/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; for your reference.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Updating Pages
&lt;/h2&gt;

&lt;p&gt;With the new &lt;code&gt;Auth&lt;/code&gt; component in place, it's time to update our page code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Home
&lt;/h3&gt;

&lt;p&gt;Our &lt;strong&gt;Home&lt;/strong&gt; page will use the original code from &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/blob/v1/src/pages/index.js" rel="noopener noreferrer"&gt;src/pages/index.js&lt;/a&gt; as the starting point. And there really isn't much to change!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We're still using the &lt;code&gt;useAuth&lt;/code&gt; hook, and reading &lt;code&gt;view&lt;/code&gt;, &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;signOut&lt;/code&gt; from it&lt;/li&gt;
&lt;li&gt;Thanks to the new shared layout, we don't need the &lt;code&gt;Layout&lt;/code&gt; wrapper anymore&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Auth&lt;/code&gt; component API is a bit simplified, as it doesn't require the Supabase client to be passed to it anymore (that's done internally in the component)&lt;/li&gt;
&lt;li&gt;The imports for &lt;code&gt;AuthProvider&lt;/code&gt; and &lt;code&gt;Auth&lt;/code&gt; will also need to be updated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With all said, the &lt;code&gt;Home&lt;/code&gt; page should look something 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;import Link from 'next/link';

import Auth from 'src/components/Auth';
import { useAuth, VIEWS } from 'src/components/AuthProvider';

export default function Home() {
  const { user, view, signOut } = useAuth();

  if (view === VIEWS.UPDATE_PASSWORD) {
    return &amp;lt;Auth view={view} /&amp;gt;;
  }

  if (user) {
    return (
      &amp;lt;div className="card"&amp;gt;
        &amp;lt;h2&amp;gt;Welcome!&amp;lt;/h2&amp;gt;
        &amp;lt;code className="highlight"&amp;gt;{user.role}&amp;lt;/code&amp;gt;
        &amp;lt;Link className="button" href="/profile"&amp;gt;
          Go to Profile
        &amp;lt;/Link&amp;gt;
        &amp;lt;button type="button" className="button-inverse" onClick={signOut}&amp;gt;
          Sign Out
        &amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }

  return &amp;lt;Auth view={view} /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As before, we are showing the &lt;code&gt;Auth&lt;/code&gt; component if no &lt;code&gt;user&lt;/code&gt; is found in the current session, or a simple authenticated view with a link to &lt;code&gt;/profile&lt;/code&gt; and a &lt;strong&gt;Sign Out&lt;/strong&gt; button otherwise.&lt;/p&gt;

&lt;p&gt;Note also that we are rendering the &lt;code&gt;Auth&lt;/code&gt; component first if the &lt;code&gt;view&lt;/code&gt; is &lt;code&gt;UPDATE_PASSWORD&lt;/code&gt;, which means that a user has been redirected to here after clicking the link in Supabase &lt;strong&gt;Reset Password&lt;/strong&gt; email.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; It's important that this is returned for the &lt;code&gt;UPDATE_PASSWORD&lt;/code&gt; view regardless if there's an active &lt;code&gt;user&lt;/code&gt;, as the email link passes an &lt;code&gt;access_token&lt;/code&gt; along with the URL and Supabase client creates a &lt;code&gt;session&lt;/code&gt; with this token. So we're basically in an "authenticated" state during the Update Password flow, and if we check for a &lt;code&gt;user&lt;/code&gt; first, the home page will always show the authenticated view without giving our user ability to update their password.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is essentially the same behaviour as we had in the &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12#reset-password"&gt;original solution&lt;/a&gt;, but updated to use the new &lt;code&gt;Auth&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Now, if we try to run the app and go to the Home page in its current state, we'll get an error like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fwebpack-error.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fwebpack-error.png" alt="Home: Error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As mentioned earlier, in Next 13 pages are &lt;a href="https://beta.nextjs.org/docs/rendering/server-and-client-components" rel="noopener noreferrer"&gt;Server Components&lt;/a&gt; by default when using the &lt;code&gt;app&lt;/code&gt; dir. This means that our &lt;code&gt;AuthProvider&lt;/code&gt;, which is a &lt;a href="https://beta.nextjs.org/docs/rendering/server-and-client-components#client-components" rel="noopener noreferrer"&gt;Client Component&lt;/a&gt;, cannot be consumed within the &lt;strong&gt;Home&lt;/strong&gt; page in its current state.&lt;/p&gt;

&lt;p&gt;If we look at the error a bit closer we'll see that the &lt;code&gt;useAuth&lt;/code&gt; hook is the culprit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&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;view&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;=&lt;/span&gt; &lt;span class="nf"&gt;useAuth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix this, we need to make &lt;code&gt;Home&lt;/code&gt; a Client Component. As before, add &lt;code&gt;'use client'&lt;/code&gt; at the very top of the &lt;code&gt;src/app/page.js&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;'use client';

import Link from 'next/link';

import Auth from 'src/components/Auth';
import { useAuth, VIEWS } from 'src/components/AuthProvider';

export default function Home() {
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we run the app again, we should see the &lt;code&gt;Auth&lt;/code&gt; component rendered:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fsign-in.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fsign-in.png" alt="Home page: Sign In view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking on "Forgot password" or "Sign Up" text will set &lt;code&gt;view&lt;/code&gt; to the corresponding screen (this is implemented internally in the &lt;code&gt;Auth&lt;/code&gt; component, by calling &lt;code&gt;setView&lt;/code&gt; from the &lt;code&gt;AuthProvider&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Let's go ahead and either &lt;strong&gt;Sign In&lt;/strong&gt; or &lt;strong&gt;Sign Up&lt;/strong&gt;. These flows behave &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12#authentication-flows"&gt;the same as before&lt;/a&gt;, and if successful we should see the authenticated part of our &lt;strong&gt;Home&lt;/strong&gt; page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fhome.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fhome.png" alt="Home page: Authenticated view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The view rerendered because &lt;code&gt;Home&lt;/code&gt; page is a &lt;strong&gt;Client Component&lt;/strong&gt; and is nested within the &lt;code&gt;AuthProvider&lt;/code&gt; (also a Client Component). As we had &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12#handling-auth-state-change"&gt;previously done&lt;/a&gt;, the &lt;code&gt;onAuthStateChange&lt;/code&gt; listener will listen for auth event changes, and &lt;a href="https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12#switching-auth-views"&gt;update the &lt;code&gt;view&lt;/code&gt;&lt;/a&gt; in the state, thereby triggering a rerender in relevant components (the &lt;code&gt;Home&lt;/code&gt; page in this case).&lt;/p&gt;

&lt;h3&gt;
  
  
  Profile
&lt;/h3&gt;

&lt;p&gt;For the &lt;strong&gt;Profile&lt;/strong&gt; page, we'll be starting off with &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth/blob/v1/src/pages/index.js" rel="noopener noreferrer"&gt;src/pages/index.js&lt;/a&gt; as our base.&lt;/p&gt;

&lt;p&gt;We'll keep this page as a &lt;strong&gt;Server Component&lt;/strong&gt; (default in Next 13), which means that we can call API's and server-side methods directly in the component. So any calls made within &lt;code&gt;getServerSideProps&lt;/code&gt; before can now be done directly in the component.&lt;/p&gt;

&lt;p&gt;This is also where we use the Supabase &lt;strong&gt;Server Component&lt;/strong&gt; client we had created in &lt;code&gt;src/lib/supabase-server&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following to &lt;code&gt;src/app/profile/page.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Link from 'next/link';
import { redirect } from 'next/navigation';

import createClient from 'src/lib/supabase-server';

export default async function Profile() {
  const supabase = createClient();

  const {
    data: { user },
  } = await supabase.auth.getUser();

  if (!user) {
    redirect('/');
  }

  return (
    &amp;lt;div className="card"&amp;gt;
      &amp;lt;h2&amp;gt;User Profile&amp;lt;/h2&amp;gt;
      &amp;lt;code className="highlight"&amp;gt;{user.email}&amp;lt;/code&amp;gt;
      &amp;lt;div className="heading"&amp;gt;Last Signed In:&amp;lt;/div&amp;gt;
      &amp;lt;code className="highlight"&amp;gt;{new Date(user.last_sign_in_at).toUTCString()}&amp;lt;/code&amp;gt;
      &amp;lt;Link className="button" href="/"&amp;gt;
        Go Home
      &amp;lt;/Link&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break this down a bit.&lt;/p&gt;

&lt;p&gt;As noted earlier, the &lt;code&gt;getUserByCookie&lt;/code&gt; method was deprecated. We can now &lt;a href="https://supabase.com/docs/reference/javascript/auth-getuser" rel="noopener noreferrer"&gt;get the current user&lt;/a&gt; with the &lt;code&gt;getUser()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default async function Profile() {
  const supabase = createClient();

  const {
    data: { user },
  } = await supabase.auth.getUser();
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that because &lt;code&gt;getUser()&lt;/code&gt; is an async method, we need to make &lt;code&gt;Profile&lt;/code&gt; and asynchronous component as well. Keep this in mind as we continue.&lt;/p&gt;

&lt;p&gt;Next, we check if there's a valid &lt;code&gt;user&lt;/code&gt;, and if there isn't - redirect user back to &lt;strong&gt;Home&lt;/strong&gt; using the &lt;a href="https://beta.nextjs.org/docs/api-reference/redirect" rel="noopener noreferrer"&gt;redirect&lt;/a&gt; function from Next.js. This keeps the &lt;strong&gt;Profile&lt;/strong&gt; page protected, and only allow authenticated users to access it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; &lt;code&gt;redirect()&lt;/code&gt; can only be called as part of rendering and not as part of event handlers (&lt;a href="https://github.com/vercel/next.js/issues/42556#issuecomment-1328859648" rel="noopener noreferrer"&gt;source&lt;/a&gt;). This means you can't use &lt;code&gt;redirect&lt;/code&gt; within a button's &lt;code&gt;onClick&lt;/code&gt; handler, for example.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's run our app, and make sure everything works as expected. If signed in, we should see our &lt;strong&gt;Profile&lt;/strong&gt; page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fprofile-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fprofile-1.png" alt="Profile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything works great!&lt;/p&gt;

&lt;p&gt;But let's say we want to add a "Sign Out" button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fprofile-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fprofile-2.png" alt="Profile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This button will need an &lt;code&gt;onClick&lt;/code&gt; handler, which means that we can't use it directly in the &lt;code&gt;Profile&lt;/code&gt; as that's a &lt;strong&gt;Server Component&lt;/strong&gt;. We'll need to make this button into a separate &lt;strong&gt;Client Component&lt;/strong&gt;, which can then be imported and used in the &lt;code&gt;Profile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's put this tiny component in &lt;code&gt;src/components/SignOut.js&lt;/code&gt;. Upon clicking the button, it'll call the &lt;code&gt;signOut()&lt;/code&gt; method from our &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 plaintext"&gt;&lt;code&gt;'use client';

import { useAuth } from './AuthProvider';

export default function SignOut() {
  const { signOut } = useAuth();

  async function handleSignOut() {
    const { error } = await signOut();

    if (error) {
      console.error('ERROR signing out:', error);
    }
  }

  return (
    &amp;lt;button type="button" className="button-inverse" onClick={handleSignOut}&amp;gt;
      Sign Out
    &amp;lt;/button&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add it to the &lt;strong&gt;Profile&lt;/strong&gt; page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import SignOut from 'src/components/SignOut';

export default async function Profile() {
  // ...
  return (
    &amp;lt;div className="card"&amp;gt;
      {/** ... */}
      &amp;lt;Link className="button" href="/"&amp;gt;
        Go Home
      &amp;lt;/Link&amp;gt;
      &amp;lt;SignOut /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when user presses the button, they'll be signed out and &lt;code&gt;session&lt;/code&gt; cleared. But there's one problem.&lt;/p&gt;

&lt;p&gt;You see, since &lt;code&gt;Profile&lt;/code&gt; is a &lt;strong&gt;Server Component&lt;/strong&gt;, any updates in the &lt;code&gt;AuthProvider&lt;/code&gt; state don't cause it to rerender. This also means that any changes in Supabase auth state (ie. user signing out) don't trigger a rerender either, and so our UI doesn't reflect the change in the auth state. We need a different way of handling this, compared to &lt;strong&gt;Client Components&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syncing-up Server and Client states
&lt;/h2&gt;

&lt;p&gt;Our problem is that after a user signs out, our UI (ie. the rendered &lt;strong&gt;Server Component&lt;/strong&gt;) and server state are no longer in sync. In order for them to be in sync, we need to rerender our page.&lt;/p&gt;

&lt;p&gt;One way of doing that is to simply reload the page. In fact, if you reload the browser on &lt;code&gt;/profile&lt;/code&gt; again, it should redirect you back to &lt;strong&gt;Home&lt;/strong&gt;, as intended. Understandably, we shouldn't be relying solely on users manually refreshing their browser window to update our UI state.&lt;/p&gt;

&lt;p&gt;Thanks to the new router in Next 13, we can use the &lt;a href="https://beta.nextjs.org/docs/api-reference/use-router" rel="noopener noreferrer"&gt;useRouter&lt;/a&gt; hook and call the &lt;code&gt;router.refresh()&lt;/code&gt; method to trigger a route refresh when there is no longer a valid user in the session.&lt;/p&gt;

&lt;p&gt;But how do we know if the session is no longer valid on the server side? A-ha! For this, we'll need to check whether our client and server sessions match.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;AuthProvider&lt;/code&gt;, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ...
import { useRouter } from 'next/navigation';

export const AuthProvider = (props) =&amp;gt; {
  // ...
  const router = useRouter();

  useEffect(() =&amp;gt; {
    // ...
    const {
      data: { subscription: authListener },
    } = supabase.auth.onAuthStateChange((event, currentSession) =&amp;gt; {
      if (currentSession?.access_token !== accessToken) {
        router.refresh();
      }
    });
    // ...
  });
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, whenever the auth state changes, we're checking if the current session's &lt;code&gt;access_token&lt;/code&gt; (on the client) matches the one on the server. If it does not, we trigger a &lt;code&gt;router.refresh()&lt;/code&gt; and our UI state will be updated. The server's access token will be passed as the &lt;code&gt;accessToken&lt;/code&gt; prop.&lt;/p&gt;

&lt;p&gt;So, where should this access token come from? Well, considering that we need to pass it to the &lt;code&gt;AuthProvider&lt;/code&gt; and it needs to be done server-side, we need to fetch it in our &lt;code&gt;RootLayout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following to &lt;code&gt;src/app/layout.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import createClient from 'src/lib/supabase-server';

// ...

export default async function RootLayout({ children }) {
  const supabase = createClient();

  const {
    data: { session },
  } = await supabase.auth.getSession();

  const accessToken = session?.access_token || null;

  return (
    &amp;lt;html lang="en"&amp;gt;
      {/** ... */}
      &amp;lt;AuthProvider accessToken={accessToken}&amp;gt;{children}&amp;lt;/AuthProvider&amp;gt;
      {/** ... */}
    &amp;lt;/html&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will read the current server-side &lt;code&gt;session&lt;/code&gt; and pass its &lt;code&gt;access_token&lt;/code&gt; as the &lt;code&gt;accessToken&lt;/code&gt; prop to the &lt;code&gt;AuthProvider&lt;/code&gt;. Now the auth listener will have something to compare the client-side session to.&lt;/p&gt;

&lt;p&gt;We also don't want our &lt;code&gt;RootLayout&lt;/code&gt; to get cached, so we'll need to change the default &lt;a href="https://beta.nextjs.org/docs/data-fetching/revalidating" rel="noopener noreferrer"&gt;revalidation&lt;/a&gt; behaviour in Next 13 by setting the &lt;a href="https://beta.nextjs.org/docs/api-reference/segment-config#revalidate" rel="noopener noreferrer"&gt;revalidate&lt;/a&gt; option to &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following to &lt;code&gt;src/app/layout.js&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;// ...
export const revalidate = 0;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will ensure that every time a new route is loaded, our &lt;code&gt;session&lt;/code&gt; data in &lt;code&gt;RootLayout&lt;/code&gt; will always be up-to-date.&lt;/p&gt;

&lt;p&gt;Now if go back to the &lt;strong&gt;Profile&lt;/strong&gt; page, and click "Sign Out", we should be redirected to &lt;strong&gt;Home&lt;/strong&gt; page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding loading state
&lt;/h2&gt;

&lt;p&gt;You may have noticed that when going to &lt;strong&gt;Profile&lt;/strong&gt; for the first time, it takes a little bit of time to load. Let's exaggerate it by adding a simple &lt;code&gt;sleep&lt;/code&gt; util in our &lt;code&gt;Profile&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ...
const sleep = (ms) =&amp;gt;
  new Promise((resolve) =&amp;gt; {
    setTimeout(resolve, ms);
  });

export default async function Profile() {
  // ...
  await sleep(2000);

  const {
    data: { user },
  } = await supabase.auth.getUser();
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add a 2-second delay to the &lt;code&gt;getUser()&lt;/code&gt; call. Now that is really noticeable. Let's make this better.&lt;/p&gt;

&lt;p&gt;In Next 13, there is a new concept of a &lt;a href="https://beta.nextjs.org/docs/routing/loading-ui" rel="noopener noreferrer"&gt;Loading UI&lt;/a&gt;, which adds an &lt;strong&gt;instant loading state&lt;/strong&gt; with the help of &lt;a href="https://beta.reactjs.org/apis/react/Suspense" rel="noopener noreferrer"&gt;React Suspense&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using it couldn't be any simpler. Just add a &lt;code&gt;loading.js&lt;/code&gt; file wherever you'd like to create an instant loading state, and specify the UI to show.&lt;/p&gt;

&lt;p&gt;For our &lt;strong&gt;Profile&lt;/strong&gt;, let's add the following to &lt;code&gt;src/app/profile/loading.js&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;export default function Loading() {
  return &amp;lt;div className="card h-72"&amp;gt;Loading...&amp;lt;/div&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when you reload the page (or go to &lt;code&gt;/profile&lt;/code&gt; from the home page), you should see the loading UI almost immediately:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Floading.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Floading.png" alt="Loading UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now that we've verified it works as expected, let's not forget to remove that &lt;code&gt;sleep&lt;/code&gt; call from our &lt;strong&gt;Profile&lt;/strong&gt; page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ...
export default async function Profile() {
  const supabase = createClient();

  const {
    data: { user },
  } = await supabase.auth.getUser();

  if (!user) {
    redirect('/');
  }

  return (
    // ...
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Flash of unauthenticated state
&lt;/h2&gt;

&lt;p&gt;Almost done! But before we wrap up, there is one other thing left to fix.&lt;/p&gt;

&lt;p&gt;Right now, if we have a valid &lt;code&gt;session&lt;/code&gt; and reload the &lt;strong&gt;Home&lt;/strong&gt; page, we'll still see a brief flash of unauthenticated state:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fsign-in-flash.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fsign-in-flash.gif" alt="Flash of Sign In screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This happens because on the very first render the &lt;code&gt;Home&lt;/code&gt; page (which remember is a &lt;strong&gt;Client Component&lt;/strong&gt;) doesn't yet have any &lt;code&gt;session&lt;/code&gt; data from the &lt;code&gt;AuthProvider&lt;/code&gt;, so it returns the &lt;code&gt;&amp;lt;Auth&amp;gt;&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function Home() {
  const { initial, user, view, signOut } = useAuth();
  // ...
  return &amp;lt;Auth view={view} /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This, of course, is desired behaviour when there is no user data found. But we know that our &lt;code&gt;session&lt;/code&gt; data has a valid user - it just so happens to not be available on the first render, since we fetch that data inside a &lt;code&gt;useEffect&lt;/code&gt; in our &lt;code&gt;AuthProvider&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To fix this, we need to be able to differentiate between an "initial" state of our app on the client side - before we check if there's a valid session - and after. This way we'll know whether a valid &lt;code&gt;session&lt;/code&gt; truly doesn't exist, or just hasn't had a chance to load yet.&lt;/p&gt;

&lt;p&gt;Now, if &lt;code&gt;Home&lt;/code&gt; was a &lt;strong&gt;Server Component&lt;/strong&gt;, then we could simply &lt;code&gt;await&lt;/code&gt; the result of &lt;code&gt;getSession()&lt;/code&gt; (like we do in the &lt;code&gt;RootLayout&lt;/code&gt;) and place a Suspense boundary to show a loading state (like we did for the &lt;strong&gt;Profile&lt;/strong&gt; above). But because &lt;code&gt;Home&lt;/code&gt; is a &lt;strong&gt;Client Component&lt;/strong&gt;, that won't work.&lt;/p&gt;

&lt;p&gt;You see, root-level &lt;code&gt;await&lt;/code&gt; is not supported in client-side components, and so we can't "suspend" our &lt;strong&gt;Home&lt;/strong&gt; page until the &lt;code&gt;session&lt;/code&gt; data is available like we do with &lt;strong&gt;Profile&lt;/strong&gt;. React team is working on an &lt;a href="https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md" rel="noopener noreferrer"&gt;RFC&lt;/a&gt; and a new &lt;a href="https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md#example-use-in-client-components-and-hooks" rel="noopener noreferrer"&gt;use&lt;/a&gt; hook that will allow us to conditionally wait for data to load, but it's not quite ready yet. Its use (pardon the pun) is also &lt;a href="https://beta.nextjs.org/docs/data-fetching/fetching#use-in-client-components" rel="noopener noreferrer"&gt;not recommended&lt;/a&gt; by Next itself, as it may cause multiple re-renders in Client Components. Considering all that, we'll need to find an alternative way.&lt;/p&gt;

&lt;p&gt;There are a few ways we could solve this. For example, we could move the "authenticated" portion of our &lt;strong&gt;Home&lt;/strong&gt; page to a new route altogether (e.g. &lt;code&gt;/home&lt;/code&gt;), thereby completely separating the "unathenticated" state. But that would involve a bunch of refactoring of the code we already wrote, and ideally would like to avoid that for this guide. So in the interest of time, we'll go with a bit more "old school" approach.&lt;/p&gt;

&lt;p&gt;One simple way to fix this is to add another state variable in our &lt;code&gt;AuthProvider&lt;/code&gt; that will simply tell us whether our app is loading for the first time or not. We can set its value to &lt;code&gt;true&lt;/code&gt; initially, and once we do the first call to &lt;code&gt;supabase.auth.getSession()&lt;/code&gt; we can set it to &lt;code&gt;false&lt;/code&gt;, indicating that our app has loaded the data.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;AuthProvider&lt;/code&gt;, create an &lt;code&gt;initial&lt;/code&gt; state, and make sure its value is provided:&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 AuthProvider = (props) =&amp;gt; {
  const [initial, setInitial] = useState(true);
  // ...
  useEffect(() =&amp;gt; {
    async function getActiveSession() {
      const {
        data: { session: activeSession },
      } = await supabase.auth.getSession();
      // ...
      setInitial(false);
    }
    getActiveSession();
    // ...
  }, []);
  // ...
  const value = useMemo(() =&amp;gt; {
    return {
      initial,
      session,
      user,
      view,
      setView,
      signOut: () =&amp;gt; supabase.auth.signOut(),
    };
  }, [initial, session, user, view]);

  return &amp;lt;AuthContext.Provider value={value} {...rest} /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can read &lt;code&gt;initial&lt;/code&gt; using the &lt;code&gt;useAuth&lt;/code&gt; hook in our &lt;strong&gt;Home&lt;/strong&gt; page, and while it's value is &lt;code&gt;true&lt;/code&gt;, show our loading state instead of returning the &lt;code&gt;&amp;lt;Auth&amp;gt;&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ...
export default function Home() {
  const { initial, user, view, signOut } = useAuth();

  if (initial) {
    return &amp;lt;div className="card h-72"&amp;gt;Loading...&amp;lt;/div&amp;gt;;
  }
  // ...
  return &amp;lt;Auth view={view} /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now if we reload our &lt;strong&gt;Home&lt;/strong&gt; page, we should see the same kind of loading state that we have in &lt;strong&gt;Profile&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fhome-loading.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Fsupabase-auth-next-13%2Fhome-loading.gif" alt="Home page loading"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a quick and easy way of dealing with this problem, but by no means the only way. Ideally we'd like to use Suspense for this, but until React lands on a more established pattern for it in client-side components, we're not going to focus on it too much. For the time being, this solves our immediate problem in this scenario.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;Well, this about wraps it up. If you've made it this far - thank you for reading! Hopefully this guide gives you a good starting point for using Supabase in your Next 13 project, or at the very least points you in the right direction.&lt;/p&gt;

&lt;p&gt;Make sure to give the new Next.js &lt;a href="https://beta.nextjs.org" rel="noopener noreferrer"&gt;Beta Docs&lt;/a&gt; a read as well, as I've found them to be an invaluable resource for learning some of these new paradigms coming to the world of React.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; The new &lt;a href="https://nextjs.org" rel="noopener noreferrer"&gt;Next.js Docs&lt;/a&gt; have now been updated. Definitely give them a read if you haven't yet.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Reference Materials
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth" rel="noopener noreferrer"&gt;github.com/mryechkin/nextjs-supabase-auth&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Example:&lt;/strong&gt; &lt;a href="https://supabase-auth-next-13.vercel.app" rel="noopener noreferrer"&gt;supabase-auth-next-13.vercel.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt; Beta Docs: &lt;a href="https://beta.nextjs.org" rel="noopener noreferrer"&gt;beta.nextjs.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt; Beta Docs: &lt;a href="https://beta.reactjs.org" rel="noopener noreferrer"&gt;beta.reactjs.org&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; Both &lt;a href="https://react.dev" rel="noopener noreferrer"&gt;React&lt;/a&gt; and &lt;a href="https://nextjs.org" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; docs have since been released.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>supabase</category>
      <category>authentication</category>
      <category>auth</category>
    </item>
    <item>
      <title>Rollup Library Starter</title>
      <dc:creator>Mykhaylo Ryechkin 🇺🇦</dc:creator>
      <pubDate>Wed, 05 Oct 2022 16:47:31 +0000</pubDate>
      <link>https://dev.to/mryechkin/rollup-library-starter-7ab</link>
      <guid>https://dev.to/mryechkin/rollup-library-starter-7ab</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;In this post we'll take a look at how to package your JavaScript library code into a production-ready bundle using &lt;a href="https://rollupjs.org" rel="noopener noreferrer"&gt;Rollup&lt;/a&gt; module bundler. By the end of this tutorial we will have a dual-module format bundle that is ready to be published to NPM, can be consumed in either server or browser environments, and is available in both ESM and CommonJS formats.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Want to learn more about the different module formats? Check out &lt;a href="https://dev.to/blog/javascript-modules"&gt;this post&lt;/a&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The base recipe assumes use of regular JavaScript and is meant for use with React projects, however the basic principles and patterns we'll cover here are not restricted to any one framework, and can be extended to a variety of different projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; If your project uses TypeScript, I would suggest using &lt;a href="https://tsdx.io/" rel="noopener noreferrer"&gt;tsdx&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;First, init your project using &lt;code&gt;npm init&lt;/code&gt;. You should have a &lt;code&gt;package.json&lt;/code&gt; now that looks something like this:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.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="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rollup-library-starter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Starter template for building JS libraries using Rollup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&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;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mykhaylo Ryechkin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&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;You'll also want to add a &lt;code&gt;.gitignore&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;.DS_Store
dist
node_modules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Folder Structure
&lt;/h3&gt;

&lt;p&gt;Our project files will live inside the &lt;code&gt;src&lt;/code&gt; folder, and the example folder structure will look something 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;src/
├── components/
│   ├── Button/
│   │   ├── Button.js
│   │   └── index.js
│   ├── Text/
│   │   ├── Text.js
│   │   └── index.js
│   └── index.js
├── utils/
│   └── index.js
└── index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just an example convention. Ultimately, you can structure it however you'd like. The main thing to remember is every folder will need an &lt;code&gt;index.js&lt;/code&gt; file, including the top-level &lt;code&gt;src&lt;/code&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="c1"&gt;// src/index.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we're simultaneously importing and re-exporting all modules from the &lt;code&gt;components&lt;/code&gt; and &lt;code&gt;utils&lt;/code&gt; folders (each having their own &lt;code&gt;index.js&lt;/code&gt; file). This is where we control what's available from our library for external consumption - anything that's exported will be available to the library consumer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modules
&lt;/h3&gt;

&lt;p&gt;Our library will expose each module as a &lt;strong&gt;named&lt;/strong&gt; module, ie:&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;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&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="s1"&gt;rollup-library-starter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make things easier to maintain, we're putting each module and the related files in its own folder, using the same name as the module (ie. &lt;code&gt;src/components/Button&lt;/code&gt; and &lt;code&gt;src/components/Text&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;We can then further group these modules by category and put all related modules in the same folder (ie. &lt;code&gt;src/components&lt;/code&gt;). Each folder also needs to have its own &lt;code&gt;index.js&lt;/code&gt; file as well:&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;// src/components/index.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&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="s1"&gt;./Button&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="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Text&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="s1"&gt;./Text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we're importing the &lt;code&gt;default&lt;/code&gt; exports of the &lt;code&gt;Button&lt;/code&gt; and &lt;code&gt;Text&lt;/code&gt; modules, and re-exporting them as &lt;code&gt;Button&lt;/code&gt; and &lt;code&gt;Text&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside each of our &lt;code&gt;Button&lt;/code&gt; and &lt;code&gt;Text&lt;/code&gt; folders, we have the main &lt;code&gt;index.js&lt;/code&gt; files, as well as separate component files (&lt;code&gt;Button.js&lt;/code&gt; and &lt;code&gt;Text.js&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Button/Button.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleOnClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Button onClick&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;onClick&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&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="nx"&gt;handleOnClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VARIANT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;PRIMARY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;SECONDARY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secondary&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="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;







&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Button/index.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;VARIANT&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="s1"&gt;./Button&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;default&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;VARIANT&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;Notice the little trick we're doing inside the component &lt;code&gt;index.js&lt;/code&gt; file above:&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;VARIANT&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;Here we're assigning &lt;code&gt;VARIANT&lt;/code&gt; as a property on the main &lt;code&gt;Button&lt;/code&gt; component using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign" rel="noopener noreferrer"&gt;Object.assign()&lt;/a&gt;, which will let us use &lt;code&gt;VARIANT&lt;/code&gt; without having to import it explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="s1"&gt;rollup-library-starter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&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="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="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VARIANT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIMARY&lt;/span&gt;&lt;span class="si"&gt;}&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;This pattern allows us to group related code that normally would be imported together anyway, reducing some verbosity in the import statements.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Text&lt;/code&gt; component is slightly simpler, with just one main &lt;strong&gt;default&lt;/strong&gt; export, which is then re-exported inside &lt;code&gt;index.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Text/Text.js&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;Text&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="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="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monospace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Text/index.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Text&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;default&lt;/span&gt; &lt;span class="nx"&gt;Text&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, in our &lt;code&gt;utils&lt;/code&gt; folder, we have a single &lt;code&gt;index.js&lt;/code&gt; file, with a sample function &lt;code&gt;Greet&lt;/code&gt; exported as a &lt;strong&gt;named&lt;/strong&gt; export:&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;// src/utils/index.js&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;Greet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To export all these modules at the root, make sure they're included in the &lt;code&gt;index.js&lt;/code&gt; file at the top of the &lt;code&gt;src&lt;/code&gt; folder, as we saw earlier:&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;// src/index.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea here is that our main &lt;code&gt;index.js&lt;/code&gt; file will contain all the exported modules within our library, as &lt;strong&gt;named&lt;/strong&gt; exports.&lt;/p&gt;

&lt;p&gt;With that done, time to install our dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling &amp;amp; Dependencies
&lt;/h2&gt;

&lt;p&gt;Now that the base library setup, let's install all the necessary tooling. As mentioned earlier, we'll be using &lt;a href="https://rollupjs.org" rel="noopener noreferrer"&gt;Rollup&lt;/a&gt; as our module bundler (&lt;code&gt;v2&lt;/code&gt; at the time of writing this post):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Rollup is a &lt;strong&gt;module bundler&lt;/strong&gt; for JavaScript which compiles small pieces of code into something larger and more complex, such as a library or application. It uses the new standardized format for code modules included in the ES6 revision of JavaScript, instead of previous idiosyncratic solutions such as CommonJS and AMD. ES modules let you freely and seamlessly combine the most useful individual functions from your favorite libraries. This will eventually be possible natively everywhere, but Rollup lets you do it today.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rollup has an extensive plugin ecosystem, which provides a lot of flexibility in adding specific functionality for a variety of use cases. Check out the awesome curated list &lt;a href="https://github.com/rollup/awesome" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, it can be daunting to figure out which exact plugins to use - and the goal of this article is to provide guidance on what's needed for a majority of bundles that you'll be building. First, we will install all the required dependencies, and then go through what each of them does as we start to configure the steps.&lt;/p&gt;

&lt;p&gt;We'll be using &lt;a href="https://babeljs.io/" rel="noopener noreferrer"&gt;Babel&lt;/a&gt; to transpile our code into JavaScript that all current and older browsers and environments will understand. For this, install &lt;code&gt;@babel/runtime&lt;/code&gt; as a dependency. This will be our only production dependency, and will let Rollup bundle some of the helper functions required for backwards compatibility:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @babel/runtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to install a few Babel plugins, as well as Rollup itself and a number of Rollup plugins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://babeljs.io/docs/babel-plugin-transform-runtime/" rel="noopener noreferrer"&gt;&lt;code&gt;@babel/plugin-transform-runtime&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://babeljs.io/docs/babel-preset-env.html" rel="noopener noreferrer"&gt;&lt;code&gt;@babel/preset-env&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://babeljs.io/docs/babel-preset-react" rel="noopener noreferrer"&gt;&lt;code&gt;@babel/preset-react&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@rollup/plugin-alias" rel="noopener noreferrer"&gt;&lt;code&gt;@rollup/plugin-alias&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rollup/plugins/tree/master/packages/babel" rel="noopener noreferrer"&gt;&lt;code&gt;@rollup/plugin-babel&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@rollup/plugin-commonjs" rel="noopener noreferrer"&gt;&lt;code&gt;@rollup/plugin-commonjs&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@rollup/plugin-node-resolve" rel="noopener noreferrer"&gt;&lt;code&gt;@rollup/plugin-node-resolve&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@rollup/plugin-terser" rel="noopener noreferrer"&gt;&lt;code&gt;@rollup/plugin-terser&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/rollup-plugin-analyzer" rel="noopener noreferrer"&gt;&lt;code&gt;rollup-plugin-analyzer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These should all be &lt;code&gt;devDependencies&lt;/code&gt;, so make sure to add the &lt;code&gt;-D&lt;/code&gt; flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; rollup rollup-plugin-analyzer @rollup/plugin-alias @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-node-resolve @rollup/plugin-terser @babel/plugin-transform-runtime @babel/preset-env @babel/preset-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And lastly, since we're using React in our library, we'll also need to specify &lt;code&gt;react&lt;/code&gt; and &lt;code&gt;react-dom&lt;/code&gt; as peer dependencies in &lt;code&gt;package.json&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.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="nl"&gt;"peerDependencies"&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;"react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^16.14.0 || ^17.0.0 || ^18.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react-dom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^16.14.0 || ^17.0.0 || ^18.2.0"&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;This will ensure that our library doesn't try to include its own copy of React when it's installed, as that can cause all sorts of issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rollup Configuration
&lt;/h2&gt;

&lt;p&gt;To get started with Rollup, we'll need to create a &lt;a href="https://rollupjs.org/guide/en/#using-config-files" rel="noopener noreferrer"&gt;configuration file&lt;/a&gt; at the root of our project, where we specify all the options for bundling, plugins, presets, etc. This file will be the bulk of our work.&lt;/p&gt;

&lt;p&gt;Our library is written using the modern &lt;strong&gt;ESM&lt;/strong&gt; module syntax, however we want our code to be executable in all JavaScript environments. In order to support this, we will ship two distinctly separate bundles as part of our library package: &lt;strong&gt;ESM&lt;/strong&gt; and &lt;strong&gt;CommonJS&lt;/strong&gt; (or CJS).&lt;/p&gt;

&lt;p&gt;Rollup will handle all the transpilation of our code from ESM to CJS, and generate two separate bundles for each format. This will make our library package consumable in both server (Node) and browser environments. We will also need to modify our &lt;code&gt;package.json&lt;/code&gt; to support this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's worthwhile to keep in mind the &lt;a href="https://nodejs.org/api/packages.html#dual-package-hazard" rel="noopener noreferrer"&gt;dual package hazard&lt;/a&gt;, which is explained in the official Node docs. With that said, this pattern has been working great for my team across multiple JS libraries for several years now, and has proven itself in many enterprise-grade production applications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Base Config
&lt;/h3&gt;

&lt;p&gt;First, let's create a file called &lt;code&gt;rollup.config.js&lt;/code&gt; at the root of our project. We will import all the packages and plugins, and then break down what each of them does.&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;// rollup.config.js&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;fileURLToPath&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="s1"&gt;node:url&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;createRequire&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="s1"&gt;node:module&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;alias&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-alias&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;babel&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-babel&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;commonjs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-commonjs&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;nodeResolve&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-node-resolve&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;terser&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-terser&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;analyze&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-plugin-analyzer&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;require&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRequire&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;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;pkg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./package.json&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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Rollup options go here&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;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;config&lt;/code&gt; is where we'll be setting all the different &lt;a href="https://rollupjs.org/guide/en/#big-list-of-options" rel="noopener noreferrer"&gt;options&lt;/a&gt;, as well as plugins and Babel presets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Output Options
&lt;/h3&gt;

&lt;p&gt;We will be generating two bundles, and there are some common output options shared between the two. Let's put these in a variable:&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;// rollup.config.js&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outputOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;named&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;preserveModules&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="na"&gt;banner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/*
 * Rollup Library Starter
 * {@link https://github.com/mryechkin/rollup-library-starter}
 * @copyright Mykhaylo Ryechkin (@mryechkin)
 * @license MIT
 */`&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;Here, we're setting the &lt;code&gt;exports&lt;/code&gt; option to &lt;code&gt;"named"&lt;/code&gt;, because we're exporting everything as named exports. This is intentional, as there can be &lt;a href="https://github.com/rollup/rollup/issues/1961#issuecomment-423037881" rel="noopener noreferrer"&gt;issues&lt;/a&gt; with mixing both default and named patterns of exports at the root of your package, when exporting to CommonJS format. Rollup will also throw a warning when you do that.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;preserveModules&lt;/code&gt; option will tell Rollup to create separate chunks for all modules, using the original module names as file names.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is needed in order for tools like Webpack 5 to be able to successfully &lt;a href="https://rollupjs.org/guide/en/#tree-shaking" rel="noopener noreferrer"&gt;tree-shake&lt;/a&gt; unused imports when consuming our library. We ran into this issue with our component library when we originally moved to Rollup. Enabling this option eliminated issues with tree-shaking for our users, and this pattern has worked well for us since.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lastly, and completely optional, we can add a &lt;code&gt;banner&lt;/code&gt; to each of the generated files. This is a good way to provide some info about our library, and add author attribution.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For all other available options, check out the big list of options &lt;a href="https://rollupjs.org/guide/en/#big-list-of-options" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With these options defined, let's now provide the entry point for our package. This will be the root-level &lt;code&gt;index.js&lt;/code&gt; file, which if you recall containts all of our available modules exported as "named". We will also set our &lt;code&gt;output&lt;/code&gt; options as well:&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;// rollup.config.js&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&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="na"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist/esm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;esm&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="nx"&gt;outputOptions&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="na"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist/cjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cjs&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="nx"&gt;outputOptions&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;Our &lt;code&gt;output&lt;/code&gt; option is an array of objects, one for each of the bundles we'd like to build. Here we specify both &lt;code&gt;esm&lt;/code&gt; and &lt;code&gt;cjs&lt;/code&gt; formats, which output to &lt;code&gt;dist/esm&lt;/code&gt; and &lt;code&gt;dist/cjs&lt;/code&gt; folders respectively. All other shared &lt;code&gt;outputOptions&lt;/code&gt; are provided for both.&lt;/p&gt;

&lt;h3&gt;
  
  
  External Modules
&lt;/h3&gt;

&lt;p&gt;Next, we need to tell Rollup which of the modules used in our code are &lt;code&gt;external&lt;/code&gt; to our library. Together with &lt;a href="https://github.com/rollup/plugins/tree/master/packages/node-resolve" rel="noopener noreferrer"&gt;@rollup/plugin-node-resolve&lt;/a&gt;, this ensures that Rollup doesn't bundle those dependencies into our final bundle. The function &lt;code&gt;makeExternalPredicate()&lt;/code&gt; generates the list of package names specified in &lt;code&gt;dependencies&lt;/code&gt; and &lt;code&gt;peerDependencies&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;. All credit for this and a big thank you goes out to &lt;a href="https://github.com/Andarist" rel="noopener noreferrer"&gt;Mateusz Burzyński&lt;/a&gt; for providing it in &lt;a href="https://github.com/rollup/rollup-plugin-babel/issues/148#issuecomment-399696316" rel="noopener noreferrer"&gt;this issue&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="c1"&gt;// rollup.config.js&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;makeExternalPredicate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;externalArr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;externalArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="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="nx"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`^(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;externalArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;|&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&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="nx"&gt;id&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;pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;makeExternalPredicate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{}),&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;peerDependencies&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{}),&lt;/span&gt;
    &lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Plugins
&lt;/h3&gt;

&lt;p&gt;Next up, we have the &lt;code&gt;plugins&lt;/code&gt; array, and it specifies which Rollup plugins to run. The order in which plugins are specified is &lt;strong&gt;very important&lt;/strong&gt;, as the input for each plugin is the previous one's output, so make sure to follow the order they're listed in here.&lt;/p&gt;

&lt;h4&gt;
  
  
  Plugin: Alias
&lt;/h4&gt;

&lt;p&gt;The first plugin we're using is &lt;a href="https://www.npmjs.com/package/@rollup/plugin-alias" rel="noopener noreferrer"&gt;&lt;code&gt;@rollup/plugin-alias&lt;/code&gt;&lt;/a&gt;, which enables us to use absolute import paths for &lt;code&gt;src&lt;/code&gt; (or any other path you want to configure):&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;// rollup.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;alias&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-alias&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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;alias&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Plugin: Resolve Node Modules
&lt;/h4&gt;

&lt;p&gt;Next, we have &lt;a href="https://www.npmjs.com/package/@rollup/plugin-node-resolve" rel="noopener noreferrer"&gt;&lt;code&gt;@rollup/plugin-node-resolve&lt;/code&gt;&lt;/a&gt;, which allows Rollup to resolve external modules from &lt;code&gt;node_modules&lt;/code&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="c1"&gt;// rollup.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;nodeResolve&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-node-resolve&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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="c1"&gt;// ...&lt;/span&gt;
      &lt;span class="nf"&gt;nodeResolve&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;h4&gt;
  
  
  Plugin: CommonsJS
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://www.npmjs.com/package/@rollup/plugin-commonjs" rel="noopener noreferrer"&gt;&lt;code&gt;@rollup/plugin-commonjs&lt;/code&gt;&lt;/a&gt; plugin converts 3rd-party CommonJS modules into ES6 code, so that they can be included in our Rollup bundle:&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;// rollup.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;commonjs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-commonjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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="c1"&gt;// ...&lt;/span&gt;
      &lt;span class="nf"&gt;commonjs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;include&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="s1"&gt;node_modules/**&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;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Plugin: Babel
&lt;/h4&gt;

&lt;p&gt;Next, we need to enable Babel for code transpilation. We do that by passing &lt;a href="https://github.com/rollup/plugins/tree/master/packages/babel" rel="noopener noreferrer"&gt;&lt;code&gt;@rollup/plugin-babel&lt;/code&gt;&lt;/a&gt; as a plugin, and then specifying the &lt;code&gt;@babel/plugin-transform-runtime&lt;/code&gt; Babel plugin:&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;// rollup.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;babel&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-babel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;babelRuntimeVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;0-9&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;*/&lt;/span&gt;&lt;span class="p"&gt;,&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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nf"&gt;babel&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/plugin-transform-runtime&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;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;babelRuntimeVersion&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;The &lt;a href="https://babeljs.io/docs/en/babel-plugin-transform-runtime" rel="noopener noreferrer"&gt;&lt;code&gt;@babel/plugin-transform-runtime&lt;/code&gt;&lt;/a&gt; plugin enables re-use of Babel's injected helper code, to help reduce the final bundle size.&lt;/p&gt;

&lt;p&gt;From the plugin's docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Babel uses very small helpers for common functions such as _extend. By default this will be added to every file that requires it. This duplication is sometimes unnecessary, especially when your application is spread out over multiple files.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The version of Babel runtime is pulled from &lt;code&gt;package.json&lt;/code&gt; by reading the &lt;code&gt;dependencies&lt;/code&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="c1"&gt;// rollup.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;babelRuntimeVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;0-9&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're also telling the Babel plugin how to handle Babel helper code via &lt;code&gt;babelHelpers&lt;/code&gt; (it is recommended to use the "runtime" option for bundling libraries with Rollup), as well as not to touch anything imported from &lt;code&gt;node_modules&lt;/code&gt; by setting the &lt;code&gt;exclude&lt;/code&gt; option:&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;// rollup.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;babel&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-babel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nf"&gt;babel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;babelHelpers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/node_modules/&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="c1"&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;We also need to specify a few presets so that we can use latest JavaScript features, as well as enable React support. These are &lt;a href="https://babeljs.io/docs/en/babel-preset-env" rel="noopener noreferrer"&gt;&lt;code&gt;@babel/preset-env&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://babeljs.io/docs/en/babel-preset-react" rel="noopener noreferrer"&gt;&lt;code&gt;@babel/preset-react&lt;/code&gt;&lt;/a&gt;, respectively:&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;// rollup.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;babel&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-babel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nf"&gt;babel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;babelHelpers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/node_modules/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;presets&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-env&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;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;defaults&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-react&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;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;automatic&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;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Plugin: Terser
&lt;/h4&gt;

&lt;p&gt;With Babel configuration out of the way, we only have a few plugins left.&lt;/p&gt;

&lt;p&gt;This next one will help us reduce final bundle size by minifying the generated code. It's called &lt;a href="https://www.npmjs.com/package/@rollup/plugin-terser" rel="noopener noreferrer"&gt;&lt;code&gt;@rollup/plugin-terser&lt;/code&gt;&lt;/a&gt; and uses &lt;a href="https://github.com/terser/terser" rel="noopener noreferrer"&gt;terser&lt;/a&gt; under the hood to minify the code.&lt;/p&gt;

&lt;p&gt;We'll be sticking with the defaults it provides, so no need to specify any options:&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;// rollup.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;terser&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-terser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nf"&gt;terser&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; You may want to comment out this plugin if you're trying to debug your generated code, but you'll definitely want to have it enabled for your production bundle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Plugin: Bundle Analyzer
&lt;/h4&gt;

&lt;p&gt;Lastly, we have &lt;a href="https://github.com/doesdev/rollup-plugin-analyzer" rel="noopener noreferrer"&gt;&lt;code&gt;rollup-plugin-analyzer&lt;/code&gt;&lt;/a&gt;. This plugin will print out some useful info about our generated bundle upon successful builds:&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;// rollup.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;analyze&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-plugin-analyzer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nf"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;hideDeps&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="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;summaryOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Config Summary
&lt;/h3&gt;

&lt;p&gt;And with that, we're done configuring Rollup! Here's what your &lt;code&gt;rollup.config.js&lt;/code&gt; should look like in the end:&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;// rollup.config.js&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;fileURLToPath&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="s1"&gt;node:url&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;createRequire&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="s1"&gt;node:module&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;alias&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-alias&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;babel&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-babel&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;commonjs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-commonjs&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;nodeResolve&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-node-resolve&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;terser&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-terser&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;analyze&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-plugin-analyzer&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;require&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRequire&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;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;pkg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./package.json&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;makeExternalPredicate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;externalArr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;externalArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="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="nx"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`^(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;externalArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;|&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&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="nx"&gt;id&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;pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;babelRuntimeVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;0-9&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;*/&lt;/span&gt;&lt;span class="p"&gt;,&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;outputOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;named&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;preserveModules&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="na"&gt;banner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/*
 * Rollup Library Starter
 * {@link https://github.com/mryechkin/rollup-library-starter}
 * @copyright Mykhaylo Ryechkin (@mryechkin)
 * @license MIT
 */`&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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&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="na"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist/esm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;esm&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="nx"&gt;outputOptions&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="na"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist/cjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cjs&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="nx"&gt;outputOptions&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="na"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;makeExternalPredicate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{}),&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;peerDependencies&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{}),&lt;/span&gt;
  &lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="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;alias&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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="nf"&gt;nodeResolve&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;commonjs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;include&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="s1"&gt;node_modules/**&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;babel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;babelHelpers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/node_modules/&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/plugin-transform-runtime&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;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;babelRuntimeVersion&lt;/span&gt; &lt;span class="p"&gt;}]],&lt;/span&gt;
      &lt;span class="na"&gt;presets&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-env&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;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;defaults&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-react&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;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;automatic&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="nf"&gt;terser&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;hideDeps&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="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;summaryOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example configuration file can be found &lt;a href="https://github.com/mryechkin/rollup-library-starter/blob/main/rollup.config.js" rel="noopener noreferrer"&gt;here&lt;/a&gt; for your reference as well.&lt;/p&gt;

&lt;p&gt;Keep in mind, this configuration is meant to be the foundation for your library. It serves as a starting point, but there's lots more you can do here with all the plugins available in the Rollup ecosystem. Make sure to explore the &lt;a href="https://github.com/rollup/awesome" rel="noopener noreferrer"&gt;awesome curated selection&lt;/a&gt;, and see if there's anything else that is applicable to your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Package Setup
&lt;/h2&gt;

&lt;p&gt;With Rollup configuration done, let's now configure our package file &lt;code&gt;package.json&lt;/code&gt; so that it can be properly packaged and published to NPM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scripts
&lt;/h3&gt;

&lt;p&gt;First, let's add a &lt;code&gt;build&lt;/code&gt; script, so that we can actually run Rollup:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.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="nl"&gt;"scripts"&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;"prebuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rm -rf dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rollup -c"&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;This will run Rollup CLI using the configuration we defined in &lt;code&gt;rollup.config.js&lt;/code&gt;. Since this file is at the root level, we don't need to specify it explicitly (the &lt;code&gt;-c&lt;/code&gt; flag takes care of that).&lt;/p&gt;

&lt;h3&gt;
  
  
  ESM
&lt;/h3&gt;

&lt;p&gt;As of Rollup &lt;strong&gt;v3&lt;/strong&gt;, we need to ensure that our configuration file is &lt;a href="https://rollupjs.org/migration/#using-configuration-files" rel="noopener noreferrer"&gt;loaded as an ES module&lt;/a&gt; by Node.&lt;/p&gt;

&lt;p&gt;There are a few ways to do this. One is by using the &lt;code&gt;.mjs&lt;/code&gt; extension, and another is by specifying our library package to be ESM, which is done by setting the &lt;code&gt;type&lt;/code&gt; to &lt;code&gt;"module"&lt;/code&gt; in the package file:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&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;h3&gt;
  
  
  Entry Points
&lt;/h3&gt;

&lt;p&gt;We've configured Rollup to output the bundle to the &lt;code&gt;dist&lt;/code&gt; folder. And since we've configured our library to have a root-level &lt;code&gt;index.js&lt;/code&gt;, we can use this file as the &lt;a href="https://nodejs.org/api/packages.html#package-entry-points" rel="noopener noreferrer"&gt;entry point&lt;/a&gt; of our package. Since we're publishing a dual-module package, we will need to specify these entry points separately for each of the formats (ESM and CommonJS).&lt;/p&gt;

&lt;p&gt;For CommonJS, set the &lt;code&gt;main&lt;/code&gt; field to point to the &lt;code&gt;cjs&lt;/code&gt; bundle:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.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="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/cjs/index.js"&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;Then do the same for ES Modules, by pointing the &lt;code&gt;module&lt;/code&gt; field to the &lt;code&gt;esm&lt;/code&gt; bundle:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.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="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/esm/index.js"&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;h3&gt;
  
  
  Exports
&lt;/h3&gt;

&lt;p&gt;In order to ensure maximum interoperability with tools like Webpack (and others), we should also specify the &lt;a href="https://nodejs.org/api/packages.html#subpath-exports" rel="noopener noreferrer"&gt;subpath exports&lt;/a&gt; separtely for each module format.&lt;/p&gt;

&lt;p&gt;To do this, add an &lt;code&gt;exports&lt;/code&gt; field and specify the main entry point's &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;require&lt;/code&gt; to point to the &lt;code&gt;esm&lt;/code&gt; and &lt;code&gt;cjs&lt;/code&gt; bundles, respectively:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.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="nl"&gt;"exports"&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="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"import"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/esm/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"require"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/cjs/index.js"&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;This is to ensure that we can do both:&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;// ESM&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;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="s1"&gt;rollup-library-starter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// CommonJS&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;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-library-starter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Package Files
&lt;/h3&gt;

&lt;p&gt;Lastly, we need to tell NPM which files and folders to include in our package. For this we'll use the &lt;code&gt;files&lt;/code&gt; field, which describes the entries to be included when the package is installed as a dependency. In addition to the default includes (&lt;code&gt;package.json&lt;/code&gt; itself, &lt;code&gt;README&lt;/code&gt;, &lt;code&gt;LICENSE&lt;/code&gt;, etc.) we need to specify the folder with output from Rollup.&lt;/p&gt;

&lt;p&gt;Add the &lt;code&gt;dist&lt;/code&gt; folder to the &lt;code&gt;files&lt;/code&gt; array:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.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="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="s2"&gt;"dist"&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;blockquote&gt;
&lt;p&gt;The full list of &lt;code&gt;package.json&lt;/code&gt; configuration options is available &lt;a href="https://docs.npmjs.com/cli/v8/configuring-npm" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Running the Build
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;package.json&lt;/code&gt; setup, let's now run our build and check it out. In the terminal at the root of our project type in &lt;code&gt;npm run build&lt;/code&gt;. This will run the Rollup CLI and generate its output in the &lt;code&gt;dist&lt;/code&gt; folder. You'll notice that there are also two folders in there: &lt;code&gt;esm&lt;/code&gt; and &lt;code&gt;cjs&lt;/code&gt;, each containing code in the corresponding module format.&lt;/p&gt;

&lt;p&gt;Thanks to the &lt;code&gt;rollup-plugin-analyzer&lt;/code&gt; plugin, we also get a summary of our package build:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Frollup-library-starter%2Fanalyzer-output.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2Fblog%2Frollup-library-starter%2Fanalyzer-output.png" alt="Rollup bundle analyzer plugin output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;And that about does it! Hopefully this recipe gives you a good starting point for your next JavaScript library, and remember to experiment and adjust it as needed.&lt;/p&gt;

&lt;p&gt;The full example project is available in GitHub for your reference:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/mryechkin/rollup-library-starter" rel="noopener noreferrer"&gt;https://github.com/mryechkin/rollup-library-starter&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you've made it this far - thanks for reading, and until next time!&lt;/p&gt;

</description>
      <category>rollup</category>
      <category>javascript</category>
      <category>bundle</category>
      <category>library</category>
    </item>
    <item>
      <title>Using NPM Programatically</title>
      <dc:creator>Mykhaylo Ryechkin 🇺🇦</dc:creator>
      <pubDate>Sun, 21 Aug 2022 00:37:29 +0000</pubDate>
      <link>https://dev.to/mryechkin/using-npm-programatically-13ln</link>
      <guid>https://dev.to/mryechkin/using-npm-programatically-13ln</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Did you know that you can run &lt;code&gt;npm&lt;/code&gt; commands programatically, giving you access to their output? For example, if you wanted to get the &lt;em&gt;exact&lt;/em&gt; version of a 3rd-party package installed in your &lt;code&gt;node_modules&lt;/code&gt; and display it somewhere in your app?&lt;/p&gt;

&lt;p&gt;In this post, I'll show you how to do just that, and how I've recently utilized this in a project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;In my day job, as part of our design system library ecosystem, we're building an internal code sandbox (think of it as a mix between &lt;a href="https://github.com/seek-oss/playroom"&gt;Seek OSS Playroom&lt;/a&gt; and &lt;a href="https://quickpaste.net/"&gt;QuickPaste&lt;/a&gt;). It allows our users try the components from our component library (let's call it &lt;code&gt;@wtf-ds/core&lt;/code&gt;) and any other supplementary React code right there in the browser, without having to create a new project in their own environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Requirements
&lt;/h2&gt;

&lt;p&gt;One of the features we were looking to add was a way to display the currently installed versions of the dependencies that users have access to, somewhere in the UI. The sandbox automatically includes &lt;code&gt;react&lt;/code&gt;, &lt;code&gt;styled-components&lt;/code&gt; and several component library packages in the browser editor, and users should have a way to know what specific versions of those packages they're working with.&lt;/p&gt;

&lt;p&gt;It may be tempting to just pull this information from &lt;code&gt;package.json&lt;/code&gt; at first:&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="kr"&gt;package&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;package.json&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;sc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, we quickly run into a problem.&lt;/p&gt;

&lt;p&gt;Most of the time, the version specified in &lt;code&gt;package.json&lt;/code&gt; won't be exact. It can be either the caret notation (ie. &lt;code&gt;^5.3.3&lt;/code&gt;), or the tilda (&lt;code&gt;~5.3.3&lt;/code&gt;), or perhaps just &lt;code&gt;latest&lt;/code&gt;. This doesn't exactly give us what we want. An approximate version number is better than &lt;em&gt;nothing&lt;/em&gt; - of course - but it's also not as useful as the exact one would be.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For example, whenever there's a new version of &lt;code&gt;styled-components&lt;/code&gt; released (eg. &lt;code&gt;5.3.5&lt;/code&gt;), and you do a fresh &lt;code&gt;npm install&lt;/code&gt;, the &lt;code&gt;^5.3.3&lt;/code&gt; notation won't accurately reflect the actual, currently installed version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can't rely on the value inside &lt;code&gt;package.json&lt;/code&gt;. So how do we solve this?&lt;/p&gt;

&lt;p&gt;Well, if we were looking for this info ad-hoc, we could simply run the &lt;code&gt;npm list&lt;/code&gt; command in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm list styled-components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which gives us &lt;strong&gt;all&lt;/strong&gt; instances of this package in our &lt;code&gt;node_modules&lt;/code&gt;, including any nested dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wtf-ds@ ~/Projects/wtf-ds
└─┬ @wtf-ds/core@1.0.0 -&amp;gt; ./packages/core
  ├─┬ babel-plugin-styled-components@2.0.7
  │ └── styled-components@5.3.5 deduped
  └── styled-components@5.3.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could reduce this down by adding the &lt;code&gt;--depth=0&lt;/code&gt; flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm list &lt;span class="nt"&gt;--depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 styled-components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which now gives us just the top-level instances, ie. what we need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wtf-ds@ ~/Projects/wtf-ds
└─┬ @wtf-ds/core@1.0.0 -&amp;gt; ./packages/core
  └── styled-components@5.3.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see above, our &lt;code&gt;package.json&lt;/code&gt; has &lt;code&gt;styled-components&lt;/code&gt; set to &lt;code&gt;^5.3.3&lt;/code&gt; but the actual installed version is &lt;code&gt;5.3.5&lt;/code&gt; (latest at the time of writing this). This is the version we'd like our users to see, so we can't use the caret notation - we need a way to show this version instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Turns out, you can run &lt;code&gt;npm&lt;/code&gt; commands programatically! 🤯&lt;/p&gt;

&lt;p&gt;This means that we can now run those &lt;code&gt;npm list&lt;/code&gt; commands from within a Node script, and store the output in a simple JSON file - which can then be accessed in our React code.&lt;/p&gt;

&lt;p&gt;To do this, you will need a &lt;a href="https://nodejs.org/api/util.html#utilpromisifyoriginal"&gt;promisified&lt;/a&gt; version of the &lt;a href="https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback"&gt;exec&lt;/a&gt; method from &lt;code&gt;child_process&lt;/code&gt;, which then lets you run whatever command, and have access to its output (in our case it's &lt;code&gt;npm list&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;So, I've created a seperate script (called &lt;code&gt;dependencies.js&lt;/code&gt;) which parses the output of those commands for each package, and saves that information in a &lt;code&gt;dependencies.json&lt;/code&gt; file. This file is then imported in our &lt;a href="https://nextjs.org"&gt;Next.js&lt;/a&gt; app, and the values displayed in the sandbox UI.&lt;/p&gt;

&lt;p&gt;To ensure that this file is always up-to-date, it can be run as a &lt;code&gt;postinstall&lt;/code&gt; script in &lt;code&gt;package.json&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;"scripts"&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;"postinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node scripts/dependencies.js"&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;The script itself is as follows:&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;// scripts/dependencies.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&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;util&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;util&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;exec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kr"&gt;package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../package.json&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;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;packageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dep&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;dep&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;promises&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;filteredList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@wtf-ds/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="nx"&gt;promises&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filteredList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&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;name&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stdout&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;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`npm list --depth=0 &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="s2"&gt; | grep &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="s2"&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;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&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="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="nx"&gt;version&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="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="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dependencies.json&lt;/span&gt;&lt;span class="dl"&gt;'&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what's happening here?&lt;/p&gt;

&lt;p&gt;First, we create a "promisified" version of &lt;code&gt;exec&lt;/code&gt; by wrapping it with &lt;code&gt;util.promisify()&lt;/code&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&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;util&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;util&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;exec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we read our package info from &lt;code&gt;package.json&lt;/code&gt;, and create an array of our dependency names:&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="kd"&gt;const&lt;/span&gt; &lt;span class="kr"&gt;package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../package.json&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;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;packageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dep&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;dep&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we filter out only the packages we're interested in:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@wtf-ds/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will ensure that we're only showing the relevant packages to our users. Because our "promisified" &lt;code&gt;exec&lt;/code&gt; method returns a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;Promise&lt;/a&gt; object, and we need one for each of the packages (above), we will need to store these promises in an array that can be resolved later:&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;promises&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filteredList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&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;name&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="c1"&gt;// ... each of the relevant dependencies&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now for the ✨magic✨&lt;/p&gt;

&lt;p&gt;For each of the packages in the above array, we run the &lt;code&gt;npm list&lt;/code&gt; command:&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stdout&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;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`npm list --depth=0 &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="s2"&gt; | grep &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us the currently installed version, and the output can be accessed via the &lt;code&gt;stdout&lt;/code&gt; variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  └── styled-components@5.3.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we only care about the version number, and not everything else in the output, we can parse it and get just the version number itself:&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;promises&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filteredList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&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;name&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stdout&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;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`npm list --depth=0 &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="s2"&gt; | grep &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="s2"&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;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&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="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="nx"&gt;version&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;There's probably a more elegant way to do this with regex, but I will leave that for you to optimize 😉&lt;/p&gt;

&lt;p&gt;With our array of promises ready, all that's left is to resolve them. We do this by using &lt;code&gt;Promise.all()&lt;/code&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="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="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dependencies.json&lt;/span&gt;&lt;span class="dl"&gt;'&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us the result, which is the &lt;code&gt;data&lt;/code&gt; that we'd like to store in our JSON file. The resulting output will look something like this:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@wtf-ds/core"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18.2.0"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"styled-components"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5.3.5"&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;We can now import this in our React code, and display the relevant data on the UI&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that you'll need to specify the &lt;code&gt;json&lt;/code&gt; &lt;a href="https://v8.dev/features/import-assertions"&gt;import assertion&lt;/a&gt; here to import this as a &lt;a href="https://github.com/tc39/proposal-json-modules"&gt;JSON module&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dependencies&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dependencies.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&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;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Dependencies&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dep&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GeW8Y13N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.misha.wtf/_next/image%3Furl%3D%252Fblog%252Fusing-npm-programatically%252Fui.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GeW8Y13N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.misha.wtf/_next/image%3Furl%3D%252Fblog%252Fusing-npm-programatically%252Fui.png%26w%3D3840%26q%3D100" alt="Dependencies shown in the UI" width="880" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it! 🎉 This is a fairly simple use case, but as you can see we've only scratched the surface here, and hopefully this gives you an idea of what's possible.&lt;/p&gt;

&lt;p&gt;The full script is also available as a gist &lt;a href="https://gist.github.com/mryechkin/a80a22bb2651bde70c9aa2fb4d925bc5"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>npm</category>
      <category>node</category>
      <category>cli</category>
      <category>scripts</category>
    </item>
    <item>
      <title>Streamlining your Tailwind CSS workflow with ESLint + Prettier</title>
      <dc:creator>Mykhaylo Ryechkin 🇺🇦</dc:creator>
      <pubDate>Wed, 13 Jul 2022 18:09:20 +0000</pubDate>
      <link>https://dev.to/mryechkin/streamlining-your-tailwind-css-workflow-with-eslint-prettier-1hg</link>
      <guid>https://dev.to/mryechkin/streamlining-your-tailwind-css-workflow-with-eslint-prettier-1hg</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;If you're working with &lt;a href="https://www.tailwindcss.com" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; on a regular basis, there are a few tools at your disposal that can help streamline some of the code authoring workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;One argument you often hear from opponents of Tailwind CSS is how unreadable it makes your page markup, and in particular the &lt;code&gt;class&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;With long strings of numerous Tailwind classes and all sorts of possible combinations, it's understandable how that can become a bit daunting.&lt;/p&gt;

&lt;p&gt;But, I'm here to tell you that it doesn't have to be!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;In this article we'll take a look at how tools like &lt;a href="https://eslint.org" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; and &lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt; can help us never have to think about class names again, and provide some helpful guidance along the way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-prettier-vscode.gif%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-prettier-vscode.gif%26w%3D3840%26q%3D100" alt="ESLint and Prettier formatting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eslint.org" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; is a &lt;strong&gt;code linter&lt;/strong&gt;. Linters helps identify issues in our code, ensure consistency and reduce possibilities of bugs. They generally concern themselves with code &lt;strong&gt;logic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then we have &lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;, which is an &lt;strong&gt;opinionated code formatter&lt;/strong&gt;. It concerns itself more with code &lt;strong&gt;style&lt;/strong&gt; - things like line length, indentation, syntax, etc. Prettier's main job is to ensure consistency in code, no matter the development enviornment or the number of people working on the same file.&lt;/p&gt;

&lt;p&gt;Regardless of whether a project is using Tailwind or not, ESLint and Prettier are both tools that should be part of our workflow. A lot of what we do as part of code authoring process can be automated away with these tools, and help reduce the cognitive load while writing code. With Tailwind, this is particularly noticeable.&lt;/p&gt;

&lt;p&gt;Both ESLint and Prettier have an extensive 3rd party plugins ecosystem. There are plugins and shared configurations available for all sorts of use cases, enabling us to extend the base functionality of these tools. Frameworks and libraries often provide plugins that are meant to work seamlessly alongside them, whether official or developed by the open-source community, and Tailwind is no exception.&lt;/p&gt;

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

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

&lt;p&gt;First, let's install the necessary libraries.&lt;/p&gt;

&lt;p&gt;In addition to core &lt;a href="https://eslint.org" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; and &lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt; packages themselves, there are two main plugins that we'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/francoismassart/eslint-plugin-tailwindcss" rel="noopener noreferrer"&gt;eslint-plugin-tailwindcss&lt;/a&gt; for &lt;strong&gt;ESLint&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/tailwindlabs/prettier-plugin-tailwindcss" rel="noopener noreferrer"&gt;prettier-plugin-tailwindcss&lt;/a&gt; for &lt;strong&gt;Prettier&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install these as dev dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; eslint eslint-plugin-tailwindcss prettier prettier-plugin-tailwindcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;Next, we need to create config files for both ESLint and Prettier.&lt;/p&gt;

&lt;h4&gt;
  
  
  ESLint
&lt;/h4&gt;

&lt;p&gt;First, let's do &lt;strong&gt;ESLint&lt;/strong&gt;. Create an &lt;code&gt;.eslintrc&lt;/code&gt; file at the root of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// .eslintrc
{
  "extends": [
    "eslint:recommended",
    "plugin:prettier/recommended",
    "plugin:tailwindcss/recommended"
  ],
  "env": {
    "browser": true,
    "es2021": true
  },
  "parserOptions": {
    "ecmaVersion": 2021,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "plugins": ["tailwindcss"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we're extending the recommended rule sets from ESLint, Prettier, and the Tailwind CSS plugin, as well as specifying &lt;code&gt;eslint-plugin-tailwindcss&lt;/code&gt; itself to be used as a plugin. We're also setting some defaults for our project environment and parser options.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This is the most basic setup. It's highly recommended to look into the &lt;a href="https://eslint.org/docs/latest/user-guide/configuring/" rel="noopener noreferrer"&gt;advanced configuration options&lt;/a&gt; for ESLint, and take the time to setup additional plugins and options appropriate for your project environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Prettier
&lt;/h4&gt;

&lt;p&gt;For &lt;strong&gt;Prettier&lt;/strong&gt;, we'll stick with most of the defaults, overriding just a couple of options. Create a &lt;code&gt;.prettierrc&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;// .prettierrc
{
  "printWidth": 90,
  "singleQuote": true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are personal preferences - see the complete list of &lt;a href="https://prettier.io/docs/en/options.html" rel="noopener noreferrer"&gt;options&lt;/a&gt; and adjust as needed.&lt;/p&gt;

&lt;p&gt;One neat thing with Prettier is that you don't need to explicitly list the plugins that you'd like to use. So long as they're in the same &lt;code&gt;node_modules&lt;/code&gt; folder as Prettier itself, they're &lt;a href="https://prettier.io/docs/en/plugins.html#using-plugins" rel="noopener noreferrer"&gt;loaded automatically&lt;/a&gt;. Since we installed everything in our project already, we're all set in that regard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Scripts
&lt;/h3&gt;

&lt;p&gt;Let's now create some scripts to help automate the linting process. In &lt;code&gt;package.json&lt;/code&gt;, add a &lt;code&gt;lint&lt;/code&gt; and &lt;code&gt;format&lt;/code&gt; scripts. For demo purposes, let's assume all of our code is in &lt;code&gt;src&lt;/code&gt; folder:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.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="nl"&gt;"scripts"&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;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint --fix src"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier --write src"&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;The &lt;code&gt;lint&lt;/code&gt; script will run &lt;strong&gt;ESLint&lt;/strong&gt; on everything inside our &lt;code&gt;src&lt;/code&gt; folder, and the &lt;code&gt;--fix&lt;/code&gt; flag tells it to fix any automatically-fixable issues at the same time as well. This will use the config specified in the &lt;code&gt;.eslintrc&lt;/code&gt; file we created earlier, including the plugins.&lt;/p&gt;

&lt;p&gt;Similarly, the &lt;code&gt;format&lt;/code&gt; script will run &lt;strong&gt;Prettier&lt;/strong&gt; and format it using the options specified in &lt;code&gt;.prettierrc&lt;/code&gt;. As mentioned earlier, Prettier loads its plugins automatically, so the Tailwind plugin will be loaded for us already.&lt;/p&gt;

&lt;p&gt;For complete list of available CLI options, see &lt;a href="https://prettier.io/docs/en/cli.html" rel="noopener noreferrer"&gt;Prettier docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Scripts
&lt;/h3&gt;

&lt;p&gt;With our scripts defined, we can now run these as part of our workflow to lint and format our code.&lt;/p&gt;

&lt;p&gt;To test it out, run &lt;code&gt;npm run lint&lt;/code&gt;. Here's a real example from my personal site that I ran into recently:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-eslint-output.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-eslint-output.png%26w%3D3840%26q%3D100" alt="Example of output from ESLint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, &lt;strong&gt;eslint-plugin-tailwindcss&lt;/strong&gt; helped identify some deprecated classes that I was still using. Neat! I'd been using Tailwind v3 for some time now, without realizing there were deprecated class names in my code. Without this plugin, there's a good chance I still wouldn't have noticed this.&lt;/p&gt;

&lt;p&gt;Similarly, &lt;strong&gt;prettier-plugin-tailwindcss&lt;/strong&gt; tells me that a number of Tailwind classes aren't sorted properly in a few places. Little while back, Tailwind team introduced &lt;a href="https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted" rel="noopener noreferrer"&gt;official class sorting&lt;/a&gt;, which with the help of this plugin sorts classes in a specific order. This order essentially follows how Tailwind structures the classes in the final CSS output. Having them sorted the same way in the code helps to visualize the cascade, which IMO is extremely helpful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-commit Hook
&lt;/h3&gt;

&lt;p&gt;Running these scripts manually every time is not great. Let's fix that!&lt;/p&gt;

&lt;p&gt;To help automate the process, we can use &lt;a href="https://typicode.github.io/husky" rel="noopener noreferrer"&gt;husky&lt;/a&gt; to create a pre-commit hook that will run &lt;a href="https://github.com/okonet/lint-staged" rel="noopener noreferrer"&gt;lint-staged&lt;/a&gt;, which in turn will run these linting scripts on staged files, before committing them.&lt;/p&gt;

&lt;p&gt;To do this, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx mrm@2 lint-staged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installs &lt;code&gt;lint-staged&lt;/code&gt; and &lt;code&gt;husky&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Creates a pre-commit hook in the &lt;code&gt;.husky&lt;/code&gt; directory which runs &lt;code&gt;lint-staged&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Updates &lt;code&gt;package.json&lt;/code&gt; with config for &lt;code&gt;lint-staged&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice the new entry in &lt;code&gt;package.json&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"lint-staged"&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;"*.js"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint --cache --fix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"*.{js,css,md}"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier --write"&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;Let's update this to use our scripts instead:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"lint-staged"&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;"*.js"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run lint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"*.{js,css,md*}"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run format"&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;This will tell &lt;strong&gt;lint-staged&lt;/strong&gt; to run our &lt;code&gt;lint&lt;/code&gt; script on all staged JS files, and &lt;code&gt;format&lt;/code&gt; on JS, CSS and MD(X) ones (as always, adjust this as needed). Now, before any code is committed, it's guaranteed to be linted and properly formatted. If either of those scripts fails, a commit will not proceed and we'll see what the issues are in the output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-eslint-output.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-eslint-output.png%26w%3D3840%26q%3D100" alt="Example output of our linting script"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating with VSCode
&lt;/h2&gt;

&lt;p&gt;Now this is where it gets even better. If you're using &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;, there are extensions that can help automate things further.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extensions
&lt;/h3&gt;

&lt;p&gt;Install the following VSCode extensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; (&lt;code&gt;dbaeumer.vscode-eslint&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode" rel="noopener noreferrer"&gt;Prettier - Code Formatter&lt;/a&gt;(&lt;code&gt;esbenp.prettier-vscode&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss" rel="noopener noreferrer"&gt;Tailwind CSS IntelliSense&lt;/a&gt;(&lt;code&gt;bradlc.vscode-tailwindcss&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two integrate &lt;strong&gt;ESLint&lt;/strong&gt; and &lt;strong&gt;Prettier&lt;/strong&gt; into VSCode, which will let VSCode underline any problematic code that is identified:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-vscode-1.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-vscode-1.png%26w%3D3840%26q%3D100" alt="Example of issues identified by ESLint Tailwind plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hovering over the issue will show more details:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-vscode-2.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-vscode-2.png%26w%3D3840%26q%3D100" alt="Example of issues identified by ESLint Tailwind plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Tailwind CSS IntelliSense&lt;/strong&gt; extension adds intellisense for Tailwind classes. This will let VSCode show suggestions for Tailwind classes, and what CSS they output. It even works with any custom classes you have defined in your Tailwind config. Very handy!&lt;/p&gt;

&lt;p&gt;Now, as long as you have the &lt;code&gt;.eslintrc&lt;/code&gt; and &lt;code&gt;.prettierrc&lt;/code&gt; configuration files in your root, VSCode will highlight any applicable issues in your code, using the provided configurations.&lt;/p&gt;

&lt;p&gt;If you'd like to take it a step further, you can also create a &lt;code&gt;.vscode/extensions.json&lt;/code&gt; file in your repo to provide a list of recommended extensions for anyone cloning it:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.vscode/extensions.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="nl"&gt;"recommendations"&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="s2"&gt;"dbaeumer.vscode-eslint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"bradlc.vscode-tailwindcss"&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;h3&gt;
  
  
  Enabling auto-format on save
&lt;/h3&gt;

&lt;p&gt;The last thing we want to do is enable automatic code formatting whenever we save a file in VSCode. This way, you let the tools worry about style and formatting, and can just focus on writing code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-prettier-vscode.gif%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Ftailwind-eslint-prettier%252Ftailwind-prettier-vscode.gif%26w%3D3840%26q%3D100" alt="ESLint and Prettier formatting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, open up your VSCode &lt;code&gt;settings.json&lt;/code&gt; file: &lt;code&gt;Preferences: Open Settings (JSON)&lt;/code&gt;. Make sure that the default formatter is set to the Prettier extension:&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="nl"&gt;"editor.defaultFormatter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, enable format on save:&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="nl"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that these settings can also be specified separately for specific languages:&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="nl"&gt;"[html, javascript]"&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;"editor.defaultFormatter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;Now, whenever you save a file, &lt;strong&gt;Prettier&lt;/strong&gt; will format it using the VSCode extension. This means that not only do you get all the nice formatting from Prettier config, but your Tailwind classes will also be in the same consistent order thanks to the &lt;a href="https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss" rel="noopener noreferrer"&gt;Tailwind CSS IntelliSense&lt;/a&gt; plugin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared Config
&lt;/h2&gt;

&lt;p&gt;If you like this setup (and are using &lt;strong&gt;React&lt;/strong&gt; and &lt;strong&gt;Next.js&lt;/strong&gt;) - all of the plugins mentioned here (and a few others) are included in my personal shared config:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✨ &lt;a href="https://www.npmjs.com/package/eslint-config-acme" rel="noopener noreferrer"&gt;ACME ESLint Config&lt;/a&gt; ✨&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These days &lt;strong&gt;Next.js&lt;/strong&gt; and &lt;strong&gt;Tailwind&lt;/strong&gt; are my default go-to's when building a new project, and I'll generally want the same rules applied throughout, including the same set of plugins. This &lt;a href="https://eslint.org/docs/latest/developer-guide/shareable-configs" rel="noopener noreferrer"&gt;shareable config&lt;/a&gt; makes it easy to use my preferred configuration, and not have to worry about setting up everything from scratch every time. Just install, extend, and you're good to go!&lt;/p&gt;

&lt;p&gt;This particular config is based on the popular &lt;a href="https://github.com/airbnb/javascript" rel="noopener noreferrer"&gt;Airbnb Javascript Style Guide&lt;/a&gt; and extends the corresponding &lt;a href="https://www.npmjs.com/package/eslint-config-airbnb" rel="noopener noreferrer"&gt;eslint-config-airbnb&lt;/a&gt;, as well as few others that I always find myself using. Feel free to use it in your project as well!&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Your Own
&lt;/h2&gt;

&lt;p&gt;If you're interested in making one of these on your own, check out my &lt;a href="https://youtu.be/tsPXN4mJGSc" rel="noopener noreferrer"&gt;video tutorial&lt;/a&gt; on how to do just that.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>eslint</category>
      <category>prettier</category>
      <category>vscode</category>
    </item>
    <item>
      <title>JavaScript Module Ecosystem</title>
      <dc:creator>Mykhaylo Ryechkin 🇺🇦</dc:creator>
      <pubDate>Wed, 06 Apr 2022 15:44:00 +0000</pubDate>
      <link>https://dev.to/mryechkin/javascript-module-ecosystem-3mj7</link>
      <guid>https://dev.to/mryechkin/javascript-module-ecosystem-3mj7</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;If you've done web development for any amount of time, there's a good chance you've had to work with tools like &lt;a href="https://webpack.js.org"&gt;Webpack&lt;/a&gt;, &lt;a href="https://rollupjs.org"&gt;Rollup&lt;/a&gt;, &lt;a href="https://browserify.org/"&gt;Browserify&lt;/a&gt; and other front-end tooling systems. But do you know why we started using them in the first place, and why they are still part of our everyday workflow?&lt;/p&gt;

&lt;p&gt;In this post, we'll take a look at one of the core areas of JavaScript - the &lt;strong&gt;module ecosystem&lt;/strong&gt; - and why tools like the ones mentioned above are &lt;em&gt;required&lt;/em&gt; (🥁).&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Before we talk about what modules are, let's take a brief look at some JavaScript history, and why modules and their different formats came to be.&lt;/p&gt;

&lt;p&gt;For most of its early life, "the web" (ie. browsers) had only one way to load script files, via plain &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"a.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"b.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"c.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is now what we refer to as "classic" scripts. In classic scripts, all &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Scope"&gt;scope&lt;/a&gt; is shared (via the global &lt;code&gt;window&lt;/code&gt; object). There is also no explicit way to specify dependency between files, so order of &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags matters. You need to be careful about the order in which files are imported, and be mindful of subsequent changes in them.&lt;/p&gt;

&lt;p&gt;This may not be such a big deal for simple scripts and adding some interactivity to a static page, but nowadays we run entire applications comprised of complex JavaScript - and as you can imagine, with the classic scripts approach things can get really messy, really quickly. There had to be another - better - way of loading JavaScript.&lt;/p&gt;

&lt;p&gt;With the advent of &lt;a href="https://nodejs.org/"&gt;Node&lt;/a&gt; in 2009, we also needed a way to load and run JavaScript on the server as well. With one key difference, however. In high-latency client environments like the browser, it's faster to send one large file, rather than many small ones. By contrast, in a server environment files are co-located on the same filesystem, and as such can be accessed virtually instantly. Node can load as many individual files as necessary, without any performance implications due to latency.&lt;/p&gt;

&lt;p&gt;And this is where the module system and JavaScript tooling come into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what are modules anyway?
&lt;/h2&gt;

&lt;p&gt;Modules are a mechanism for splitting up JavaScript into smaller, manageable logical chunks of code. They are essentially a way to organize, and ship code in JavaScript. Modules let us write code in one file that explicitly depends on (or is a dependency of) code in another file.&lt;/p&gt;

&lt;p&gt;When browsers and Node load a JavaScript program, they build a map of all the modules that are used in the project. This process is called &lt;strong&gt;module resolution&lt;/strong&gt;, and the map of these modules and their relationship to each other is often referred to as a &lt;strong&gt;module graph&lt;/strong&gt;. The resolution algorithm itself is different depending on the runtime environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Module Formats
&lt;/h3&gt;

&lt;p&gt;There are several different module formats: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules"&gt;ES6 Modules&lt;/a&gt; (or &lt;strong&gt;ESM&lt;/strong&gt;), &lt;a href="https://en.wikipedia.org/wiki/CommonJS"&gt;CommonJS&lt;/a&gt; (or &lt;strong&gt;CJS&lt;/strong&gt;), &lt;a href="http://requirejs.org/docs/whyamd.html"&gt;AMD&lt;/a&gt; and &lt;a href="https://github.com/umdjs/umd"&gt;UMD&lt;/a&gt; are among the ones you're likely to come across.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why so many?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As mentioned earlier, there are different JavaScript runtime environments to consider. We have the &lt;strong&gt;browser&lt;/strong&gt; with its various implementations (Chrome, Firefox, Safari, etc), and then the &lt;strong&gt;server&lt;/strong&gt;, with runtimes like &lt;a href="https://nodejs.org/"&gt;Node&lt;/a&gt; and &lt;a href="https://deno.land/"&gt;Deno&lt;/a&gt;. Each has its own different set of concerns, as we saw earlier as well.&lt;/p&gt;

&lt;p&gt;That made it tricky to land on a specification. For a long time, there wasn't a single, agreed-upon standard between those environments in terms of how to deal with modules. There were concurrent attempts at solving the problem (even JavaScript standards themselves are &lt;em&gt;async&lt;/em&gt; 🥁), and what resulted was an emergence of the module formats mentioned above.&lt;/p&gt;

&lt;p&gt;Eventually, module format spec was standardized by the &lt;a href="https://tc39.es/"&gt;TC39&lt;/a&gt; committee, with &lt;strong&gt;ESM&lt;/strong&gt; becoming the de-facto "future-proof" standard going forward. Along with &lt;strong&gt;CommonJS&lt;/strong&gt;, it is the format you are most likely to come across and work with today.&lt;/p&gt;

&lt;h3&gt;
  
  
  Module Specifiers
&lt;/h3&gt;

&lt;p&gt;Modules are loaded using keywords like &lt;code&gt;import&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./module.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and &lt;code&gt;require&lt;/code&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are called &lt;strong&gt;module specifiers&lt;/strong&gt;. They can be either full or relative URL's:&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;// Full URL&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;greet&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="s1"&gt;https://some.cdn.com/module.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Relative URL&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;greet&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="s1"&gt;./module.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They can also be "bare" (ie. without specifying file extensions):&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;greet&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="s1"&gt;./module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; the bare specifier is not yet supported in browsers as of the writing of this post, and requires tools to interpret the syntax.&lt;/p&gt;

&lt;h3&gt;
  
  
  Module Scope
&lt;/h3&gt;

&lt;p&gt;The way modules are loaded is different between browsers and server environments (ie. Node).&lt;/p&gt;

&lt;p&gt;Browser loads modules as &lt;strong&gt;stateful singletons&lt;/strong&gt; - meaning that the same module will share its state anywhere it's imported in the application, for the duration of that session. A good mental model to help understand this better is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When you import a module, you're not getting a piece of code that you're running, you get a reference to an object in memory&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(shoutout to &lt;a href="https://twitter.com/samselikoff"&gt;Sam Selikoff&lt;/a&gt; and &lt;a href="https://twitter.com/ryanto"&gt;Ryan Toronto&lt;/a&gt; from &lt;a href="https://frontendfirst.fm/"&gt;Frontend First Podcast&lt;/a&gt; whose discussion in &lt;a href="https://youtu.be/j1s_3zytAcM?t=1740"&gt;Episode #100&lt;/a&gt; helped a great deal in understanding these concepts)&lt;/p&gt;

&lt;p&gt;In a Node environment, however, modules are loaded as &lt;strong&gt;instances&lt;/strong&gt;. This means that each imported module instance in your app has its own state, not shared with any of the other instances of the same module - so you no longer have a &lt;strong&gt;global&lt;/strong&gt; module state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Module Exports
&lt;/h3&gt;

&lt;p&gt;By default, everything that is declared inside a module is scoped locally to that module. If you want to make something accessible outside the module (and really, that's the whole point), you need to &lt;code&gt;export&lt;/code&gt; it. There are several ways of exporting, and which one to use will depend on the target module format (ie. ESM vs CommonJS), as well as what kind of export you are doing.&lt;/p&gt;

&lt;p&gt;In general, ES modules have two types of exports: &lt;strong&gt;default&lt;/strong&gt; and &lt;strong&gt;named&lt;/strong&gt;. You can export any top-level function, class or variable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use which?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That really depends on the intended use and structure of the module. One approach is to &lt;code&gt;export default&lt;/code&gt; the main functionality of a module, to denote its main intent. Then any supplemental functionality or data are treated as named exports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Format: ES6 Modules (ESM)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ESM&lt;/strong&gt; is the standard established and governed by &lt;a href="https://tc39.es/"&gt;TC39&lt;/a&gt; committee. It is the modern standard for JavaScript modules going forward, and is supported natively in all major browsers, as well as newer versions of Node (15 and above). For Node 14 and below, ESM can be enabled with the help of 3rd party libraries (eg. &lt;a href="https://github.com/standard-things/esm"&gt;esm&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;ESM uses &lt;code&gt;.js&lt;/code&gt; and &lt;code&gt;.mjs&lt;/code&gt; extensions (browser and Node, respectively), and utilizes &lt;code&gt;import&lt;/code&gt; keyword for importing, and &lt;code&gt;export&lt;/code&gt; for exporting.&lt;/p&gt;

&lt;p&gt;When exporting from ESM, you can do either &lt;strong&gt;default&lt;/strong&gt; or &lt;strong&gt;named&lt;/strong&gt; exports:&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;// module.esm.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Human&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Planet Earth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// named exports&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;GREETING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&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="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greeting&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from &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;location&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// default export&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Importing can be done using &lt;strong&gt;default&lt;/strong&gt; imports:&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;user&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./module.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or using &lt;strong&gt;named&lt;/strong&gt; imports, where the name of the thing you're importing goes inside curly braces:&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;greet&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="s1"&gt;./module.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also import both default and named at the same time, as well as multiple named imports, using this one-line convention:&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;// index.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GREETING&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="s1"&gt;./foo.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GREETING&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="c1"&gt;// "Hello, Human from Planet Earth"&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GREETING&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Hello"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&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="c1"&gt;// { name: 'Human', location: 'Planet Earth' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some characteristics and rules of ESM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;import&lt;/code&gt;'s are static and asynchronous (browsers are async in their nature, after all)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;import&lt;/code&gt;'s must live at the root level&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;import&lt;/code&gt;'s also get hoisted, so can be written anywhere in the code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;import&lt;/code&gt; specifier can only accept a string literal (ie. it can't be dynamically generated)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Due to this nature of ESM, code written in it can also be statically analyzed and &lt;strong&gt;tree-shaken&lt;/strong&gt; by tools like &lt;a href="https://rollupjs.org/"&gt;Rollup&lt;/a&gt; , so that no extra unused JavaScript is included in the bundle.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Tree-shaking"&lt;/strong&gt; or what is also known as "dead code elimination" is a process through which tools like &lt;a href="https://webpack.js.org"&gt;Webpack&lt;/a&gt; and &lt;a href="https://rollupjs.org"&gt;Rollup&lt;/a&gt; do static analysis of your code, and try to determine which modules aren't utilized. Doing this allows these tools to drastically cut down on the overall bundle size, and only include what's actually needed to run your application or library code. ESM is much more compatible with this process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To load an ESM module in a browser, we need to specify &lt;code&gt;type&lt;/code&gt; as &lt;code&gt;"module"&lt;/code&gt; in the script tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/some-module.js"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&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;When loading in Node, there are several ways to target ESM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set &lt;code&gt;type&lt;/code&gt; field to &lt;code&gt;"module"&lt;/code&gt; in the &lt;code&gt;package.json&lt;/code&gt; of the project&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;.mjs&lt;/code&gt; file extension&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;--input-type=module&lt;/code&gt; flag via Node CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Format: CommonJS (CJS)
&lt;/h2&gt;

&lt;p&gt;CommonJS (or &lt;strong&gt;CJS&lt;/strong&gt;) is a module system that originated in &lt;a href="https://nodejs.org/"&gt;Node&lt;/a&gt;. It has been the prevalent format in the Node ecosystem for many years, and is still used in many libraries and tools today.&lt;/p&gt;

&lt;p&gt;CJS modules are exported via &lt;code&gt;module.exports&lt;/code&gt;, and use the &lt;code&gt;require&lt;/code&gt; keyword for importing:&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;// module.cjs.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Human&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Planet Earth&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;GREETING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&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;greet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greeting&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from &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;location&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GREETING&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the above can also be written this way:&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;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GREETING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;GREETING&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To import CommonJS, use the &lt;code&gt;require&lt;/code&gt; keyword :&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;// index.js&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;default&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;greet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GREETING&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./module.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GREETING&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="c1"&gt;// "Hello, Human from Planet Earth"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GREETING&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Hello"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&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="c1"&gt;// { name: 'Human', location: 'Planet Earth' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CommonJS uses &lt;code&gt;.js&lt;/code&gt; and &lt;code&gt;.cjs&lt;/code&gt; file extensions, and it &lt;em&gt;cannot&lt;/em&gt; be loaded directly in a browser. For that exist specific tools that allow us to run CommonJS code in a browser environment, such as &lt;a href="https://browserify.org/"&gt;Browserify&lt;/a&gt;, &lt;a href="https://rollupjs.org/"&gt;Rollup&lt;/a&gt; and others.&lt;/p&gt;

&lt;p&gt;Unlike ES6 Modules which are loaded &lt;strong&gt;asynchronously&lt;/strong&gt;, CommonJS module resolution is &lt;strong&gt;synchronous&lt;/strong&gt;. Remember how we talked about server environments having virtually no latency for module loading? This is why.&lt;/p&gt;

&lt;p&gt;Due to this low latency, CJS modules are loaded dynamically, at runtime. The module specifier is a function, which can accept JS expressions, making &lt;code&gt;require&lt;/code&gt; dynamic. This allows us to do things like conditional imports:&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;thing&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isTrue&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./a.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./b.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this has certain tradeoffs. For instance, JavaScript tools can't know what's going to be loaded ahead of time. This unfortunately makes CommonJS modules not compatible with tree-shaking. It's much less of a concern on the server - since you're not sending code to the client - and if we remember that the CJS module format originated in Node, then it make sense why this format wouldn't concern itself with that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interoperability
&lt;/h2&gt;

&lt;p&gt;With all the differences between the module formats we've seen so far, and the different runtime environment gotchas, it's evident why there is such a strong need for a &lt;strong&gt;single&lt;/strong&gt;, standard module specification going into the future.&lt;/p&gt;

&lt;p&gt;Now let us ask a question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"What happens if you want to use a CommonJS module inside an ES6 module? Or the other way around?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The short answer is, it depends. Browsers don't support this natively - so we have to yet again rely on our tooling to support this functionality.&lt;/p&gt;

&lt;p&gt;Bundlers and transpilers such as &lt;a href="https://babeljs.io/"&gt;Babel&lt;/a&gt;, &lt;a href="https://webpack.js.org"&gt;Webpack&lt;/a&gt;, &lt;a href="https://rollupjs.org"&gt;Rollup&lt;/a&gt; etc. have been doing a decent job of ensuring compatibility between the different module formats and runtimes, however some &lt;a href="https://github.com/rollup/plugins/issues/481"&gt;edge cases&lt;/a&gt; and &lt;a href="https://github.com/babel/babel/issues/12363"&gt;issues&lt;/a&gt; still exist today.&lt;/p&gt;

&lt;p&gt;We'll take a closer look at some of these interoperability concerns in a future post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Before wrapping this up, let's consider something for a second. If there are so many issues with interoperability, then &lt;strong&gt;why are we still using CommonJS?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer to that is not a simple one, unfortunately. First, CommonJS is &lt;em&gt;everywhere&lt;/em&gt;. It's still the main format used in Node, and has been for many years (Node only recently started supporting ESM). The NPM ecosystem is &lt;em&gt;huge&lt;/em&gt;. And though many popular library authors have been shipping both ESM and CJS compatible code, there are still many packages out there that are exclusively CommonJS. This is especially true for legacy systems, and enterprise code, which may not have the luxury of moving its entire codebase to an entirely different module system.&lt;/p&gt;

&lt;p&gt;Second, it's a lengthy process. Lots of large (and popular) codebases and tools still use and heavily rely on it. So while the goal may be to move to a single unified format down the road (ESM), it is not an overnight change, and will take some time for the entire ecosystem to migrate to it.&lt;/p&gt;

&lt;p&gt;There are some folks who are eager to help &lt;a href="https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c"&gt;move it forward&lt;/a&gt;, though others are &lt;a href="https://gist.github.com/joepie91/bca2fda868c1e8b2c2caf76af7dfcad3"&gt;against the idea&lt;/a&gt; altogether. Both sides present valuable arguments, and the discussions are worth checking out if you're interested in the topic.&lt;/p&gt;

&lt;p&gt;In a future post, we'll take a look at how to ship your library code in both ESM and CommonJS using &lt;a href="https://rollupjs.org"&gt;Rollup&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Until next time!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>modules</category>
      <category>esm</category>
      <category>commonjs</category>
    </item>
    <item>
      <title>User Authentication in Next.js with Supabase</title>
      <dc:creator>Mykhaylo Ryechkin 🇺🇦</dc:creator>
      <pubDate>Wed, 24 Nov 2021 04:16:34 +0000</pubDate>
      <link>https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12</link>
      <guid>https://dev.to/mryechkin/user-authentication-in-nextjs-with-supabase-4l12</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT NOTE:&lt;/strong&gt; This article was written for Supabase &lt;strong&gt;v1&lt;/strong&gt;, which is now outdated. Though everything still works (to the best of my knowledge), please be aware that the libraries and versions mentioned here &lt;strong&gt;are now outdated&lt;/strong&gt;. See the ✨NEW✨ &lt;a href="https://dev.to/mryechkin/authentication-in-nextjs-with-supabase-and-next-13-36le"&gt;updated guide&lt;/a&gt; on using Supabase &lt;strong&gt;v2&lt;/strong&gt; and Next.js &lt;strong&gt;13&lt;/strong&gt; instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.supabase.io" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; has been getting a lot of attention in the tech community, and for good reason. This open source platform makes it super easy to get started building complex full-stack applications, and in this post we will take a look at how to utilize one of its core offerings: &lt;strong&gt;User Authentication&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;One of the things that stands out about Supabase almost immediately is just how easy it is to get started. You can be up and running in quite literally minutes, and Authentication is no exception. It provides a fully integrated solution, including user management and email notifications, with no reliance on any external authentication services. And with Supabase being open source, you have complete control and ownership of your user data, as it's all stored in the same PostgreSQL database.&lt;/p&gt;

&lt;p&gt;Supabase provides several different authentication mechanisms out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic &lt;strong&gt;Email&lt;/strong&gt; authentication&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Magic Link&lt;/strong&gt; or a one-time login with email&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Social&lt;/strong&gt; logins: Google, Facebook, GitHub, Azure, Gitlab, Twitter, Discord, and Bitbucket&lt;/li&gt;
&lt;li&gt;Phone / SMS login using &lt;strong&gt;Twilio&lt;/strong&gt; integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this tutorial we'll be using &lt;strong&gt;Email&lt;/strong&gt; authentication, with ability to reset forgotten password.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Just want the code?&lt;/strong&gt; GitHub repo available &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Live version is &lt;a href="https://next-supabase-ui-auth.vercel.app" rel="noopener noreferrer"&gt;available&lt;/a&gt; as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Supabase Client
&lt;/h2&gt;

&lt;p&gt;Supabase provides a &lt;a href="https://supabase.io/docs/reference/javascript/supabase-client" rel="noopener noreferrer"&gt;client library&lt;/a&gt; that makes it &lt;em&gt;supa&lt;/em&gt; easy to get started in your project. It is a modular library, comprised of several different sub-libraries, each enabling integration with the specific sub-system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@supabase/postgrest-js&lt;/code&gt; for &lt;a href="https://github.com/postgrest/postgrest" rel="noopener noreferrer"&gt;PostgREST&lt;/a&gt; (REST API for PostgreSQL)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@supabase/realtime-js&lt;/code&gt; for &lt;a href="https://github.com/supabase/realtime" rel="noopener noreferrer"&gt;Realtime&lt;/a&gt; (realtime connection to PostgreSQL via websockets)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@supabase/gotrue-js&lt;/code&gt; for &lt;a href="https://github.com/netlify/gotrue" rel="noopener noreferrer"&gt;GoTrue&lt;/a&gt; (fork of Netlify's authentication and user management API)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The single &lt;code&gt;@supabase/supabase-js&lt;/code&gt; bundle combines the three libraries into one, and adds some ease-of-use enhancements, making it the perfect Supabase companion for your projects.&lt;/p&gt;

&lt;p&gt;It's worthwhile to note that the client library is also available in several other different languages as well - including &lt;strong&gt;C#&lt;/strong&gt;, &lt;strong&gt;Python&lt;/strong&gt;, &lt;strong&gt;Rust&lt;/strong&gt; and &lt;strong&gt;Dart&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supabase UI
&lt;/h2&gt;

&lt;p&gt;Supabase also provides an open source component library called &lt;a href="https://ui.supabase.io/" rel="noopener noreferrer"&gt;Supabase UI&lt;/a&gt;, which is a collection of common UI components and utilities that are used across the range of Supabase products. Its styling is heavily inspired by &lt;a href="https://www.tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;, so you know it will look good out of the box.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsupabase-ui.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsupabase-ui.png%26w%3D3840%26q%3D100" alt="Supabase UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will be using the &lt;a href="https://ui.supabase.io/components/auth" rel="noopener noreferrer"&gt;Auth&lt;/a&gt; component, which provides all the necessary screens and integrations for the various authentication flows. In particular, we'll need to be able to perform the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sign Up&lt;/strong&gt; (Email)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign In&lt;/strong&gt; (Email)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sign Out&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reset Password&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Update Password&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, that's quite a bit of UI and state logic that we would need to implement ourselves from scratch. Using a component that provides all of that already wired up out of the box will be a big time saver.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll take a look at everything you need to use this component in your own application, as well as some ways to customize it to your needs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; At the time of writing this post, Supabase UI is in early development stages, so the API and some features may still change in the full release. For example, theming is not currently supported, and is the reason we'll need to perform some workarounds later on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Supabase Setup
&lt;/h2&gt;

&lt;p&gt;You will need to create a Supabase account if you haven't already done so. Supabase provides a &lt;a href="https://supabase.io/pricing" rel="noopener noreferrer"&gt;generous&lt;/a&gt; free tier for their cloud solution, so it's easy to get started. Alternatively, since it's open-source, you can also host your own as well.&lt;/p&gt;

&lt;p&gt;Once signed up, go to &lt;a href="https://app.supabase.io/" rel="noopener noreferrer"&gt;Supabase Dashboard&lt;/a&gt; and create a new project.&lt;/p&gt;

&lt;h3&gt;
  
  
  API Keys
&lt;/h3&gt;

&lt;p&gt;In order to be able to access the Supabase API via our JS client, we will need to have API keys available in the app.&lt;/p&gt;

&lt;p&gt;In the dashboard, go to &lt;strong&gt;Settings &amp;gt; API&lt;/strong&gt;. As you'll see, by default an anonymous public API key is already available. This will be enough for our needs. Take note of this value, as well as the URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsettings-api.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsettings-api.png%26w%3D3840%26q%3D100" alt="API Settings in Supabase Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure to keep these on hand, as we'll need them later on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js Project Setup
&lt;/h2&gt;

&lt;p&gt;For this tutorial, we'll be using &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; and the &lt;a href="https://www.tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; starter template 🚀&lt;/p&gt;

&lt;p&gt;To do that, 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 create-next-app &lt;span class="nt"&gt;--example&lt;/span&gt; with-tailwindcss next-with-supabase-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, install both &lt;strong&gt;Supabase Client&lt;/strong&gt;, and &lt;strong&gt;Supabase UI&lt;/strong&gt; dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @supabase/supabase-js @supabase/ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all we need to get started. Let's code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Application Structure
&lt;/h2&gt;

&lt;p&gt;Our application will be pretty simple. The main &lt;strong&gt;Home&lt;/strong&gt; page will show the different authentication screens - Sign In, Sign Up, Forgot Password, etc. It wil also show the authentication status, a button linking to a &lt;strong&gt;Profile&lt;/strong&gt; page, and a button to sign out.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Profile&lt;/strong&gt; page will display the currently logged-in user's data, and a button to go back to &lt;strong&gt;Home&lt;/strong&gt; page. It also needs to be a "protected" page, meaning that only authenticated users can access it. We'll take a look at how to accomplish this both on client and server-side in later steps.&lt;/p&gt;

&lt;p&gt;First, let's scaffold out the base pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Home Page
&lt;/h3&gt;

&lt;p&gt;Let's go ahead and put some placeholder content on the main page to start with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/index.js;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/Layout&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;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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&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;"highlight"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;You are logged out&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Profile Page
&lt;/h3&gt;

&lt;p&gt;Similarly, let's put some placeholder content on the Profile page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/profile.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/link&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;Layout&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/Layout&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;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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;User Profile&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&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;"heading"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Last Signed In:&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&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;"highlight"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;N/A&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&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;"button"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Go Home&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;Layout&lt;/code&gt; is our main layout container, abstracted into a component in &lt;code&gt;components/Layout.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Layout.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/head&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;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Layout&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&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;"flex min-h-screen flex-col items-center justify-center py-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Next.js with Supabase Auth&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/favicon.ico"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&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;"flex w-full flex-1 flex-col items-center justify-center px-8 text-center sm:px-20"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&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;"text-5xl font-bold sm:text-6xl"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Next.js with &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&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;"font-black text-green-400"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Supabase&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&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;"mt-8 inline-flex w-full max-w-sm flex-col space-y-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TIP:&lt;/strong&gt; Enable &lt;a href="https://nextjs.org/docs/advanced-features/module-path-aliases" rel="noopener noreferrer"&gt;absolute import paths and module aliases&lt;/a&gt; in Next.js for shorter imports, like &lt;code&gt;@/components&lt;/code&gt; etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We've also abstracted some CSS classes that will be used throughout the app in the &lt;code&gt;styles/globals.css&lt;/code&gt; file (using Tailwind):&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="c"&gt;/* src/styles/globals.css */&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;py-4&lt;/span&gt; &lt;span class="err"&gt;text-4xl&lt;/span&gt; &lt;span class="err"&gt;font-black&lt;/span&gt; &lt;span class="err"&gt;text-gray-800;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;custom-focus&lt;/span&gt; &lt;span class="err"&gt;rounded-full&lt;/span&gt; &lt;span class="err"&gt;border-2&lt;/span&gt; &lt;span class="err"&gt;border-green-400&lt;/span&gt; &lt;span class="err"&gt;bg-white&lt;/span&gt; &lt;span class="err"&gt;px-8&lt;/span&gt; &lt;span class="err"&gt;py-2&lt;/span&gt; &lt;span class="err"&gt;font-bold&lt;/span&gt; &lt;span class="err"&gt;text-green-400&lt;/span&gt; &lt;span class="py"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;bg-green-400&lt;/span&gt; &lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;text-white&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;bg-green-400&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;text-white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.button-inverse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;custom-focus&lt;/span&gt; &lt;span class="err"&gt;rounded-full&lt;/span&gt; &lt;span class="err"&gt;border-2&lt;/span&gt; &lt;span class="err"&gt;border-white&lt;/span&gt; &lt;span class="err"&gt;bg-green-400&lt;/span&gt; &lt;span class="err"&gt;px-8&lt;/span&gt; &lt;span class="err"&gt;py-2&lt;/span&gt; &lt;span class="err"&gt;font-bold&lt;/span&gt; &lt;span class="err"&gt;text-white&lt;/span&gt; &lt;span class="py"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;border-green-400&lt;/span&gt; &lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;bg-white&lt;/span&gt; &lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;text-green-400&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;border-green-400&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;bg-white&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;text-green-400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.custom-focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="py"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;border-green-400&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;outline-none&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ring-2&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ring-green-400&lt;/span&gt; &lt;span class="n"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ring-offset-2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.heading&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;text-lg&lt;/span&gt; &lt;span class="err"&gt;font-semibold&lt;/span&gt; &lt;span class="err"&gt;text-gray-700;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.highlight&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;ml-1&lt;/span&gt; &lt;span class="err"&gt;rounded-lg&lt;/span&gt; &lt;span class="err"&gt;bg-gray-100&lt;/span&gt; &lt;span class="err"&gt;p-2&lt;/span&gt; &lt;span class="err"&gt;font-mono;&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;h2&gt;
  
  
  Adding Authentication
&lt;/h2&gt;

&lt;p&gt;With the base of our project scaffolded out, we can start working on the authentication layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initializing Supabase
&lt;/h3&gt;

&lt;p&gt;Supabase Client lets us easily work with the Supabase API, and manages our authentication and user data on the front-end. In order to initialize it, we will need to specify the URL and the public API key from the previous step.&lt;/p&gt;

&lt;p&gt;We can do this by setting those values as &lt;a href="https://nextjs.org/docs/basic-features/environment-variables" rel="noopener noreferrer"&gt;environment variables&lt;/a&gt; in &lt;strong&gt;Next.js&lt;/strong&gt;. Create a &lt;code&gt;.env.local&lt;/code&gt; file in the root of the project, and set the values to the ones from the dashboard earlier:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.env.local&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;NEXT_PUBLIC_SUPABASE_URL=&amp;lt;value&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;NEXT_PUBLIC_SUPABASE_ANON_KEY=&amp;lt;value&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's create a separate file for our Supabase Client instance. Name this file &lt;code&gt;client.js&lt;/code&gt; and put it in &lt;code&gt;lib&lt;/code&gt; folder at the root of the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/client.js&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;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="s1"&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;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;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;NEXT_PUBLIC_SUPABASE_URL&lt;/span&gt;&lt;span class="p"&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;NEXT_PUBLIC_SUPABASE_ANON_KEY&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now whenever we need to use Supabase Client, we can simply import it and access the available functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication Provider
&lt;/h3&gt;

&lt;p&gt;In order to handle all the authentication logic in our app, we're going to use the concept of an authenticaion provider. This pattern was heavily inspired by Kent C. Dodds &lt;a href="https://kentcdodds.com/blog/authentication-in-react-applications" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; on this topic, and follows a lot of the same basic principles.&lt;/p&gt;

&lt;p&gt;We'll call this &lt;strong&gt;AuthProvider&lt;/strong&gt; and use it as the top-level component in our app, thereby providing user data and authentication functionality throughout. It will utilize &lt;a href="https://reactjs.org/docs/context.html" rel="noopener noreferrer"&gt;React Context&lt;/a&gt;, and provide the &lt;code&gt;session&lt;/code&gt; and &lt;code&gt;user&lt;/code&gt; objects from Supabase Client, as well as the &lt;a href="https://supabase.io/docs/reference/javascript/auth-signout" rel="noopener noreferrer"&gt;signOut&lt;/a&gt; function. The rest of the authentication flows will be handled by the &lt;strong&gt;Auth&lt;/strong&gt; component from Supabase UI, which we'll get to in later steps.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;lib&lt;/code&gt; folder, create a file &lt;code&gt;auth.js&lt;/code&gt;, and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/auth.js&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="nx"&gt;useContext&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="s1"&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;const&lt;/span&gt; &lt;span class="nx"&gt;AuthContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&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;AuthProvider&lt;/span&gt; &lt;span class="o"&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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="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="nf"&gt;useState&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="nf"&gt;useState&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AuthContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;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="na"&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="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="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&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;useAuth&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&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="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&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="s1"&gt;useAuth must be used within an AuthProvider&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;return&lt;/span&gt; &lt;span class="nx"&gt;context&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;Here, we have the main &lt;strong&gt;AuthProvider&lt;/strong&gt;, which we'll need to wrap our application in. It provides the &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;session&lt;/code&gt; values, as well as exposes the &lt;code&gt;signOut&lt;/code&gt; function from Supabase Client. To access these values in our app pages, we've also created the &lt;code&gt;useAuth&lt;/code&gt; hook, which simply pulls the values from the &lt;strong&gt;AuthContext&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now before we can use it, we need to make &lt;strong&gt;AuthProvider&lt;/strong&gt; the top-level component of our application. We'll do this by adding the following to &lt;code&gt;pages/_app.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/_app.js&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;AuthProvider&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="s1"&gt;@/lib/auth&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="s1"&gt;@/lib/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AuthProvider&lt;/span&gt; &lt;span class="na"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;supabase&lt;/code&gt; is our &lt;strong&gt;Supabase Client&lt;/strong&gt; instance. Now we can freely use the &lt;code&gt;useAuth&lt;/code&gt; hook in our app and access the &lt;code&gt;session&lt;/code&gt; and &lt;code&gt;user&lt;/code&gt; objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting User Data
&lt;/h3&gt;

&lt;p&gt;Let's update the &lt;strong&gt;Home&lt;/strong&gt; page to utilize some of the user data, and add a few more UI elements for the authenticated state. We'll add a link to the &lt;strong&gt;Profile&lt;/strong&gt; page, and a button to log out the current user (by calling the &lt;code&gt;signOut&lt;/code&gt; function). We'll also display the user's &lt;code&gt;role&lt;/code&gt; as a badge. Feel free to get more creative here 😄&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fhome.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fhome.png%26w%3D3840%26q%3D100" alt="Home Page"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/index.js&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;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="s1"&gt;@/lib/auth&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;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;signOut&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;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&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="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&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;"highlight"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&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;role&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/profile"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&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;"button"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Go to Profile&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&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;"button-inverse"&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="nx"&gt;signOut&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Sign Out
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding Supabase UI
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, we will need to support the following auth flows: &lt;strong&gt;Sign Up&lt;/strong&gt;, &lt;strong&gt;Sign In&lt;/strong&gt;, &lt;strong&gt;Sign Out&lt;/strong&gt;, &lt;strong&gt;Reset Password&lt;/strong&gt;, &lt;strong&gt;Update Password&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Normally this would take quite a bit of time to build from scratch - we'd need to create several different forms, add input validation, error handling, state and UI logic, etc. As you can see, the list gets rather long rather quickly.&lt;/p&gt;

&lt;p&gt;Supabase makes this easy for us to do as well. Using the &lt;strong&gt;Auth&lt;/strong&gt; component from Supabase UI, we can add all of these required screens to our app with fairly minimal effort, with the aforementioned functionality already included.&lt;/p&gt;

&lt;p&gt;To do this, we'll use the &lt;strong&gt;Auth&lt;/strong&gt; component on the main landing page, and pass it our Supabase Client instance. In &lt;code&gt;pages/index.js&lt;/code&gt;, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/index.js&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;Auth&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="s1"&gt;@supabase/ui&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="s1"&gt;@/lib/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="c1"&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;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Auth&lt;/span&gt; &lt;span class="na"&gt;supabaseClient&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;}&lt;/span&gt;
  &lt;span class="c1"&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;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsign-in.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsign-in.png%26w%3D3840%26q%3D100" alt="Sign In"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We pass our Supabase Client instance to it via the &lt;code&gt;supabaseClient&lt;/code&gt; prop, and voila! 🎉 Now we have a shiny new UI, with all of the required forms to handle the login flows. However, before we can fully test this, we'll need to setup a few more things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Auth State Change
&lt;/h2&gt;

&lt;p&gt;What happens if the authenticated state changes in Supabase Client? For example, when a user successfully logs in, or the current user signs out? Our application will need to know about these changes in the state. Which means that we also need a way to update our &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;session&lt;/code&gt; data whenever this happens. We can do this by adding an event listener on the &lt;code&gt;onAuthStateChange&lt;/code&gt; method in Supabase Client.&lt;/p&gt;

&lt;p&gt;Back in our &lt;strong&gt;lib/auth.js&lt;/strong&gt; file, create &lt;code&gt;authListener&lt;/code&gt; for the &lt;code&gt;onAuthStateChange&lt;/code&gt; event inside a &lt;code&gt;useEffect&lt;/code&gt; hook (on initial load):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/auth.js&lt;/span&gt;
&lt;span class="c1"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;activeSession&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;session&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;activeSession&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;activeSession&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="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;authListener&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="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;currentSession&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;currentSession&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;currentSession&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="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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;authListener&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="p"&gt;[]);&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now whenever auth state in Supabase Client changes, our &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;session&lt;/code&gt; state objects will be updated as well, and this data will be in sync with Supabase Client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switching Auth Views
&lt;/h2&gt;

&lt;p&gt;We need a way to tell the &lt;strong&gt;Auth&lt;/strong&gt; component which screen to show as a result of the auth state change. For example - when a user signs out, we want our &lt;strong&gt;Auth&lt;/strong&gt; component to show the &lt;strong&gt;Sign In&lt;/strong&gt; screen again. We can do this by passing &lt;code&gt;view&lt;/code&gt; prop to the &lt;strong&gt;Auth&lt;/strong&gt; component, which tells it which authentication flow to show. The &lt;code&gt;event&lt;/code&gt; received by &lt;code&gt;onAuthStateChanged&lt;/code&gt; will dictate which view we should be showing. We'll see how this gets utilized for updating a user's password in a later step.&lt;/p&gt;

&lt;p&gt;First, let's store all the possible values for both the &lt;code&gt;VIEWS&lt;/code&gt; and &lt;code&gt;EVENTS&lt;/code&gt; in &lt;code&gt;lib/auth.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/auth.js&lt;/span&gt;
&lt;span class="c1"&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;EVENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;PASSWORD_RECOVERY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PASSWORD_RECOVERY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;SIGNED_OUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGNED_OUT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;USER_UPDATED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;USER_UPDATED&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;VIEWS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;SIGN_IN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sign_in&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;SIGN_UP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sign_up&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;FORGOTTEN_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;forgotten_password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;MAGIC_LINK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;magic_link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;UPDATE_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update_password&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="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll need to keep track of the current view in our &lt;strong&gt;AuthProvider&lt;/strong&gt;, so let's add it as &lt;code&gt;view&lt;/code&gt; to the context as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/auth.js&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;AuthProvider&lt;/span&gt; &lt;span class="o"&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setView&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="nx"&gt;VIEWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SIGN_IN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&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="c1"&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;authListener&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="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;currentSession&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;currentSession&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;currentSession&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;switch &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="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;EVENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PASSWORD_RECOVERY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;setView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;VIEWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;EVENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SIGNED_OUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;EVENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;USER_UPDATED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;setView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;VIEWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SIGN_IN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AuthContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;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="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&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="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="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we're setting the &lt;code&gt;view&lt;/code&gt; to &lt;code&gt;UPDATE_PASSWORD&lt;/code&gt; when &lt;code&gt;PASSWORD_RECOVERY&lt;/code&gt; event is dispatched, and to &lt;code&gt;SIGN_IN&lt;/code&gt; when user logs out, or user is updated in session. Now all that's left is to pass this value to the &lt;strong&gt;Auth&lt;/strong&gt; component. In our main page &lt;code&gt;pages/index.js&lt;/code&gt;, update the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/index.js&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;view&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;=&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;// ...&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&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;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Auth&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;supabaseClient&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;}&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;h2&gt;
  
  
  Authentication Flows
&lt;/h2&gt;

&lt;p&gt;With everything in place, we're now ready to try out the authentication flows. Make sure that you have the environment variables setup as outlined earlier, and then run the app with &lt;code&gt;npm run dev&lt;/code&gt; and load &lt;code&gt;localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sign Up
&lt;/h3&gt;

&lt;p&gt;First, let's register our user. On the landing page, click on "Sign up" link, which will take you to the &lt;strong&gt;Sign Up&lt;/strong&gt; form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsign-up.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsign-up.png%26w%3D3840%26q%3D100" alt="Sign Up"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter your email and password, and press the "Sign up" button. This will send a confirmation email to the address provided, with a link to complete the registration process. It uses the default email template, which can be updated on the Templates page in Supabase Dashboard settings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Ftemplates.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Ftemplates.png%26w%3D3840%26q%3D100" alt="Supabase Email Templates"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note as well that the default URL in the link is set to &lt;code&gt;http://localhost:3000&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsettings-auth.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsettings-auth.png%26w%3D3840%26q%3D100" alt="Supabase URL Settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This works for development, but will need to be updated to the corresponding URL when running in production environments. See &lt;a href="https://github.com/supabase/supabase/discussions/1514" rel="noopener noreferrer"&gt;this&lt;/a&gt; GitHub discussion for more details.&lt;/p&gt;

&lt;p&gt;Clicking the confirmation link will redirect you to the site URL (&lt;code&gt;http://localhost:3000&lt;/code&gt;), along with an &lt;code&gt;access_token&lt;/code&gt; and &lt;code&gt;type&lt;/code&gt;, which is verified by the Supabase Client. It then sets the local session, and broadcasts the &lt;code&gt;SIGNED_IN&lt;/code&gt; event.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sign In
&lt;/h3&gt;

&lt;p&gt;After a user signs in (either via &lt;strong&gt;Sign In&lt;/strong&gt; form, or after clicking confirmation link, as above), Supabase Client sets the user session in localStorage under the &lt;code&gt;supabase.auth.token&lt;/code&gt; key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;currentSession&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;provider_token&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="na"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;access_token&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;expires_in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;expires_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1635127600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;refresh_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;refresh_token&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;token_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bearer&lt;/span&gt;&lt;span class="dl"&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;43cf36c1-9940-46e7-980a-fe1243b0e43c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;aud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authenticated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authenticated&lt;/span&gt;&lt;span class="dl"&gt;'&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;darth@empire.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;email_confirmed_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-10-25T01:06:38.040501Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;confirmation_sent_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-10-25T01:06:09.418358Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;confirmed_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-10-25T01:06:38.040501Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;email_change_confirm_status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;last_sign_in_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-10-25T01:06:38.041156Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;app_metadata&lt;/span&gt;&lt;span class="p"&gt;:&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;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;user_metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="na"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-10-25T01:06:09.41273Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;updated_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-10-25T01:06:09.41273Z&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="na"&gt;expiresAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1635127600&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;This also broadcasts the &lt;code&gt;SIGNED_IN&lt;/code&gt; event, which gets picked up by our &lt;code&gt;onAuthStateChanged&lt;/code&gt; listener we had setup earlier. The &lt;code&gt;session&lt;/code&gt;, &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;view&lt;/code&gt; are also updated as a result.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sign Out
&lt;/h3&gt;

&lt;p&gt;Signing out a user is as easy as calling the &lt;code&gt;signOut&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/index.js&lt;/span&gt;
&lt;span class="c1"&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;view&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;=&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;// ...&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&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;"button-inverse"&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="nx"&gt;signOut&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Sign Out
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will remove the signed in user from the browser session, clear any associated items from localStorage, and fire the &lt;code&gt;SIGNED_OUT&lt;/code&gt; event. Since our &lt;code&gt;onAuthStateChange&lt;/code&gt; event handler is already setup, it will set the &lt;code&gt;Auth&lt;/code&gt; view to &lt;code&gt;SIGN_IN&lt;/code&gt;, so that our users are presented with the Sign In form again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/auth.js&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="k"&gt;switch &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="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;EVENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SIGNED_OUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;EVENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;USER_UPDATED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;setView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;VIEWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SIGN_IN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;Auth&lt;/strong&gt; component will detect this change, and render the sign-in form.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reset Password
&lt;/h3&gt;

&lt;p&gt;If a user had forgotten their password, they can request a password reset. From the sign in screen, click on "Forgot your password?" and enter the email used to register:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Freset-password.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Freset-password.png%26w%3D3840%26q%3D100" alt="Reset Password"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After submitting the form, Supabase will send a password reset email with a link. Remember that you can update this email template via Supabase Dashboard as well if you'd like.&lt;/p&gt;

&lt;p&gt;When a user clicks the link in the email, they'll be redirected to:&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;SITE_URL&amp;gt;#access_token=x&amp;amp;refresh_token=y&amp;amp;expires_in=z&amp;amp;token_type=bearer&amp;amp;type=recovery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;type=recovery&lt;/code&gt; indicates that this is a &lt;strong&gt;Reset Password&lt;/strong&gt; flow. Normally, our app would need to detect this and present the user with a password reset form. However, since we are using &lt;strong&gt;Supabase Client&lt;/strong&gt; and &lt;strong&gt;Supabase UI&lt;/strong&gt;, all of that is made much easier.&lt;/p&gt;

&lt;p&gt;Earlier we had setup the &lt;code&gt;onAuthStateChange&lt;/code&gt; listener to wait for specific auth events and update the &lt;code&gt;view&lt;/code&gt; accordingly. When the above request comes in, &lt;strong&gt;Supabase Client&lt;/strong&gt; dispatches the &lt;code&gt;PASSWORD_RECOVERY&lt;/code&gt; event, which sets the &lt;code&gt;view&lt;/code&gt; to &lt;code&gt;update_password&lt;/code&gt;. We're not quite done, however.&lt;/p&gt;

&lt;p&gt;You see, as part of the reset password flow in &lt;strong&gt;GoTrue&lt;/strong&gt;, user is temporarily logged in with the &lt;a href="https://github.com/supabase/gotrue#get-verify" rel="noopener noreferrer"&gt;verification token&lt;/a&gt;, before actually updating the password. This is &lt;a href="https://github.com/supabase/supabase/issues/383#issuecomment-747105808" rel="noopener noreferrer"&gt;by design&lt;/a&gt;, however it means that we need to add some additional checks for this in our app.&lt;/p&gt;

&lt;p&gt;Since we're relying on &lt;code&gt;user&lt;/code&gt; to determine whether to show the auth forms, we need to check for the &lt;code&gt;UPDATE_PASSWORD&lt;/code&gt; view explicitly, and render the corresponding form then. Luckily for us, &lt;strong&gt;Auth&lt;/strong&gt; from Supabase UI also exports the &lt;code&gt;UpdatePassword&lt;/code&gt; component, which we can use on its own.&lt;/p&gt;

&lt;p&gt;Add this conditional to check for the &lt;code&gt;view&lt;/code&gt; on the &lt;code&gt;Home&lt;/code&gt; page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/index.js&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;view&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;=&lt;/span&gt; &lt;span class="nf"&gt;useAuth&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;view&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;VIEWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UpdatePassword&lt;/span&gt; &lt;span class="na"&gt;supabaseClient&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&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 when a user clicks on the link, they'll be presented with this screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fupdate-password.png%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fupdate-password.png%26w%3D3840%26q%3D100" alt="Update Password"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Behind the scenes, when a user submits the new password, Supabase UI will call the &lt;a href="https://supabase.io/docs/reference/javascript/auth-update" rel="noopener noreferrer"&gt;update&lt;/a&gt; method in Supabase Client, which updates the user on the backend and sets the new password. If successful, Supabase Client then dispatches the &lt;code&gt;USER_UPDATED&lt;/code&gt; event, which (once again) gets picked up by &lt;code&gt;onAuthStateChange&lt;/code&gt; listener, and updates our &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;session&lt;/code&gt; data.&lt;/p&gt;

&lt;p&gt;Go ahead and give that a try. You should now see the logged-in state of the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server-Side Rendering (SSR)
&lt;/h2&gt;

&lt;p&gt;All of the above examples are doing authentication on the &lt;strong&gt;client-side&lt;/strong&gt;. Let's also take a look at how do this on the &lt;strong&gt;server&lt;/strong&gt;, using Next.js &lt;a href="https://nextjs.org/docs/api-routes/introduction" rel="noopener noreferrer"&gt;API routes&lt;/a&gt; and &lt;a href="https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering" rel="noopener noreferrer"&gt;server-side rendered&lt;/a&gt; pages.&lt;/p&gt;

&lt;p&gt;This will allow us to do &lt;a href="https://nextjs.org/docs/authentication#authenticating-server-rendered-pages" rel="noopener noreferrer"&gt;protected routes&lt;/a&gt; to limit access only to authenticated users, and redirect otherwise. It will also help eliminate a flash of unauthenticated state on initial page load, which can happen with the client-side only approach.&lt;/p&gt;

&lt;p&gt;Let's add this to the existing &lt;strong&gt;Profile&lt;/strong&gt; page.&lt;/p&gt;

&lt;p&gt;First, we need to create a new API route. Create a new &lt;code&gt;auth.js&lt;/code&gt; file in the &lt;code&gt;pages/api&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/api/auth.js&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="s1"&gt;@/lib/client&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;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&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="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAuthCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;Calling the &lt;code&gt;setAuthCookie&lt;/code&gt; method will set the current &lt;code&gt;session&lt;/code&gt; in a cookie, allowing us to persist it to the server.&lt;/p&gt;

&lt;p&gt;Next, we need to ensure that whenver authentication state changes, that change gets propagated down (via the above API). To do this, update &lt;strong&gt;AuthProvider&lt;/strong&gt; in &lt;code&gt;lib/auth.js&lt;/code&gt; to call the &lt;code&gt;/api/auth&lt;/code&gt; API with the current &lt;code&gt;session&lt;/code&gt; in the &lt;code&gt;onAuthStateChange&lt;/code&gt; handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/auth.js&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;AuthProvider&lt;/span&gt; &lt;span class="o"&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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="c1"&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="c1"&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;authListener&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="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;currentSession&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="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/auth&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
          &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;same-origin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&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="na"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentSession&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to enable &lt;a href="https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering" rel="noopener noreferrer"&gt;server-side rendering&lt;/a&gt; on the &lt;code&gt;Profile&lt;/code&gt; page, and check for &lt;code&gt;user&lt;/code&gt; prior to rendering the page on the client. To do this, we'll need to get the &lt;code&gt;user&lt;/code&gt; from the cookie above. If no valid session exists, we can redirect user back to the &lt;strong&gt;Sign In&lt;/strong&gt; form.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;pages/profile.js&lt;/code&gt;, add &lt;code&gt;getServerSideProps&lt;/code&gt; and call the &lt;a href="https://supabase.com/docs/reference/javascript/auth-user" rel="noopener noreferrer"&gt;getUserByCookie&lt;/a&gt; method from &lt;strong&gt;Supabase Client&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/profile.js&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="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&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;getServerSideProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="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="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUserByCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please login.&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="na"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;permanent&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="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="na"&gt;props&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="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there is a valid logged-in user in the session stored in the cookie, we can use it to protect our pages in Next.js. If &lt;code&gt;user&lt;/code&gt; exists, pass it as a prop to our client-side. Otherwise, we can redirect users back to &lt;strong&gt;Home&lt;/strong&gt; page by setting the &lt;code&gt;redirect&lt;/code&gt; to &lt;code&gt;/&lt;/code&gt;. This way we can ensure that &lt;strong&gt;Profile&lt;/strong&gt; is only accessible to logged-in users.&lt;/p&gt;

&lt;p&gt;Next, let's update the &lt;strong&gt;Profile&lt;/strong&gt; page to display some of the user data. Update &lt;code&gt;pages/profile.js&lt;/code&gt; to display the user &lt;code&gt;id&lt;/code&gt; and the &lt;code&gt;last_sign_in_at&lt;/code&gt; date:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/profile.js&lt;/span&gt;
&lt;span class="c1"&gt;// ...&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="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&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;"py-8 text-4xl font-black"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&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;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&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;"my-4 text-lg"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Last Signed In:
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&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;"highlight"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&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;last_sign_in_at&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&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;lt;/&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&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;"inline-flex flex-col"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&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;"button mt-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Go Home&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Theming
&lt;/h2&gt;

&lt;p&gt;While the default styling of &lt;strong&gt;Supabase UI&lt;/strong&gt; is a good start, more than likely you will want it to match the rest of your app's look and feel. Unfortunately, as of the writing of this article (&lt;code&gt;@supabase/ui&lt;/code&gt; version &lt;code&gt;0.36.0&lt;/code&gt;), theming support is not available &lt;em&gt;just yet&lt;/em&gt; (though &lt;a href="https://github.com/supabase/ui/issues/17" rel="noopener noreferrer"&gt;it is coming&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;But don't fret! It's quite easy to work around this limitation in the meantime. We can set styling of UI elements in &lt;strong&gt;Supabase UI&lt;/strong&gt; by targeting their CSS classes, and extend them in our &lt;code&gt;src/styles/globals.css&lt;/code&gt; file with Tailwind, and our existing custom classes:&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="c"&gt;/* src/styles/globals.css */&lt;/span&gt;
&lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="nc"&gt;.sbui-input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;custom-focus&lt;/span&gt; &lt;span class="err"&gt;rounded-full&lt;/span&gt; &lt;span class="py"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;shadow-none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.sbui-checkbox&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;custom-focus&lt;/span&gt; &lt;span class="err"&gt;rounded-full&lt;/span&gt; &lt;span class="py"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;shadow-none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.sbui-btn-primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;custom-focus&lt;/span&gt; &lt;span class="err"&gt;button-inverse&lt;/span&gt; &lt;span class="err"&gt;rounded-full&lt;/span&gt; &lt;span class="err"&gt;!important;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.sbui-typography-link&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;custom-focus&lt;/span&gt; &lt;span class="err"&gt;rounded-full&lt;/span&gt; &lt;span class="err"&gt;font-bold&lt;/span&gt; &lt;span class="err"&gt;text-green-400&lt;/span&gt; &lt;span class="err"&gt;!important;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note the use of &lt;code&gt;!important&lt;/code&gt; here, as we need these styles to be the top-most specificity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This will ensure that the input fields, buttons and text links in the &lt;strong&gt;Auth&lt;/strong&gt; component us the same styling as the rest of our application. We're also making it a bit more accessible by adding more pronounced focus and hover outlines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsign-in-themed.gif%26w%3D3840%26q%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.misha.wtf%2F_next%2Fimage%3Furl%3D%252Fblog%252Fnextjs-supabase-auth%252Fsign-in-themed.gif%26w%3D3840%26q%3D100" alt="Sign In form improvements"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now our authentication forms match as well! 🎉 Play around with it and change more as you see fit. Though not the ideal solution, it still beats setting everything up from scratch, and I'm confident that the folks over at &lt;strong&gt;Supabase&lt;/strong&gt; will have this capability delivered in the near future.&lt;/p&gt;

&lt;p&gt;You may want to keep an eye on their GitHub &lt;a href="https://github.com/supabase/ui" rel="noopener noreferrer"&gt;repo&lt;/a&gt; as well for future updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;And this about wraps it up. If you've followed along this far, by now you should have a fully working authentication layer in your app, with all of the required forms and flows hooked in, and a pretty decent-looking UI to go along with it.&lt;/p&gt;

&lt;p&gt;All of the code in this article is available for reference in &lt;a href="https://github.com/mryechkin/nextjs-supabase-auth" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. Live version is available as well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://next-supabase-ui-auth.vercel.app" rel="noopener noreferrer"&gt;next-supabase-ui-auth.vercel.app&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you'd like to learn more about &lt;strong&gt;Supabase&lt;/strong&gt; and &lt;strong&gt;Supabase UI&lt;/strong&gt;, make sure to check out the official docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://supabase.com/docs" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ui.supabase.io/" rel="noopener noreferrer"&gt;Supabase UI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nextjs</category>
      <category>supabase</category>
      <category>authentication</category>
      <category>auth</category>
    </item>
  </channel>
</rss>
