<?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: Ben Fox</title>
    <description>The latest articles on DEV Community by Ben Fox (@benjaminwfox).</description>
    <link>https://dev.to/benjaminwfox</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%2F402840%2Fbd65bdd0-46a1-4927-86bd-c9382f2c7962.jpg</url>
      <title>DEV Community: Ben Fox</title>
      <link>https://dev.to/benjaminwfox</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/benjaminwfox"/>
    <language>en</language>
    <item>
      <title>Next.js Setup | ESLint, Jest, React Testing Library, and Absolute Imports</title>
      <dc:creator>Ben Fox</dc:creator>
      <pubDate>Thu, 10 Mar 2022 22:15:14 +0000</pubDate>
      <link>https://dev.to/benjaminwfox/nextjs-setup-eslint-jest-react-testing-library-and-absolute-imports-3881</link>
      <guid>https://dev.to/benjaminwfox/nextjs-setup-eslint-jest-react-testing-library-and-absolute-imports-3881</guid>
      <description>&lt;h3&gt;
  
  
  &lt;em&gt;A comprehensive step-by-step guide to configuring Jest, React Testing Library, ESLint, and Absolute Path Aliases in a Next.js project.&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Next.js is amazing&lt;/strong&gt; when it comes to installing, learning the framework, and jumping into the code. Its superb documentation &amp;amp; zero-config philosophy make this possible, and not having to think about configuration is wonderful…right up to the point when you want to add some additional configuration.&lt;/p&gt;

&lt;p&gt;The configuration I want to add is, technically speaking, useless to your final product. It won’t make it faster, or reduce your bundle size, or add amazing new features.&lt;/p&gt;

&lt;p&gt;How’s that for a hook…🙄&lt;/p&gt;

&lt;p&gt;But it’s important 🤩 Consider this step the first reminder to &lt;a href="https://www.infoq.com/articles/slow-down-go-faster/"&gt;go slow to go fast&lt;/a&gt; (esp. check the second to last paragraph). If you need more convincing, remember when Facebook changed its motto to ‘&lt;a href="https://mashable.com/2014/04/30/facebooks-new-mantra-move-fast-with-stability/"&gt;move fast with stable infra&lt;/a&gt;’?&lt;/p&gt;

&lt;p&gt;You don’t even have to use all of it right away. ESLint and path aliases for absolute imports, once set up, are a free productivity boost. Absolute imports mean no need to worry about how many levels of ../../ are needed to find the component you are trying to import. Linting means no need to worry that a missing ) or } will leave you bashing your head against the wall for 30 minutes wondering why your code doesn’t work.&lt;/p&gt;

&lt;p&gt;Jest &amp;amp; React Testing Library, on the other hand, require some effort after setup. Testing your code &lt;a href="https://dev.to/restoreddev/why-you-should-be-unit-testing--3k85"&gt;is a good habit to have&lt;/a&gt;, and there are some &lt;em&gt;very&lt;/em&gt; good resources out there to help you &lt;a href="https://kentcdodds.com/blog/how-to-know-what-to-test"&gt;figure out what to test&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You may not start testing much right away — particularly if your UI &amp;amp; functional requirements are subject to frequent, drastic changes — but you should test what you can. If you’re not testing at all, you may want to consider evaluating &lt;a href="https://kentcdodds.com/blog/why-youve-been-bad-about-testing"&gt;why you’re putting it off&lt;/a&gt;. At least now, with this setup ready to go, &lt;a href="https://lifehacker.com/form-better-habits-by-making-them-more-convenient-1640358351"&gt;you’re more likely to get into the habit&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem?
&lt;/h2&gt;

&lt;p&gt;Sounds great right? You’ll have stable infrastructure to boost productivity, linting to enforce consistent coding standards, increasing readability and maintainability, and testing to make sure you don’t break stuff 🥳 but getting all of these set up and playing nicely with each other, with Next.js and with your IDE, can be a time consuming exercise in frustration. It’s also WAY less fun than writing code 😩&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution?
&lt;/h2&gt;

&lt;p&gt;This is it! Take the time to set it all up once, before writing any project specific code, to create a codebase that can be easily duplicated for any new projects.&lt;/p&gt;

&lt;p&gt;Let’s look at what it takes.&lt;/p&gt;

&lt;h3&gt;
  
  
  What We’ll Cover
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Assumptions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Final Repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next.js: Installing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ESLint: Install &amp;amp; Configure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Jest &amp;amp; React Testing Library: Install, Configure, Implement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configuring Path Aliases/Absolute Imports&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Assumptions
&lt;/h2&gt;

&lt;p&gt;I’m going to assume you have familiarity running commands in a terminal, and I’m going to use npm commands. None of the commands are anything fancy, so you should be able to &lt;a href="https://alligator.io/nodejs/npm-yarn-cheatsheet/"&gt;convert to yarn&lt;/a&gt; if needed.&lt;/p&gt;

&lt;p&gt;I’m going to jump right in to adding configuration, and won’t dive in to too much detail on any one item — &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt;, &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;, &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt;, &lt;a href="https://testing-library.com/docs/react-testing-library/intro"&gt;React Testing Library&lt;/a&gt;, or &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt; —but I will try to give at least some high-level context for what’s happening at each step.&lt;/p&gt;

&lt;p&gt;I’m not going to talk about IDE-specific integrations or setup. I’m using VSCode, and I’ll mention it in a few places. Other IDEs should have similar options, but likely require other specific setup steps. If you run into IDE specific issues let me know and I can see about adding additional notes.&lt;/p&gt;

&lt;h3&gt;
  
  
  A note before we start
&lt;/h3&gt;

&lt;p&gt;Some of the configuration files we create (&lt;a href="https://jestjs.io/docs/en/configuration"&gt;jest.config.js&lt;/a&gt;, &lt;a href="https://eslint.org/docs/user-guide/configuring"&gt;.eslintrc&lt;/a&gt;) can be included within package.json rather than using separate files, if that feels cleaner to you. That will require additional wrapping syntax, which you can find at their respective links. The jsconfig.json &amp;amp; jest.setup.js files will have to be separate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Repository
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/BenjaminWFox/nextjs-base"&gt;https://github.com/BenjaminWFox/nextjs-base&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js: Installing
&lt;/h2&gt;

&lt;p&gt;To start, in your terminal of choice, cd into a folder where you want to install this project. A new subfolder will be created be after you run the setup:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Give your project a name like "nextjs-base" (this will also be the folder name). Once the install completes, cd nextjs-base into your project folder.&lt;/p&gt;

&lt;p&gt;Now, &lt;a href="https://nextjs.org/docs/advanced-features/src-directory"&gt;for better organization&lt;/a&gt;, create a new folder called &lt;code&gt;src&lt;/code&gt; and then move the &lt;code&gt;pages&lt;/code&gt; and &lt;code&gt;styles&lt;/code&gt; folders into &lt;code&gt;src&lt;/code&gt;. Your project should 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;.next/
node_modules/
public/
src/
 - pages/
  - api/
 - styles/
.eslint.json
.gitignore
next.config.js
package-lock.json
package.json
README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ESLint: Install &amp;amp; Configure
&lt;/h2&gt;

&lt;p&gt;For configuration, let’s start with eslint — that’ll ensure that any future code we write is linted right away and we don’t need to go back and make edits. This will also include a plugin for specifically linting React, and another for linting import/export statements. You'll already have &lt;code&gt;eslint&lt;/code&gt; and &lt;code&gt;eslint-config-next&lt;/code&gt; - so let's add two more:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D eslint-plugin-react eslint-plugin-import
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;While that’s running, open up the &lt;code&gt;.eslintrc.json&lt;/code&gt; file that is at the root of your site. Replace the contents with the configuration below.&lt;/p&gt;

&lt;p&gt;Note that &lt;a href="https://eslint.org/docs/user-guide/configuring"&gt;there are a ton of options for configuring ESLint&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You &lt;strong&gt;&lt;em&gt;can&lt;/em&gt;&lt;/strong&gt; just extend &lt;code&gt;next&lt;/code&gt; and &lt;code&gt;next/core-web-vitals&lt;/code&gt; if you want, leaving out the others. If you do, you can also omit the everything in the &lt;code&gt;rules&lt;/code&gt; property. Personally, I like the extra structure and what's there feel to me like a good default baseline. A number of the &lt;code&gt;react/&lt;/code&gt; specific rules are disabled to prevent conflicts with the default &lt;code&gt;next-app&lt;/code&gt; code style.&lt;/p&gt;

&lt;p&gt;If you're working anyone else I'd highly recommend leaving the rules in place, it goes a long way towards keeping a codebase stylistically consistent:&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;"extends"&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;"next"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"next/core-web-vitals"&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:all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:react/all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:import/errors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:import/warnings"&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;"env"&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;"browser"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"es2020"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"node"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"jest"&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;span class="nl"&gt;"parserOptions"&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;"sourceType"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ecmaFeatures"&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;"jsx"&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;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&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;"indent"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"quotes"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"single"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"semi"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"never"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"func-style"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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;"max-len"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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;"no-magic-numbers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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;"max-lines-per-function"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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;"space-before-function-paren"&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;"error"&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;"anonymous"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"never"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"named"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"never"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"asyncArrow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&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;"function-call-argument-newline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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;"padded-blocks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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;"padding-line-between-statements"&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;"error"&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;"blankLine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"return"&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;"blankLine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prev"&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;"const"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"let"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"var"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"blankLine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"any"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"prev"&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;"const"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"let"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"var"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"next"&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;"const"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"let"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"var"&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;"object-curly-spacing"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"one-var"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"never"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"quote-props"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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/prop-types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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/jsx-indent"&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&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/jsx-indent-props"&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&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/jsx-filename-extension"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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/react-in-jsx-scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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/jsx-no-literals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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/jsx-one-expression-per-line"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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/jsx-max-depth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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/jsx-newline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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/jsx-props-no-spreading"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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/jsx-max-props-per-line"&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;"error"&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="nl"&gt;"maximum"&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="nl"&gt;"single"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"multi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&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;"ignorePatterns"&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;"node_modules/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;".next/"&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;^ some breakdown of what this is doing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://eslint.org/docs/2.0.0/user-guide/configuring#extending-configuration-files"&gt;extends&lt;/a&gt; sets up a set of base rules to use as a starting point. Using &lt;strong&gt;all&lt;/strong&gt; is probably going to make your life harder…but I would recommend keeping it, and adding specific modifications to rules you don’t like. It will give you a good sense of the different ways people might format code. There are all kinds of base configs you could extend instead, from companies (&lt;a href="https://www.npmjs.com/package/eslint-config-airbnb"&gt;airbnb&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/eslint-config-fbjs"&gt;facebook&lt;/a&gt;) and projects (&lt;a href="https://www.npmjs.com/package/eslint-config-standard"&gt;standard&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/eslint-config-prettier"&gt;prettier&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://eslint.org/docs/2.0.0/user-guide/configuring#specifying-environments"&gt;env&lt;/a&gt; tells ESLint what global variables &amp;amp; special syntax to expect. Since this is for Next.js, we’re adding the &lt;strong&gt;browser&lt;/strong&gt; and &lt;strong&gt;node&lt;/strong&gt;. The &lt;strong&gt;es2020&lt;/strong&gt; (which is ecmaVersion 11 (which basically means JavaScript version 11)) allows for using newer JavaScript syntax, and &lt;strong&gt;jest&lt;/strong&gt; is for global variables used when writing tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://eslint.org/docs/2.0.0/user-guide/configuring#specifying-parser-options"&gt;parserOptions&lt;/a&gt; is specifically for allowing additional JavaScript language features. &lt;strong&gt;sourceType&lt;/strong&gt; will prevent errors from import syntax, and &lt;strong&gt;ecmaFeatures&lt;/strong&gt; allows for additional features outside the standard ecma syntax.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://eslint.org/docs/2.0.0/user-guide/configuring#configuring-rules"&gt;rules&lt;/a&gt; is where you can configure the linting behavior to your liking. Any that are prefixed with react/ are &lt;a href="https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules"&gt;specific to the ESLint react plugin&lt;/a&gt;, similarly import/ would prefix any &lt;a href="https://github.com/benmosher/eslint-plugin-import#rules"&gt;rules for the import plugin&lt;/a&gt; — we just don’t need to add any here. Otherwise they are &lt;a href="https://eslint.org/docs/rules/"&gt;standard ESLint rules&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://eslint.org/docs/user-guide/configuring#ignorepatterns-in-config-files"&gt;ignorePatterns&lt;/a&gt; lets you define specific files, folders, or patterns to exclude from linting. Both the &lt;strong&gt;node_modules&lt;/strong&gt; and &lt;strong&gt;.next&lt;/strong&gt; folders are actually excluded be default, and added here only as examples.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So…that’s a lot! But it will let us lint the Next.js project we have now with the --fix flag enabled to automatically format our code (next step!).&lt;/p&gt;

&lt;h3&gt;
  
  
  Add &amp;amp; Run the Lint Script
&lt;/h3&gt;

&lt;p&gt;Now add one new script to your &lt;strong&gt;package.json&lt;/strong&gt; file under the start script:&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="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next start"&lt;/span&gt;&lt;span class="err"&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;"next lint"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint.fix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next lint --fix"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;^&lt;/strong&gt; Don’t forget the , (comma) at the end of the &lt;code&gt;"lint"&lt;/code&gt; line! If you've integrated your IDE with ESLint you’ll already have seen a bunch of errors if you open &lt;strong&gt;src/pages/index.js.&lt;/strong&gt; The &lt;strong&gt;src/pages/api/hello.js&lt;/strong&gt; should be error-free!&lt;/p&gt;

&lt;p&gt;If you &lt;code&gt;npm run lint&lt;/code&gt; now, you can also see all the errors in the console. I've tweaked the eslint config over time, so the exact set of errors may be slightly different.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PxAUchXN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3552/1%2AaCb1Y6V6IDusI3c6fc7Fmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PxAUchXN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3552/1%2AaCb1Y6V6IDusI3c6fc7Fmw.png" alt="errors shown from running eslint, mostly about sorting props alphabetically" width="880" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;…now do npm run lint.fix and you’ll see a number of formatting changes to align the code with the linter rules, and no more errors!&lt;/p&gt;

&lt;h3&gt;
  
  
  Two Final Notes on Linting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Regarding IDE integration if you go that route — it’s super convenient to set it up to lint &amp;amp; fix whenever you save the file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assuming you use this base template in new projects, if you find yourself making updates to the .estlintrc file to accommodate your style preferences, remember to copy those back to the base project!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Jest &amp;amp; Testing Library: Install, Configure, Implement
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install Dependencies
&lt;/h3&gt;

&lt;p&gt;Next up let’s add testing capabilities. Start with the install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D jest @types/jest @testing-library/react @testing-library/jest-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;^ &lt;a href="https://jestjs.io/"&gt;jest&lt;/a&gt; for running the tests &amp;amp; &lt;a href="https://www.npmjs.com/package/@types/jest"&gt;@types/jest&lt;/a&gt; to help with IDE auto-complete when writing tests. &lt;a href="https://github.com/testing-library/react-testing-library"&gt;@testing-library/react&lt;/a&gt; to render components in the testing environment &amp;amp; test them in a way that tries to mimic how users interact with them. &lt;a href="https://github.com/testing-library/jest-dom#readme"&gt;@testing-library/jest-dom&lt;/a&gt; for additional DOM-related &lt;a href="https://www.tutorialspoint.com/software_testing_dictionary/assertion_testing.htm"&gt;assertions&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Config Files
&lt;/h3&gt;

&lt;p&gt;Create two new files at the project root for Jest: &lt;strong&gt;jest.config.js&lt;/strong&gt; &amp;amp; &lt;strong&gt;jest.setup.js&lt;/strong&gt;. Add this content to the &lt;strong&gt;jest.config.js&lt;/strong&gt; file:&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;// Jest.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextJest&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;next/jest&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;createJestConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nextJest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// Provide the path to your Next.js app to load next.config.js and .env files in your test environment&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;./&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Jest.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Automatically clear mock calls and instances between every test&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;clearMocks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// The directory where Jest should output its coverage files&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;coverageDirectory&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;.coverage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// A list of paths to modules that run some code to configure or set up the testing framework before each test&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setupFilesAfterEnv&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;./jest.setup.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;// By default jest will use a node environment, so DOM elements (like document) will be undefined without this&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testEnvironment&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;jsdom&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="nx"&gt;createJestConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;^ There are &lt;a href="https://jestjs.io/docs/en/configuration"&gt;a huge number of configuration options &lt;/a&gt;for Jest. This is a very small subset. &lt;strong&gt;clearMocks&lt;/strong&gt; can prevent headaches with unintended &lt;a href="https://jestjs.io/docs/en/manual-mocks"&gt;persistence of mock data&lt;/a&gt; between tests. &lt;strong&gt;coverageDirectory&lt;/strong&gt; is for generating &lt;a href="https://jestjs.io/docs/en/cli.html#--coverageboolean"&gt;test coverage&lt;/a&gt;, running jest with the --coverage flag. The most important piece here is &lt;strong&gt;setupFilesAfterEnv&lt;/strong&gt;, which will run before each test file. Add this to the &lt;strong&gt;jest.setup.js&lt;/strong&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;// Jest.setup.js
import '@testing-library/jest-dom'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;^ This enables access to the additional assertions provided by the&lt;a href="https://github.com/testing-library/jest-dom#readme"&gt;@testing-library/jest-do&lt;/a&gt;m package.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write a Test File
&lt;/h3&gt;

&lt;p&gt;Create a file &lt;strong&gt;src/page-tests/index.test.js&lt;/strong&gt; and add some test code:&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;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&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;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Home&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;../pages/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// `describe` is not required, but it helps the tests read nicely&lt;/span&gt;
&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The Home Page Component&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Each test for the component will get an `it` block&lt;/span&gt;
  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should have exactly 1 `main` section&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// The getByRole will error if there are less or more than 1 element found&lt;/span&gt;
    &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Home&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;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&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;
  
  
  Add a Test Script
&lt;/h3&gt;

&lt;p&gt;The last change for Jest is to the &lt;strong&gt;package.json&lt;/strong&gt; file; Update it to add a test script under the lint script you added 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="nl"&gt;"lint.fix"&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 --ext .js ./"&lt;/span&gt;&lt;span class="err"&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;"jest"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in the project root in the terminal you can npm run test — and should see it passing!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z1dLvqv0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3548/1%2AFlTB0Avl89dbpuz19_Hi4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z1dLvqv0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3548/1%2AFlTB0Avl89dbpuz19_Hi4g.png" alt="Screen shot of passing tests" width="880" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Path Aliases/Absolute Imports
&lt;/h2&gt;

&lt;p&gt;I have seen some debate that leads me to believe path aliases are a love-it or hate-it addition to a codebase. I personally hate having to remember which particular file I’m working in and how many levels it is to import some other component or method…so I love aliasing my import paths. The difference is:&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;// (Default) Relative imports 😈: &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;Awesome&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;../../components/awesome
import { Method } from &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&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;classes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;

&lt;span class="c1"&gt;// (Aliased) Absolute imports 😇:&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;Awesome&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;@/components/awesome
import { Method } from &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="sr"&gt;/classes/m&lt;/span&gt;&lt;span class="nx"&gt;ethod&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;^ Note that the syntax I’m using, @/folder/path, is arbitrary — the @ may look fancy but it is only there to make it obvious that this isn’t an npm package or a relative import — you could name the alias paths however you like!&lt;/p&gt;

&lt;p&gt;The challenge setting these up is that once you start using them in your application &lt;em&gt;and&lt;/em&gt; in your tests, &lt;em&gt;all&lt;/em&gt; the different systems in your code that have to &lt;a href="https://www.typescriptlang.org/docs/handbook/module-resolution.html"&gt;resolve imports&lt;/a&gt; (&amp;lt;-- good explanation of resolving modules — ignore the TypeScript parts 😅) need to understand these aliases. For us, that means adding configuration for Next.js, Jest, ESLint, and VSCode 😰 … so a lot of updates to the configuration we’ve done thus far but don’t worry —it’s not &lt;em&gt;too&lt;/em&gt; drastic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Test Component
&lt;/h3&gt;

&lt;p&gt;In order to verify the aliased paths are working we need something to import. Typically you would alias the top-level folders to reference the import path from there, but the only two top-level folders we have currently aren’t really something we need to alias; Anything in pages/ probably shouldn’t be imported anywhere else, and anything in public/ can already be referenced by absolute path in &lt;code&gt;src&lt;/code&gt; or &lt;code&gt;href&lt;/code&gt; attributes.&lt;/p&gt;

&lt;p&gt;Instead, let’s create a new section in the code specifically for components. This will be two new folders and a file: &lt;strong&gt;src/components/callout/callout.js&lt;/strong&gt;. Add this to the &lt;strong&gt;callout.js&lt;/strong&gt; file:&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;PropTypes&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;prop-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Callout&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;strong&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/strong&amp;gt; {children} &amp;lt;strong style={{ color: 'red' }}&amp;gt;!&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;strong&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Callout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRequired&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Try The Component
&lt;/h3&gt;

&lt;p&gt;If you import that component in &lt;strong&gt;src/pages/index.js&lt;/strong&gt; via a relative import, you can confirm it’s working:&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;Callout&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/callout/callout&lt;/span&gt;&lt;span class="dl"&gt;'&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then wrap the component around the “Welcome…” message in the h1 tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Callout&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Welcome&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://nextjs.org&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;Callout&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then npm run dev and see: ❗️️ Welcome to Next.js! ❗️&lt;/p&gt;

&lt;p&gt;Now change &lt;strong&gt;src/pages/index.js&lt;/strong&gt; to use the aliased absolute import:&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;Callout&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/callout/callout&lt;/span&gt;&lt;span class="dl"&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--lMgWcBlz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2948/1%2AqwtcIk5THQuMRMz7pN98zw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lMgWcBlz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2948/1%2AqwtcIk5THQuMRMz7pN98zw.png" alt="Screen shot of a compile error, module not found" width="880" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;…and you should see an error, yay! Let’s fix that!&lt;/p&gt;

&lt;h3&gt;
  
  
  Next.js &amp;amp; VSCode
&lt;/h3&gt;

&lt;p&gt;Now that we have a component to test and we can see it’s not working, let’s start the configuration updates. Create a file in the project root named &lt;strong&gt;jsconfig.json&lt;/strong&gt;. This will let us &lt;a href="https://idioms.thefreedictionary.com/kill+two+birds+with+one+stone"&gt;nab two birds with one stone&lt;/a&gt; since both &lt;a href="https://code.visualstudio.com/docs/languages/jsconfig#_using-webpack-aliases"&gt;VSCode&lt;/a&gt; and &lt;a href="https://nextjs.org/docs/advanced-features/module-path-aliases"&gt;Next.js&lt;/a&gt; use this format for aliases. Add this to the file you just created:&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;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@/components/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src/components/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;^ This won’t trigger a HRM refresh, so you’ll have to stop the dev server and npm run dev again, but after that — your component should be up and running again!&lt;/p&gt;

&lt;p&gt;In the IDE, if you’ve integrated ESLint, you’ll probably see an error still about how it is “Unable to resolve path to module,” so let’s update ESLint next.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update ESLint
&lt;/h3&gt;

&lt;p&gt;The configuration for ESLint will be added to &lt;strong&gt;.eslintrc&lt;/strong&gt;, but first we need to install another package:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i -D eslint-import-resolver-alias&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;^ this package adds the functionality for ESLint to handle the resolution of aliased paths, which it can’t do by default. Update the &lt;strong&gt;.eslintrc&lt;/strong&gt; file by adding the following at the bottom, after the ignorePatterns property:&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;"ignorePatterns"&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;"node_modules/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".next/"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"settings"&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/resolver"&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;"alias"&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="s2"&gt;"@/components"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/components"&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;"@/classes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/classes"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;^ I’ve added an additional entry for a hypothetical &lt;strong&gt;/classes&lt;/strong&gt; directory to show the syntax for multiple aliases. The need for each entry to be its own array was not intuitive for me.&lt;/p&gt;

&lt;p&gt;If you npm run lint now, there shouldn’t be any module import errors (you may have some spacing/minor issues from copy-pasting, so maybe npm run lint.fix), and the IDE error should have disappeared!&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Jest
&lt;/h3&gt;

&lt;p&gt;Finally we need to update Jest. In the file &lt;strong&gt;src/pages/index.test.js&lt;/strong&gt; add an import for our Callout component:&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;Callout&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/callout/callout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Home&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;./index&lt;/span&gt;&lt;span class="dl"&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;render&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;@testing-library/react&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;… then try npm run test. You should see an error about the module:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KYg8RvUO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3548/1%2Asv3BrXwUREHq4qMq5Ku48Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KYg8RvUO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3548/1%2Asv3BrXwUREHq4qMq5Ku48Q.png" alt="Cannot find module ‘@/components/callout/callout’ from ‘src/pages/index.test.js’" width="880" height="258"&gt;&lt;/a&gt;&lt;em&gt;Cannot find module ‘@/components/callout/callout’ from ‘src/pages/index.test.js’&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The addition to fix this will go into &lt;strong&gt;jest.config.js&lt;/strong&gt;, &lt;a href="https://jestjs.io/docs/en/configuration#modulenamemapper-objectstring-string--arraystring"&gt;a property called moduleNameMapper&lt;/a&gt; which uses RegEx syntax, so is a bit more complicated:&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;customConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Automatically clear mock calls and instances between every test&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;clearMocks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// The directory where Jest should output its coverage files&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;coverageDirectory&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;.coverage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module&lt;/span&gt;
  &lt;span class="na"&gt;moduleNameMapper&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;^@/components(.*)$&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;&amp;lt;rootDir&amp;gt;/src/components$1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// A list of paths to modules that run some code to configure or set up the testing framework before each test&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setupFilesAfterEnv&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;./jest.setup.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;// By default jest will use a node environment, so DOM elements (like document) will be undefined without this&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testEnvironment&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;jsdom&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 regex is using a &lt;a href="https://javascript.info/regexp-groups"&gt;capturing group&lt;/a&gt; to take everything that comes after @/components and resolve it instead from the /components specified on the right. &lt;a href="https://regex101.com/r/hD0zR5/6"&gt;Check it out on regex101.com&lt;/a&gt; for a more complete breakdown of what’s going on.&lt;/p&gt;

&lt;p&gt;…now try npm run test, error should be gone!&lt;/p&gt;

&lt;p&gt;Since we only added it for testing, you can remove the import Callout ... line we added to &lt;strong&gt;src/pages/index.test.js&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important to remember
&lt;/h3&gt;

&lt;p&gt;When you add new aliases in the future, you’ll need to add them to three files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;jsconfig.json&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;.eslintrc&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;jest.config.js&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Complete!
&lt;/h2&gt;

&lt;p&gt;Whew, that was a lot 😰 Fantastic job getting through it all, and you now have a robust Next.js base project you can use to build from in the future!&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions? Comments?
&lt;/h2&gt;

&lt;p&gt;Find me on twitter — &lt;a href="https://twitter.com/BenjaminWFox"&gt;@BenjaminWFox&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>How to Think in Next.js</title>
      <dc:creator>Ben Fox</dc:creator>
      <pubDate>Tue, 15 Jun 2021 12:04:07 +0000</pubDate>
      <link>https://dev.to/benjaminwfox/how-to-think-in-next-js-2dh5</link>
      <guid>https://dev.to/benjaminwfox/how-to-think-in-next-js-2dh5</guid>
      <description>&lt;p&gt;Let me tell you a story about a client.&lt;/p&gt;

&lt;p&gt;This client was demanding. They wanted &lt;em&gt;all&lt;/em&gt; the things, and they wanted them &lt;em&gt;now&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Servers know this kind of client all too well. When the client comes in, asking for everything &lt;em&gt;and&lt;/em&gt; the kitchen sink, a server just has to sigh.&lt;/p&gt;

&lt;p&gt;"A lot of that is just going to go to waste, you know," says the server, softly.&lt;/p&gt;

&lt;p&gt;Their comments go unheeded.&lt;/p&gt;

&lt;p&gt;Does this client sound familiar?&lt;/p&gt;

&lt;p&gt;This client is your Single Page Application (SPA).&lt;/p&gt;

&lt;p&gt;There's a new client in town, though, and it only asks for what it &lt;em&gt;needs&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This client is Next.js.&lt;/p&gt;

&lt;p&gt;It also happens to be the server 🤔&lt;/p&gt;

&lt;h2&gt;
  
  
  Clients and Servers and Node Oh My
&lt;/h2&gt;

&lt;p&gt;Starting with Next.js after working on SPAs can be challenging (at least it was for me) with the whole server thing going on, not to mention the node.js runtime 😱&lt;/p&gt;

&lt;p&gt;It can feel like a steep learning curve, especially if you haven't worked much with Node.js, but at the end of the day remember that &lt;strong&gt;the client is still React&lt;/strong&gt;! A majority of getting comfortable with Next.js, I've found, is understanding three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client vs server contexts&lt;/li&gt;
&lt;li&gt;Page types&lt;/li&gt;
&lt;li&gt;API Routes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rfjjf9qiqok7nb6v92r.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rfjjf9qiqok7nb6v92r.jpeg" alt="The Count from Sesame Street saying "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next.js is powerful, and a lot of fun to build with once you get a handle on how it works 🏗 It combines some of the best features of traditional and single page web applications into a hybrid application.&lt;/p&gt;

&lt;p&gt;If you want a refresher &lt;a href="https://dev.to/benjaminwfox/how-does-a-website-get-its-data-and-why-does-it-matter-dgm"&gt;check out the high-level differences between the three application types&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;⚠️ Expect that things will take longer, at least at first. If you're not learning at your own pace and have to make time estimates, remember to pad those so that you have the time needed to do things correctly the 'Next' way, and not just revert to SPA patterns on top of Next.&lt;/p&gt;

&lt;p&gt;⚠️ Inevitably there will be places where adding functionality is just more complex when rendering occurs in both a server and a browser context like &lt;a href="https://redux.js.org/recipes/server-rendering#redux-on-the-server" rel="noopener noreferrer"&gt;Redux&lt;/a&gt; or &lt;a href="https://cssinjs.org/server-side-rendering" rel="noopener noreferrer"&gt;CSS-In-JS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review: SPA vs Next.js
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhput99l0cnlisbgow409.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhput99l0cnlisbgow409.jpg" alt="Visual diagram of the following SPA vs Next.js comparison list."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;In a SPA&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your code executes in the browser &lt;em&gt;only&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The entire site code bundle is downloaded upfront&lt;/li&gt;
&lt;li&gt;You should not include sensitive information (API keys, passwords, etc...)&lt;/li&gt;
&lt;li&gt;Subsequent pages are all built from bundle code&lt;/li&gt;
&lt;li&gt;You have access to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API" rel="noopener noreferrer"&gt;Web APIs&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/DOM" rel="noopener noreferrer"&gt;the DOM&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;In Next.js&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your code executes on the server &lt;em&gt;first&lt;/em&gt; and in the browser &lt;em&gt;second&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pages are pre-built and/or pre-rendered (more on that later)&lt;/li&gt;
&lt;li&gt;During API Routes &amp;amp; Data Fetching you &lt;em&gt;can&lt;/em&gt; include sensitive information&lt;/li&gt;
&lt;li&gt;You &lt;em&gt;do not&lt;/em&gt; have access to Web APIs &amp;amp; the DOM &lt;em&gt;on the server&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;You &lt;em&gt;do&lt;/em&gt; have access to a whole new set of &lt;a href="https://nodejs.org/docs/latest/api/" rel="noopener noreferrer"&gt;APIs in Node.js&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the Browser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The browser only gets the code it needs for the requested page&lt;/li&gt;
&lt;li&gt;None of the sensitive data from the server is available&lt;/li&gt;
&lt;li&gt;Subsequent pages make new requests to the server&lt;/li&gt;
&lt;li&gt;You have access to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API" rel="noopener noreferrer"&gt;Web APIs&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/DOM" rel="noopener noreferrer"&gt;the DOM&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This &lt;em&gt;also&lt;/em&gt; means implementing functionality which may have had a common approach for SPAs, &lt;a href="https://auth0.com/blog/ultimate-guide-nextjs-authentication-auth0/" rel="noopener noreferrer"&gt;like Authentication&lt;/a&gt;, now has multiple approaches to choose from depending on a variety of factors related to how you design your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution Context
&lt;/h2&gt;

&lt;p&gt;The considerations I want to focus on all revolve around the fact that there is now a server you have to deal with. At the risk of sounding obvious, I think it's hard to overstate how important this is.&lt;/p&gt;

&lt;p&gt;The biggest gotcha?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding a server adds an execution context&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider that you've essentially doubled the complexity of your application!&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;context&lt;/em&gt; in which your code &lt;em&gt;executes&lt;/em&gt; can be either the server or the client (browser). There may be code you write that can &lt;em&gt;only&lt;/em&gt; execute in one or the other of these. Common examples are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The browser globals &lt;code&gt;window&lt;/code&gt; &amp;amp; &lt;code&gt;document&lt;/code&gt; are &lt;code&gt;undefined&lt;/code&gt; on the server&lt;/li&gt;
&lt;li&gt;The Node.js File system (&lt;code&gt;fs&lt;/code&gt;) module is &lt;code&gt;undefined&lt;/code&gt; in the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Right off the bat do yourself a favor and create two utility functions to wrap code that should run in only one context:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isClient&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&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;isServer&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="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ Those methods aren't always necessary. The &lt;code&gt;useEffect&lt;/code&gt; (and &lt;code&gt;useLayoutEffect&lt;/code&gt;) React hooks will &lt;em&gt;only&lt;/em&gt; run in the browser. The API Routes and &lt;a href="https://nextjs.org/docs/basic-features/data-fetching" rel="noopener noreferrer"&gt;Data Fetching methods&lt;/a&gt; will &lt;em&gt;only&lt;/em&gt; run on the server.&lt;/p&gt;

&lt;p&gt;⚠️ Don't leave unused imports; Node.js modules that are imported and unused will throw errors. The reference won't be removed before the code goes to the client and the browser will choke on the Node.js code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Application is Starbucks
&lt;/h2&gt;

&lt;p&gt;Before we go further, let's go back to our metaphor from the beginning. &lt;/p&gt;

&lt;p&gt;Our client (a customer) walks into a Starbucks. Our server (a barista) will be ready to help with whatever the client wants.&lt;/p&gt;

&lt;p&gt;Starbucks knows certain things about what the customer might want. Since there are things they can make ahead, they have a nice selection of canned beverages (like the DOUBLESHOT) that the customer can just grab and go!&lt;/p&gt;

&lt;p&gt;The server has to do almost no work, huzzah 🥳&lt;/p&gt;

&lt;p&gt;But Starbucks also knows that the customer might be picky (&lt;a href="https://nypost.com/2021/05/03/tiktoks-edward-trend-inspires-viral-starbucks-coffee-order/" rel="noopener noreferrer"&gt;I'm looking at YOU Edward&lt;/a&gt;) so they're ready to make something crazy (the TikTok Special) on the fly.&lt;/p&gt;

&lt;p&gt;The server has to do a lot of work, dang 😰&lt;/p&gt;

&lt;p&gt;Finally, there might be some things the server can't provide. In this case the client will sneak into the bathroom with their hip flask (don't try this at home, always drink responsibly) and add their own whisky to the coffee.&lt;/p&gt;

&lt;p&gt;The server will do some work, and so does the client 🍻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwgsp08ohkby5hl43yqt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwgsp08ohkby5hl43yqt.jpg" alt="Starbucks drinks: A Doubleshot (as SSG), fancy TikTok special order (as SSR), and coffee with a shot of whisky (as CSR)."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can you guess who Starbucks is in the scenario above? It's Next.js 😆&lt;/p&gt;

&lt;p&gt;The three scenarios above encompass the choices you have when building pages in Next.&lt;/p&gt;

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

&lt;p&gt;Before building any pages it pays to step back and think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;where does your content come from?&lt;/li&gt;
&lt;li&gt;how often does your content change?&lt;/li&gt;
&lt;li&gt;how much of a page depends on certain content?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Answers to these questions will impact whether you want to implement the page via Static Site Generation (SSG), Server Side Rendering (SSR), or some combination of those mixed with client side rendering (CSR).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSG&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Grab-and-Go: The fastest choice, &lt;a href="https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation" rel="noopener noreferrer"&gt;Static Site Generation&lt;/a&gt; means little to no processing on the server &amp;amp; best for &lt;a href="https://moz.com/learn/seo/what-is-seo" rel="noopener noreferrer"&gt;SEO&lt;/a&gt; &amp;amp; &lt;a href="https://web.dev/vitals/" rel="noopener noreferrer"&gt;Core Web Vitals&lt;/a&gt;. The server only has to return pre-built, static content.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Statically generated pages are still reactive: Next.js will &lt;a href="https://reactjs.org/docs/react-dom.html#hydrate" rel="noopener noreferrer"&gt;hydrate&lt;/a&gt; your application client-side to give it full interactivity." - &lt;a href="https://nextjs.org/docs/advanced-features/automatic-static-optimization" rel="noopener noreferrer"&gt;Next.js Documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use this option with content that doesn't change frequently (or ever). Blogs, marketing sites, policy documents, and FAQs all fall more or less in this category.&lt;/p&gt;

&lt;p&gt;This can get cumbersome on sites with many (thousands or more) pages, but can be mitigated to some degree with &lt;a href="https://vercel.com/docs/next.js/incremental-static-regeneration#" rel="noopener noreferrer"&gt;incremental static regeneration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The TikTok Special: &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; means rather than serving pre-built pages, the server builds the page when it is requested. The browser still gets static content, but data fetching &amp;amp; processing likely means longer time to &lt;a href="https://web.dev/lcp/" rel="noopener noreferrer"&gt;largest contentful paint&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's an excellent option for pages that depend on particular input data and where it isn't possible (or feasible) to statically generate all page combinations for given inputs.&lt;/p&gt;

&lt;p&gt;Input data might be something like user details, purchase/order history, weather, time, or traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Hip Flask: &lt;a href="https://nextjs.org/docs/basic-features/data-fetching#fetching-data-on-the-client-side" rel="noopener noreferrer"&gt;Client Side Rendering&lt;/a&gt; can be &lt;em&gt;added&lt;/em&gt; in addition to either of the strategies above. It can serve as a strategy to defer loading &lt;em&gt;some&lt;/em&gt; page content so that &lt;em&gt;most&lt;/em&gt; content can be ready faster via SSG or SSR.&lt;/p&gt;

&lt;p&gt;The deferred content might be frequently updating/real-time data like a stock chart or chatbar, or content with a particularly long load time.&lt;/p&gt;

&lt;p&gt;⚠️ Be mindful that if some content is not readily available there may be impact to SEO and issues with &lt;a href="https://web.dev/cls/" rel="noopener noreferrer"&gt;cumulative layout shift&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;⚠️ Remember that page code may be executed on both the server and client! If you have any sensitive information in environment variables or other stores be careful that it doesn't get sent to the client accidentally.&lt;/p&gt;

&lt;h2&gt;
  
  
  API Routes
&lt;/h2&gt;

&lt;p&gt;Let's extend our metaphor above even further! Consider an espresso maker, a beautiful and complex machine that you &lt;em&gt;definitely&lt;/em&gt; do not want your customers, err I mean clients, touching.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6q68kdvqrll0o344msvw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6q68kdvqrll0o344msvw.jpg" alt="Picture of a commercial espresso machine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To shield the clients from the complexity of the espresso maker, the client makes a &lt;strong&gt;request&lt;/strong&gt; of the server. The server goes off and deals with all the complicated bits, and after a while the order is ready. Then the server gives a &lt;strong&gt;response&lt;/strong&gt;, "Edward, I have your Venti Caramel Crunch Frappuccino!"&lt;/p&gt;

&lt;p&gt;Until the response arrives, the client is free to doomscroll TikTok looking for cat videos and a new crazy coffee drink.&lt;/p&gt;

&lt;p&gt;Your API Routes in Next.js mirror that interaction. They won't get you coffee, but if you build them right they can get you cat memes.&lt;/p&gt;

&lt;p&gt;⚠️ Remember this is in the server context. You can use sensitive keys, secrets, passwords, and connection strings if required. You could interact with the filesystem, say, to pull in markdown documents for creating content. You could add an ORM like Prisma to interact with a database.&lt;/p&gt;

&lt;p&gt;⚠️ Server-only context extends beyond API Routes. It also includes the Data Fetching methods &lt;code&gt;getServerSideProps&lt;/code&gt;, &lt;code&gt;getStaticProps&lt;/code&gt;, and &lt;code&gt;getStaticPaths&lt;/code&gt;. These methods are more specialized and I won't be going into more detail on them here, but the documentation linked in the pages section for each of the three types are great resources.&lt;/p&gt;

&lt;p&gt;For reference, an API Route looks something like:&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="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="c1"&gt;// Do lots of processing...call apis...access database...&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&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="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;Next.js&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;Simple right? 😬&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Request&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You're probably familiar with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="noopener noreferrer"&gt;fetching data&lt;/a&gt; from APIs from the SPA architecture. Now you're on the API side of that transaction.&lt;/p&gt;

&lt;p&gt;The request, or &lt;code&gt;req&lt;/code&gt; object, will have all kinds of information about the request that the client has made. This includes headers, referrers, browser information.&lt;/p&gt;

&lt;p&gt;In API Routes there is also &lt;a href="https://nextjs.org/docs/api-routes/api-middlewares" rel="noopener noreferrer"&gt;extra data added by Next&lt;/a&gt; which includes objects for &lt;code&gt;cookies&lt;/code&gt;, &lt;code&gt;query&lt;/code&gt;, and &lt;code&gt;body&lt;/code&gt; if that information is present.&lt;/p&gt;

&lt;p&gt;If you're doing &lt;a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete" rel="noopener noreferrer"&gt;CRUD operations&lt;/a&gt; pay especially close attention to the &lt;code&gt;method&lt;/code&gt; the client is using, since &lt;a href="https://stackoverflow.com/q/6203231/1763258" rel="noopener noreferrer"&gt;you'll want to respond differently to different methods&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Response&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The response, or &lt;code&gt;res&lt;/code&gt; sends information back to the client. It's important to always send back a response or the browser request will never finish, drifting endlessly in the wind.&lt;/p&gt;

&lt;p&gt;Similar to the &lt;code&gt;req&lt;/code&gt; object, the &lt;code&gt;res&lt;/code&gt; object in API Routes has &lt;a href="https://nextjs.org/docs/api-routes/response-helpers" rel="noopener noreferrer"&gt;some extra helper methods&lt;/a&gt; added by Next, which make building the response easier than default Node.js &lt;code&gt;http.ServerResponse&lt;/code&gt; functionality. It tripped me up when I saw these helpers used in tutorials but couldn't find them referenced in the Node.js documentation.&lt;/p&gt;

&lt;p&gt;And with the response sent you're all wrapped up and ready to get on with building something new and exciting!&lt;/p&gt;

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

&lt;p&gt;I hope that this has given you some new insight as you get started with Next.js!&lt;/p&gt;

&lt;p&gt;If you're looking to set up Next.js beyond the basic scaffold, &lt;a href="https://benjaminwfox.com/blog/tech/nextjs-setup-config-testing-linting-absolute-imports" rel="noopener noreferrer"&gt;check on my tutorial on adding tests, linting, and absolute imports&lt;/a&gt; to a Next.js project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions? Comments?
&lt;/h2&gt;

&lt;p&gt;Follow me on Twitter &lt;a href="https://twitter.com/BenjaminWFox" rel="noopener noreferrer"&gt;@BenjaminWFox&lt;/a&gt; for more tech and leadership content, and reach out with any thoughts or questions!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>How Does a Website Get its Data, and Why Does it Matter?</title>
      <dc:creator>Ben Fox</dc:creator>
      <pubDate>Tue, 15 Jun 2021 03:40:08 +0000</pubDate>
      <link>https://dev.to/benjaminwfox/how-does-a-website-get-its-data-and-why-does-it-matter-dgm</link>
      <guid>https://dev.to/benjaminwfox/how-does-a-website-get-its-data-and-why-does-it-matter-dgm</guid>
      <description>&lt;h2&gt;
  
  
  Servers to No Servers to Serverless
&lt;/h2&gt;

&lt;p&gt;In the beginning, there were servers.&lt;/p&gt;

&lt;p&gt;The servers roamed the wild, waiting for clients and their connections, and when a server received a connection it would pounce. The servers liked the connections and held on to them, guarding them closely.&lt;/p&gt;

&lt;p&gt;Thus the traditional web app was born.&lt;/p&gt;

&lt;p&gt;But the clients grew tired of the servers, which were needy and somehow both clingy &lt;em&gt;and&lt;/em&gt; flakey.&lt;/p&gt;

&lt;p&gt;"Give us back our connections!" cried the clients, "On our terms!"&lt;/p&gt;

&lt;p&gt;"We will just stop by to grab all the things when we need them," the clients went on, "that's really all we need."&lt;/p&gt;

&lt;p&gt;Thus the single page application was born.&lt;/p&gt;

&lt;p&gt;But the clients grew lonely. They had no one to tell their secrets to, and no one to help rearrange the furniture.&lt;/p&gt;

&lt;p&gt;"Maybe we could work out a friends with benefits kind of thing?" mused the clients.&lt;/p&gt;

&lt;p&gt;The servers were into it.&lt;/p&gt;

&lt;p&gt;Thus Next.js was born.&lt;/p&gt;

&lt;h2&gt;
  
  
  Say What Now?
&lt;/h2&gt;

&lt;p&gt;Ok, if the epic story of creation didn't do it, let's try again with pictures.&lt;/p&gt;

&lt;p&gt;I've been building on the web for what feels like a long time, and I haven't reviewed the basics of how a site works in recent memory. I've been working with Next.js a lot over the last year, and I thought I'd write some notes to refresh my memory on how my sites used to work, and how they work now.&lt;/p&gt;

&lt;p&gt;The story of each application had three main players, the:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Screen (or other interface) to drive input on the client&lt;/li&gt;
&lt;li&gt;Client (the browser) to interact with the server to get data&lt;/li&gt;
&lt;li&gt;Server to send data to the client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The client sends a request to the server for some stuff. The server sends that stuff back to the client. The client does things to it, and &lt;strong&gt;&lt;em&gt;bam&lt;/em&gt;&lt;/strong&gt; it's available to show on the screen.&lt;/p&gt;

&lt;p&gt;Exactly what happens at each of those steps differs a little depending on whether you're talking about a traditional, single page, or hybrid/serverless (like Next.js) application.&lt;/p&gt;

&lt;p&gt;Let's dive in to a high level overview of what those differences are. In all cases, the first two steps and the final step are the same:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The screen triggers a page request&lt;/li&gt;
&lt;li&gt;The client sends a page request to the server&lt;/li&gt;
&lt;li&gt;??&lt;/li&gt;
&lt;li&gt;??&lt;/li&gt;
&lt;li&gt;Profit! The screen displays the page&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So let's look specifically at steps 3 and 4 for each application!&lt;/p&gt;

&lt;h3&gt;
  
  
  Traditional Server App
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jmzwa87o2etissqae35.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jmzwa87o2etissqae35.jpg" alt="traditional app flow diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Server grabs or builds the requested page&lt;/li&gt;
&lt;li&gt;Client receives ready-to-display page&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This process will repeat itself every time. New page requested, new request fulfilled. In a traditional app servers are &lt;em&gt;also&lt;/em&gt; often stateful, so could remember details about a specific connection &lt;em&gt;in between&lt;/em&gt; requests, and use that stored information for each connection to build pages on subsequent requests.&lt;/p&gt;

&lt;p&gt;Page loads can be slow and unoptimized, and the UI refreshes for all transitions. &lt;a href="https://en.wikipedia.org/wiki/Ajax_(programming)" rel="noopener noreferrer"&gt;AJAX&lt;/a&gt; offered some additional flexibility but it was clunky to implement and rarely felt like a first-class citizen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single Page App
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ueqff3lkcleco9ifsfh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ueqff3lkcleco9ifsfh.jpg" alt="single page app flow diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Server grabs a bundle of stuff (like JavaScript and CSS)&lt;/li&gt;
&lt;li&gt;Client receives &amp;amp; processes the bundle to build pages&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Right up front the client has grabbed &lt;em&gt;everything&lt;/em&gt; it needs, for better or worse. No more requests to the server need to be made &lt;em&gt;for pages&lt;/em&gt;, which will all be built from the bundle that the browser now controls. Other requests might be made for data, either from the same server or other APIs.&lt;/p&gt;

&lt;p&gt;Bundles can grow quite large, increasing load times and degrading user experience. Bundle splitting was one solution to that problem, but it could get complex and was often poorly implemented, if at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next.js or Hybrid App
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqba4sws4537xa9ya8wv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqba4sws4537xa9ya8wv.jpg" alt="Next.js hybrid serverless app flow diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Server grabs or builds the requested page&lt;/li&gt;
&lt;li&gt;Client receives a page that may requires some processing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First a note on &lt;em&gt;serverless&lt;/em&gt;, which only means that the servers are run and maintained by a 3rd party. The term is commonly used in tandem with hybrid apps, but it's just a reference to how they're deployed. One way or another, there are still servers involved.&lt;/p&gt;

&lt;p&gt;The hybrid app is like the traditional app where new pages are requested from the server, but there is &lt;em&gt;a lot&lt;/em&gt; more flexibility, hence the "hybrid" designation. Fetching new data has first-class support. The types of pages available on the server have explicitly defined options and can be entirely ready-to-serve or generated at request-time. &lt;/p&gt;

&lt;p&gt;Like the single page app, a page in hybrid applications like Next.js can also still have large portions that need to be processed on the client.&lt;/p&gt;

&lt;p&gt;This flexibility comes with increased complexity, and unlike the traditional app, this server is &lt;em&gt;not&lt;/em&gt; stateful. It knows nothing about a connection except what is provided in the incoming request.&lt;/p&gt;

&lt;h2&gt;
  
  
  At the End
&lt;/h2&gt;

&lt;p&gt;None of these approaches are inherently better or worse than the others, and don't let anyone tell you otherwise. All have pros and cons. One may work better for a particular use case than another, but that will depend on project-specific requirements, so you'll have to do your homework once you determine what those are.&lt;/p&gt;

&lt;p&gt;And you should &lt;strong&gt;&lt;em&gt;definitely&lt;/em&gt;&lt;/strong&gt; determine your requirements up front! 😉&lt;/p&gt;

&lt;p&gt;The first time I lobbied to build a site with Next.js I ended up stripping it out a month later 🤦‍♂️ it became clear that there was actually only a single page with different sections of the page that changed at certain times, so back to the single page app I went!&lt;/p&gt;

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

&lt;p&gt;If you're just getting started with Next.js, check out my thoughts on &lt;a href="https://benjaminwfox.com/blog/tech/how-to-think-in-nextjs" rel="noopener noreferrer"&gt;How to Think in Next.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're setting up a new project, check on my tutorial on &lt;a href="https://benjaminwfox.com/blog/tech/nextjs-setup-config-testing-linting-absolute-imports" rel="noopener noreferrer"&gt;Next.js setup with tests, linting, and absolute imports&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck and happy programming!&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions? Comments?
&lt;/h2&gt;

&lt;p&gt;Follow me on Twitter &lt;a href="https://twitter.com/BenjaminWFox" rel="noopener noreferrer"&gt;@BenjaminWFox&lt;/a&gt; for more tech and leadership content, and reach out with any thoughts or questions!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>serverless</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
    <item>
      <title>Atomic Design for Developers: Better Component Composition and Organization</title>
      <dc:creator>Ben Fox</dc:creator>
      <pubDate>Sun, 09 May 2021 03:11:44 +0000</pubDate>
      <link>https://dev.to/benjaminwfox/atomic-design-for-developers-better-component-composition-and-organization-2n3l</link>
      <guid>https://dev.to/benjaminwfox/atomic-design-for-developers-better-component-composition-and-organization-2n3l</guid>
      <description>&lt;h4&gt;
  
  
  &lt;em&gt;A practical guide to developing component based sites and apps around the Atomic Design methodology.&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;Organizing your application (or app/site, I'll use these interchangeably) can seem easy. A folder for components, one for assets, another for utility methods. Maybe even a separate folder for pages! Don't be fooled, it is almost never that easy...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1k169945jq2pkwlhph4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1k169945jq2pkwlhph4.png" alt="Graphic of react logos consuming progressively smaller logos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"It's alright. This place just needs a one-hour bureaucratizing."&lt;/p&gt;

&lt;p&gt;— Hermes Conrad&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hermes Conrad would agree that what your app needs is a good, one-hour bureaucratizing. Hooray for rules and regulations! I'm not normally for bureaucracy but as your app starts to grow you should have a way to organize things that provides more granular organization, separation and, importantly, is based on explicit rules and guidelines rather than guesswork or instinct.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Goal
&lt;/h3&gt;

&lt;p&gt;I'll provide a little background, but there is a lot of content out there about Atomic Design generally, both from designers and developers. My main goal is three-fold:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enumerate the rules I've found that work for me and my team when determining how to categorize a component.&lt;/li&gt;
&lt;li&gt;Provide code showing implementation for each of the five categories.&lt;/li&gt;
&lt;li&gt;Show usage of these components in the context of a "real" site.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Please note:&lt;/strong&gt; You are free to disagree with any/all of the rules I present. You may find that they do not cover every edge case. I'd love to &lt;a href="https://twitter.com/benjaminwfox" rel="noopener noreferrer"&gt;hear any thoughts and opinions&lt;/a&gt;. My hope is that you come away with an idea of how to implement this methodology in a way that works for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Backstory&lt;/li&gt;
&lt;li&gt;Atomic Design&lt;/li&gt;
&lt;li&gt;Why this Article&lt;/li&gt;
&lt;li&gt;Why NOT this Article&lt;/li&gt;
&lt;li&gt;Sample Code&lt;/li&gt;
&lt;li&gt;
Atoms

&lt;ul&gt;
&lt;li&gt;Examples of Atoms&lt;/li&gt;
&lt;li&gt;Rules of Atoms&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Molecules

&lt;ul&gt;
&lt;li&gt;Examples of Molecules&lt;/li&gt;
&lt;li&gt;A Nebulous Molecule&lt;/li&gt;
&lt;li&gt;Rules of Molecules&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Organisms

&lt;ul&gt;
&lt;li&gt;Examples of Organisms&lt;/li&gt;
&lt;li&gt;Rules of Organisms&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Templates

&lt;ul&gt;
&lt;li&gt;Examples of Templates&lt;/li&gt;
&lt;li&gt;Template Variations&lt;/li&gt;
&lt;li&gt;Tiered Templates&lt;/li&gt;
&lt;li&gt;Rules of Templates&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Pages

&lt;ul&gt;
&lt;li&gt;Examples of Pages&lt;/li&gt;
&lt;li&gt;Rules of Pages&lt;/li&gt;
&lt;li&gt;A Note on Routes&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Conclusion

&lt;ul&gt;
&lt;li&gt;One Rule to Rule Them All&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Backstory
&lt;/h2&gt;

&lt;p&gt;A few years back I was searching for a better way to organize components in web apps. The designers I was working with at the time were adopting a design system that followed Atomic Design principles and it seems like that would translate well into the front-end development space since ultimately our work was to implement the components created by the design team.&lt;/p&gt;

&lt;p&gt;Having a common language to use for categorizing components seemed like a no-brainer, although for a variety of reasons unrelated to Atomic Design this didn't end up being the case between our designers and engineers. &lt;/p&gt;

&lt;p&gt;It did work out pretty well for the engineering team internally though so, good news, you don't need to have buy-in and adoption from designers to start using these principles for development!&lt;/p&gt;

&lt;h2&gt;
  
  
  Atomic Design
&lt;/h2&gt;

&lt;p&gt;Atomic Design is a methodology for creating design systems created by &lt;a href="https://bradfrost.com/" rel="noopener noreferrer"&gt;Brad Frost&lt;/a&gt;. You can &lt;a href="https://bradfrost.com/blog/post/atomic-web-design" rel="noopener noreferrer"&gt;read his full post&lt;/a&gt; for a comprehensive overview.&lt;/p&gt;

&lt;p&gt;For the purposes of this article it's important to know that Atomic Design breaks design systems (and the components that make up an application) into a hierarchy with five levels.&lt;/p&gt;

&lt;p&gt;It begins at the smallest component level (atoms) and combining those to create larger components (molecules) which themselves get combined into still larger components (organisms) which are then displayed in logical groups (templates) that make up the app (pages).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Atoms -&amp;gt; Molecules -&amp;gt; Organisms -&amp;gt; Templates -&amp;gt; Pages&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article I'm going to talk about applying Atomic Design principles to front-end development. I'll be using React for specific examples, but the definitions and principles should apply to any component or composition based UI applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this Article
&lt;/h2&gt;

&lt;p&gt;The biggest challenge I faced with my team after deciding to use Atomic Design principles as the basis for our component organization and hierarchy was figuring out what components went into which buckets. There were some other writeups I found that had bits and pieces of details, but I never found anything that gave both a prescriptive example of how each level might be delineated and examples of implementation and usage.&lt;/p&gt;

&lt;p&gt;When you're building reusable components there are a lot of considerations, including decisions like how a component is structured, what data it needs, where that data lives, if (and where) state is needed, and so on. Since you've (hopefully) already made most, or all, of those decisions before starting the build the component, you can use them as a set of heuristics to store your component where it makes the most sense.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;heuristic&lt;/em&gt;&lt;/strong&gt; - a practical method [for decision making] that is not guaranteed to be optimal, perfect, or rational, but is nevertheless sufficient for reaching an immediate, short-term goal.&lt;/p&gt;

&lt;p&gt;— &lt;a href="https://en.wikipedia.org/wiki/Heuristic" rel="noopener noreferrer"&gt;wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I say heuristics intentionally, since you're certain to find edge cases or gray areas in any methodology. The goal is to make sure those are few and far between, so you're left with a system of organization providing maximum &lt;strong&gt;reusability, flexibility, and composability&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Atomic design is not a linear process, but rather a mental model to help us think of our user interfaces as both a cohesive whole and a collection of parts at the same time.&lt;/p&gt;

&lt;p&gt;— Brad Frost&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why NOT this Article
&lt;/h2&gt;

&lt;p&gt;In my experience this approach is best suited to applications that are (or expect to be) large, frequently updated, and/or frequently extended.&lt;/p&gt;

&lt;p&gt;It helps to have a well-planned design and information hierarchy, but it's not strictly necessary. Even with relatively simple mockups or wireframes you can start to develop a sense of what parts of the UI build upon one another.&lt;/p&gt;

&lt;p&gt;I would not use this approach if I were working on libraries or applications that were relatively limited in scope, complexity, or life expectancy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Code
&lt;/h2&gt;

&lt;p&gt;Throughout this article I'll be sharing and referring to code that I've developed in the form of a relatively simple list/todo app. There's no interactive functionality. It's designed to show visually &amp;amp; structurally how components build on one another other using Atomic Design. On the site, you can take a look at &lt;a href="https://atomic-design-example.benjaminwfox.com/settings" rel="noopener noreferrer"&gt;the /settings page&lt;/a&gt; to toggle outlines for various levels of components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://atomic-design-example.benjaminwfox.com/" rel="noopener noreferrer"&gt;https://atomic-design-example.benjaminwfox.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Repository: &lt;a href="https://github.com/BenjaminWFox/example-app-atomic-design" rel="noopener noreferrer"&gt;https://github.com/BenjaminWFox/example-app-atomic-design&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Atoms
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;atom&lt;/strong&gt; is the most basic component, as generic as can be.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples of Atoms
&lt;/h3&gt;

&lt;p&gt;Icons, buttons, links, and labels are good examples of atoms. They don't do much on their own, and many other components on a site will typically depend on using these in one way or another. They can be used virtually anywhere throughout a site, so they have a lot of flexibility. Let's look at a very basic example, the &lt;code&gt;Button&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;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;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;label&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&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;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&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 is about as basic as it gets. Not even any styles needed here. While that may not be the case for most sites, styles would not add much complexity and wouldn't change anything about the "Atomness" of the &lt;code&gt;Button&lt;/code&gt;. Another example, a &lt;code&gt;BlockLink&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;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="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;BlockLink&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;href&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;underline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For whatever reason, the demo site I built has a frequent need for block-display links! In this case importing a framework primitive is fine. It's smaller than an Atom. You can call it a &lt;em&gt;neurotron&lt;/em&gt; if you want, that's a cool-sounding made-up word 😎 ⚛️. The &lt;code&gt;Link&lt;/code&gt; is just an abstraction of the &lt;code&gt;a&lt;/code&gt; tag with framework-specific functionality. It doesn't do anything from a style or markup perspective.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl303fhsp6gnk469yo3kk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl303fhsp6gnk469yo3kk.png" alt="Screenshot."&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Visual example of Atoms: &lt;code&gt;BlockLink&lt;/code&gt;, &lt;code&gt;Button&lt;/code&gt;, and &lt;code&gt;Icon&lt;/code&gt; components.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Rules of Atoms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Should not compose other components/only uses &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element" rel="noopener noreferrer"&gt;native elements&lt;/a&gt; or framework-specific components similar to native elements&lt;/li&gt;
&lt;li&gt;Can have its own markup &amp;amp; styles &lt;/li&gt;
&lt;li&gt;Can maintain its own internal state&lt;/li&gt;
&lt;li&gt;Should not be tightly coupled to specific UI or Logic areas&lt;/li&gt;
&lt;li&gt;Should not access application (or higher level) state directly&lt;/li&gt;
&lt;li&gt;Should not have any non-ui/layout related side effects&lt;/li&gt;
&lt;li&gt;Should not implement any application-specific business logic&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Molecules
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;molecule&lt;/strong&gt; composes atoms to create a more complex component, with its own markup and styling added to the mix. Aside from that, the rules I use for molecules are virtually identical to those of atoms.&lt;/p&gt;
&lt;h3&gt;
  
  
  Examples of Molecules
&lt;/h3&gt;

&lt;p&gt;Molecules, being made up of Atoms, tend to be a little more specific in usage, but (and this is of course also design dependant) they should also still be reusable in areas throughout the site. Below is an example atom &lt;code&gt;ImageWithOverlay&lt;/code&gt; that overlays some text onto an image. It doesn't have much in the way of specific styling besides positioning the text.&lt;/p&gt;

&lt;p&gt;Below that is a molecule &lt;code&gt;BannerImage&lt;/code&gt; that composes &lt;code&gt;ImageWithOverlay&lt;/code&gt; to create a banner designed specifically to be added at the start of content, flush with the top &amp;amp; side margins of its parent element.&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;// /atoms/image-with-overlay.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&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;./image-with-overlay.module.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Image&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/image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ImageWithOverlay&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fill&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;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;caption&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;title&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&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;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt; : null&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;subtitle&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt; : null&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Image&lt;/span&gt;
        &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;objectFit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cover&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;objectPosition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// /molecules/banner-image.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Image&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/image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&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;./banner-image.module.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ImageWithOverlay&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;../atoms/image-with-overlay&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;BannerImage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;
      &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;banner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flush-width&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;flush-top&lt;/span&gt;&lt;span class="dl"&gt;'&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="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ImageWithOverlay&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare the &lt;code&gt;BannerImage&lt;/code&gt; here (stretched to the top &amp;amp; side margins) against the &lt;code&gt;ImageWithOverlay&lt;/code&gt; in the previous screenshot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2ffv6oud33tdbtsrxb9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2ffv6oud33tdbtsrxb9.png" alt="Image showing the  raw `BannerImage` endraw  component."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A Nebulous Molecule
&lt;/h3&gt;

&lt;p&gt;There are a few components in the example project that, on first glance, don't fit neatly into the molecule definition. The &lt;code&gt;SidebarLinkList&lt;/code&gt;, &lt;code&gt;HeaderLinkList&lt;/code&gt;, and &lt;code&gt;HeaderIconList&lt;/code&gt; fall into this category. They are all about the same, and render a collection of children in a single &lt;code&gt;div&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;styles&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;./header-link-list.module.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HeaderLinkList&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headerLinkList&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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 reason I've labeled these as molecules is that while they don't explicitly compose any atoms, they all depend implicitly on a specific atom being passed as &lt;code&gt;children&lt;/code&gt;. In the case here of the &lt;code&gt;HeaderLinkList&lt;/code&gt;, all the children should be &lt;code&gt;BlockLink&lt;/code&gt; components. If the example app were more robust, I might create a custom &lt;code&gt;PropType&lt;/code&gt; entry to throw an error if any of the &lt;code&gt;children&lt;/code&gt; were not &lt;code&gt;BlockLink&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rules of Molecules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A component made up of one or more Atoms&lt;/li&gt;
&lt;li&gt;Can have its own markup &amp;amp; styles&lt;/li&gt;
&lt;li&gt;Can maintain its own internal state&lt;/li&gt;
&lt;li&gt;Should not be tightly coupled to specific UI or Logic areas&lt;/li&gt;
&lt;li&gt;Should not access application (or higher level) state directly&lt;/li&gt;
&lt;li&gt;Should not have any non-ui/layout related side effects&lt;/li&gt;
&lt;li&gt;Should not implement any application-specific business logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Organisms
&lt;/h2&gt;

&lt;p&gt;Organisms are where the business logic of your application starts to come out. They might correspond to a specific feature or section of the app. They may also be generally applicable but tightly coupled with the application logic. Data fetching and reading/writing to application state should primarily happen here (or alternatively at the Page level).&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples of Organisms
&lt;/h3&gt;

&lt;p&gt;One of the more basic organisms in the sample app is the &lt;code&gt;SidebarNavigation&lt;/code&gt;. At two molecules and one atom, it has not grown terribly complex, but it is &lt;em&gt;specialized enough&lt;/em&gt; - designed to live in the sidebar and further composes a molecule - that it is no longer a molecule itself.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Constructing organisms might be a good time to re-evaluate your other components. Do they really belong where you've categorized them? If they &lt;em&gt;are&lt;/em&gt; categorized in the correct place, have you named them appropriately?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Literally as I am writing this, I noticed that in the &lt;code&gt;SidebarNavigation&lt;/code&gt; component I had named &lt;code&gt;IconHeading&lt;/code&gt; as &lt;code&gt;SidebarTitle&lt;/code&gt;, and &lt;code&gt;VerticalListLayout&lt;/code&gt; as &lt;code&gt;SidebarLinkList&lt;/code&gt; 😱 &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's sub-optimal!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why? There isn't anything explicitly sidebar-related about those two components!&lt;/p&gt;

&lt;p&gt;It just happened that the sidebar was the only place they had been implemented. While I feel I was correct in making them molecules (even that may be debatable for the &lt;code&gt;VerticalListLayout&lt;/code&gt;, but meh...heuristics), if they were &lt;em&gt;actually&lt;/em&gt; only usable within the context of the sidebar adding them as organisms may have been more appropriate.&lt;/p&gt;

&lt;p&gt;After re-naming those two components to ensure they're more generalized, my &lt;code&gt;SidebarNavigation&lt;/code&gt; component looks like:&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;SidebarLinkList&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;../molecules/sidebar-link-list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;BlockLink&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;../atoms/block-link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SidebarTitle&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;../molecules/sidebar-title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SidebarNavigation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sidenav&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selected&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="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IconHeading&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;VerticalListLayout&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;sidenav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&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;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;entry&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;`&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;entry&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="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlockLink&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&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;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/BlockLink&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;})}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/VerticalListLayout&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;)
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;SidebarNavigation&lt;/code&gt; component is used in other more specific components like the &lt;code&gt;ListSidebar&lt;/code&gt;. In this example it doesn't do a whole lot, but it would eventually require business logic for handling things like the button.&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;SidebarNavigation&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/organisms/sidebar-navigation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Button&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;../atoms/button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ListSidebar&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;category&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;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sidenav&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;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Add List Functionality not implemented!&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;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SidebarNavigation&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&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;subtitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;sidenav&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;sidenav&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add List&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/SidebarNavigation&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rules of Organisms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A complex component made up of multiple atoms and/or molecules and/or other organisms&lt;/li&gt;
&lt;li&gt;Can have its own markup &amp;amp; styles&lt;/li&gt;
&lt;li&gt;Can fetch application-specific data&lt;/li&gt;
&lt;li&gt;Can implement application-specific business logic&lt;/li&gt;
&lt;li&gt;Can be connected to application (or higher level) state&lt;/li&gt;
&lt;li&gt;Can be tightly coupled with a specific area (UI and/or Logic) of the app&lt;/li&gt;
&lt;li&gt;Can be organized into sub-folders by logical categorization (feature, page, etc...)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Templates
&lt;/h2&gt;

&lt;p&gt;Templates are a way to ensure that the Pages of your app are consistent. They handle creating the layout, and make it easy to know where specific areas of content or functionality need to go. There are a number of ways to create templates. The way I'm going to show is very explicit, and I like it because it helps force high-level separation of application logic (into pages and organisms) and application layout (in templates).&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples of Templates
&lt;/h3&gt;

&lt;p&gt;In React this is not a pattern I've seen very often, although I have seen at least a couple articles where it was discussed. That may be because people more often talk about lower-level (atom/molecule/organism) or higher-level (page) components 🤷‍♂️&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;styles&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;../../styles/Home.module.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TemplateSidebarContent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&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;header&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;aside&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sidebar&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;sidebar&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/aside&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&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;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/section&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component really doesn't do much right?! The css import does most of the heavy lifting, but even then it's not much - primarily setting &lt;code&gt;flex&lt;/code&gt; properties, widths, and heights. It's not until this component is composed into Pages that the good times start rolling 🥳 as each of those props (&lt;code&gt;header&lt;/code&gt;/&lt;code&gt;sidebar&lt;/code&gt;/&lt;code&gt;content&lt;/code&gt;) will be an individual component that we can count on to be placed on screen exactly as intended. 🤓&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8q3pkfpifehn13l79mz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8q3pkfpifehn13l79mz4.png" alt="Screenshot."&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A template, highlighting the Header, Sidebar, and Content&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Template Variations
&lt;/h3&gt;

&lt;p&gt;It can be tempting to start adding additional props to templates to support 'variations' like a border, a background color, or other minor stylistic differences. Is this something I've done? 👀 Yes. Is this something you should do? No. Is it the end of the world if you do? Also no.&lt;/p&gt;

&lt;p&gt;Just consider that the more thought that has to go into using the template component, the less useful it becomes. The beauty is in its simplicity and not having to worry about high-level details of how the site is laid out on the page.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tiered Templates
&lt;/h3&gt;

&lt;p&gt;It's worth noting that templates don't &lt;em&gt;have&lt;/em&gt; to be implemented only at the page level. Suppose you're using a template to lay out the highest-level elements of the site (header, sidebar, content area) as you'll see in the next section, you may find that you &lt;em&gt;also&lt;/em&gt; want templates to lay out content within the content area!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Templates are an excellent choice anywhere a consistent layout is reused with different content.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Rules of Templates
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A component that facilitates the layout of multiple organisms&lt;/li&gt;
&lt;li&gt;Can have its own markup &amp;amp; styles.&lt;/li&gt;
&lt;li&gt;Can accept &amp;amp; pass props as required.&lt;/li&gt;
&lt;li&gt;Should not access application (or higher level) state&lt;/li&gt;
&lt;li&gt;Should not have any non-ui/layout related side effects&lt;/li&gt;
&lt;li&gt;Should not implement any application-specific business logic&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Pages
&lt;/h2&gt;

&lt;p&gt;Pages are the final piece of the puzzle, and each one will implement a specific Template. Pages are distinctly separate from Routing, and while I'm not covering Routing in this article it should at least be said that in the same way each Page implements a Template, each Route should implement a Page.&lt;/p&gt;

&lt;p&gt;Because I'm using React with Next.js, which has page-based routing, I've made a specific delineation in my project structure. All Atomic Design Pages live under &lt;code&gt;/src/components/pages&lt;/code&gt;, and all Routes live under &lt;code&gt;/src/pages&lt;/code&gt;. Excluding the special &lt;code&gt;_app.js&lt;/code&gt;, there is a 1:1 ratio of component pages to route pages.&lt;/p&gt;
&lt;h3&gt;
  
  
  Examples of Pages
&lt;/h3&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;TemplateSidebarContent&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;../templates/template-sidebar-content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserHeader&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/organisms/user-header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CategoryDetails&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/organisms/category-details&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CategorySidebar&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/organisms/category-sidebar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Category&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;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sidenav&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TemplateSidebarContent&lt;/span&gt;
    &lt;span class="nx"&gt;header&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserHeader&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;sidebar&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;CategorySidebar&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&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;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;sidenav&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;sidenav&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="nx"&gt;content&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;CategoryDetails&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;  &lt;span class="o"&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;For each page I'll pick both the template and the components to fill the template. These could be fairly general-use like the &lt;code&gt;UserHeader&lt;/code&gt;, which is used on all pages. They can also be specific use like the &lt;code&gt;CategoryDetails&lt;/code&gt; organism. As mentioned in the Templates section, &lt;code&gt;CategoryDetails&lt;/code&gt; &lt;em&gt;could&lt;/em&gt; implement another template if needed! Heck, either of the other components could implement another template as well if the content were complex enough!&lt;/p&gt;
&lt;h3&gt;
  
  
  Rules of Pages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A component that implements a particular template&lt;/li&gt;
&lt;li&gt;Can fetch application-specific data&lt;/li&gt;
&lt;li&gt;Can implement application-specific business logic&lt;/li&gt;
&lt;li&gt;Can be connected to application (or higher level) state&lt;/li&gt;
&lt;li&gt;Should not have its own markup &amp;amp; styles&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  A Note on Routes
&lt;/h3&gt;

&lt;p&gt;You may find, depending on your particular framework, that Routes do more of the heavy lifting than pages. In Next.js this will probably be the case, since it is in the Routes where you have to work with the special &lt;code&gt;getStaticProps&lt;/code&gt; and &lt;code&gt;getServerSideProps&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;That's not a problem, but I would pick just one, Pages &lt;strong&gt;or&lt;/strong&gt; Routes, to put this logic. Whichever of those you &lt;strong&gt;don't&lt;/strong&gt; pick should be a more basic implementation.&lt;/p&gt;

&lt;p&gt;In the sample app, I've put the data fetching and other logic into the Route to simplify the Page implementation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hopefully this has given you some concrete examples of developing with Atomic Design and a new way to think about structuring your applications.&lt;/p&gt;

&lt;p&gt;I want to reiterate the quote from Brad Frost that this is primarily &lt;em&gt;"a mental model to help us think of our user interfaces as both a cohesive whole and a collection of parts at the same time."&lt;/em&gt; As you continue developing component based applications, always consider how you structure those components to be as generic, flexible, and reusable as possible.&lt;/p&gt;
&lt;h3&gt;
  
  
  One Rule to Rule Them All
&lt;/h3&gt;

&lt;p&gt;To that end I have one more rule that probably deserves its own post, but has caused me enough headache over the years that it bears mentioning here. If you forget everything else, remember this!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Assign margins to a component via its parent, never to the component itself.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why not? Consider that each component you create should be a self contained unit that functions predictably within its own bounds. Margins break this pattern by creating space &lt;em&gt;outside&lt;/em&gt; of the element itself, and can lead to unpredictability or variable behavior &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing" rel="noopener noreferrer"&gt;due to margin collapsing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq6z7ek2rxxgydccn7ew8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq6z7ek2rxxgydccn7ew8.png" alt="Screenshot example showing a div with margin, border, and padding."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consider the above &lt;code&gt;div&lt;/code&gt; with margin, padding, and a border. The &lt;em&gt;border&lt;/em&gt; of the element is essentially where the component should end. If the &lt;em&gt;margin&lt;/em&gt; is applied to the &lt;code&gt;div&lt;/code&gt; component itself, reusing the component in other contexts may have unintended layout and display consequences.&lt;/p&gt;

&lt;p&gt;If the div needs a margin, the better approach is to specifically target it in the parent component.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Margins create extra space &lt;strong&gt;around&lt;/strong&gt; an element. In contrast, padding creates extra space &lt;strong&gt;within&lt;/strong&gt; an element.&lt;/p&gt;

&lt;p&gt;— &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/margin" rel="noopener noreferrer"&gt;MDN Web Docs&lt;/a&gt;, emphasis added&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An example from the sample app is the &lt;code&gt;VerticalListLayout&lt;/code&gt; component. It renders a collection of children that are intended to be &lt;code&gt;BlockLink&lt;/code&gt;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="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;VerticalListLayout&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verticalListLayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;molecule&lt;/span&gt;&lt;span class="dl"&gt;'&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;It is also intended that every &lt;code&gt;BlockLink&lt;/code&gt; has a certain layout within the parent component, including specific margins. If I had created this component in a vacuum, I might have applied the margin to each &lt;code&gt;BlockLink&lt;/code&gt;, since that's how it needs to appear in the list, but that would cause problems reusing the &lt;code&gt;BlockLink&lt;/code&gt; in other contexts. To prevent this the margin is assigned from the &lt;code&gt;VerticalListLayout&lt;/code&gt; itself, applied to any first-level children.&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="nc"&gt;.verticalListLayout&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--spacing-md&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--spacing-lg&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;
  
  
  Questions? Comments? &amp;lt;!-- omit in toc --&amp;gt;
&lt;/h2&gt;

&lt;p&gt;Hope you found this informative, maybe even helpful! Let me know on Twitter: &lt;a href="https://twitter.com/BenjaminWFox" rel="noopener noreferrer"&gt;@BenjaminWFox&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>tutorial</category>
      <category>atomicdesign</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Configure Azure AD B2C Authentication with Next.js</title>
      <dc:creator>Ben Fox</dc:creator>
      <pubDate>Tue, 25 Aug 2020 17:04:24 +0000</pubDate>
      <link>https://dev.to/benjaminwfox/how-to-configure-azure-ad-b2c-authentication-with-next-js-fgi</link>
      <guid>https://dev.to/benjaminwfox/how-to-configure-azure-ad-b2c-authentication-with-next-js-fgi</guid>
      <description>&lt;p&gt;Configuring authentication with Azure B2C in Next.js is not a particularly straight forward process. We'll look at how to facilitate this using the NextAuth.js library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication with Azure B2C and Next.js
&lt;/h2&gt;

&lt;p&gt;Authentication with &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; is, at least for me, a bit of a nebulous problem, especially if development requirements are not 100% solidified. Since you have access to both the client and server(less) environments, you could handle authentication purely in the client, on the server, or with a mix of both.&lt;/p&gt;

&lt;p&gt;Add in the task of configuring authentication with Azure B2C and complications are compounded. Azure AD B2C is many things but straight-forward is not one of them at least as far as I have found.&lt;/p&gt;

&lt;p&gt;Please note that &lt;a href="https://azure.microsoft.com/en-us/services/active-directory/external-identities/b2c/"&gt;Azure AD B2C&lt;/a&gt; is &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; the same thing as &lt;a href="https://azure.microsoft.com/en-us/services/active-directory/"&gt;Azure AD&lt;/a&gt;. Azure AD B2C (also referred to here as Azure B2C) is an identity &amp;amp; access management solution specifically for customer facing applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter NextAuth.js
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://next-auth.js.org/"&gt;NextAuth.js&lt;/a&gt; is a framework that aims to make authentication with Next.js a (relatively) simple and painless process. After setting initial configuration values the heavy lifting is done for you via dynamic routes in Next.js. From there, you have the flexibility of setting &amp;amp; checking sessions on both the client and server.&lt;/p&gt;

&lt;h2&gt;
  
  
  NextAuth + Azure B2C
&lt;/h2&gt;

&lt;p&gt;Setting up Azure B2C for authentication with NextAuth, though, is still a bit of a process. It requires some initial setup &amp;amp; configuration in the Azure Portal, as well as a custom configuration in NextAuth.&lt;/p&gt;

&lt;p&gt;My goal with this article is to detail all of the necessary steps to create a minimal authentication setup in Next.js using Azure B2C and NextAuth.js, and specifically to share the NextAuth configuration file I'm using. I'm not going to dive deep into the workings Azure B2C, Next.js, or NextAuth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Required Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Example Repository&lt;/li&gt;
&lt;li&gt;Set up Azure B2C&lt;/li&gt;
&lt;li&gt;Create a Next.js App&lt;/li&gt;
&lt;li&gt;Test the NextAuth Signin&lt;/li&gt;
&lt;li&gt;Add Signout Functionality&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;a id="example-repository"&gt;&lt;/a&gt;Example Repository
&lt;/h2&gt;

&lt;p&gt;If you want to go straight to the implementation, &lt;a href="https://github.com/BenjaminWFox/nextjs-azureb2c-nextauth"&gt;take a look at the repository&lt;/a&gt; for the full code, as well as two different PRs showing &lt;a href="https://github.com/BenjaminWFox/nextjs-azureb2c-nextauth/pull/1/files"&gt;the initial diff to create basic working authentication&lt;/a&gt;, as well as &lt;a href="https://github.com/BenjaminWFox/nextjs-azureb2c-nextauth/pull/3/files"&gt;the diff to add signout functionality&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a id="set-up-configure-azure-ad-b2c"&gt;&lt;/a&gt;Set up Azure B2C
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create a Subscription and Azure AD B2C Tenant
&lt;/h3&gt;

&lt;p&gt;This is probably the most complex part of the process. Since you're here, I'd assume that you already have access to an Azure subscription. Possibly even an Azure AD B2C Tenant...&lt;/p&gt;

&lt;p&gt;BUT if one or the other of those are not the case &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-tenant"&gt;you will have to start here&lt;/a&gt;, which will walk you through the process of creating a Subscription (as a prerequisite) if you don't have one, then through the process of creating hte Azure AD B2C Tenant.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pay special attention to the &lt;strong&gt;Initial domain name&lt;/strong&gt; you create, which you will use in a later step for NextAuth configuration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Create an App Registration
&lt;/h3&gt;

&lt;p&gt;Next up is &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications?tabs=app-reg-ga"&gt;another walkthrough from Microsoft detailing how to create an App Registration&lt;/a&gt;. This app registration, which lives within your Azure B2C Tenant, will be the authority that authenticates users and issues tokens.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pay special attention to the &lt;strong&gt;Client ID&lt;/strong&gt; &amp;amp; &lt;strong&gt;Client Secret&lt;/strong&gt; you create, which you will use in a later step for NextAuth configuration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Add Additional Redirect URIs
&lt;/h3&gt;

&lt;p&gt;Go back to the &lt;strong&gt;Authentication&lt;/strong&gt; section in the App Registration and add two additional Redirect URIs which will be used by NextAuth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000/api/auth/callback/azureb2c
http://localhost:3000/auth/signout
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Also make sure you checked the two checkboxes under 'Implicit grant'&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Create a User Flow
&lt;/h3&gt;

&lt;p&gt;Ok...&lt;a href="https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows"&gt;one more walkthrough from Microsoft on creating the User Flow&lt;/a&gt;. User Flows are the managed interfaces that users will use for signup, signin, profile editing, and password resets.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that you may want to add additional properties to be either collected or returned from the user flow!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--08iPiKmE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b6irrpgb46nj3lg0lbae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--08iPiKmE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b6irrpgb46nj3lg0lbae.png" alt="shows extra properties selected when creating the User Flow, like Email Address (collected) and Email Addresses(returned)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The basic pre-generated user flows are enough to get started, but as needs evolve the user flows can be fully customized to provide any functionality desired during the registration/authentication process.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a id="create-nextjs-app"&gt;&lt;/a&gt;Create a Next.js App
&lt;/h2&gt;

&lt;p&gt;That should be all the setup &amp;amp; configuration needed on the Azure B2C side, so let's get a Next.js environment set up. I named mine &lt;code&gt;nextjs-azureb2c-nextauth&lt;/code&gt; when I ran the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app
cd nextjs-azureb2c-nextauth
npm install next-auth
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Add NextAuth Config &amp;amp; Files
&lt;/h3&gt;

&lt;p&gt;There are four files we need to create or modify in order to get this working which are the &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;next.config.js&lt;/code&gt;, &lt;code&gt;_app.js&lt;/code&gt; and &lt;code&gt;[...nextauth].js&lt;/code&gt; files. Then we'll update the &lt;code&gt;index.js&lt;/code&gt; file to prove that it's working.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To set this up, copy and rename (or just rename) the &lt;code&gt;.env.example&lt;/code&gt; file in the root of the project to &lt;code&gt;.env&lt;/code&gt;. You'll need to update this with four values from Azure B2C:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AUTH_CLIENT_ID&lt;/strong&gt; - The App Registration client id.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AUTH_CLIENT_SECRET&lt;/strong&gt; - The App Registration client secret. If you didn't save the value when you created it the first time, &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications?tabs=app-reg-ga#create-a-client-secret"&gt;just create a new one&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AUTH_TENANT_NAME&lt;/strong&gt; - The 'Initial domain name' from when you initially set up Azure B2C.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AUTH_TENANT_GUID&lt;/strong&gt; - The GUID of the B2C Tenant, it can be found in the "Directory + subscription" blade in the Azure top nav bar, this icon: &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IvbQPWay--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/41qumxcgb43v6x7tx1bh.png"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;USER_FLOW&lt;/strong&gt; - The name of your signup/signin user flow, probably starting with B2C_1_&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;next.config.js&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next.js needs this file to read your &lt;code&gt;.env&lt;/code&gt; values and provide them to the application. Create the file in the root of your project. It should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="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;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;config&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;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;NEXTAUTH_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;NEXTAUTH_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;AUTH_CLIENT_ID&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;AUTH_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;AUTH_CLIENT_SECRET&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;AUTH_CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;AUTH_TENANT_NAME&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;AUTH_TENANT_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;AUTH_TENANT_GUID&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;AUTH_TENANT_GUID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;JWT_SECRET&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;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;USER_FLOW&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;USER_FLOW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://nextjs.org/docs/api-reference/next.config.js/environment-variables"&gt;I'm not sure&lt;/a&gt; the &lt;code&gt;require('dotenv').config()&lt;/code&gt; is even required, but it isn't breaking anything at the moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;_app.js&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We have to wrap &lt;code&gt;pages/_app.js&lt;/code&gt; in the NextAuth &lt;code&gt;Provider&lt;/code&gt; component in order to have access to the session, and to provide NextAuth with the NEXTAUTH_URL, which is required. Update the file to look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/_app.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;../styles/globals.css&lt;/span&gt;&lt;span class="dl"&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;Provider&lt;/span&gt; &lt;span class="k"&gt;as&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;next-auth/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&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="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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AuthProvider&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;site&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;NEXTAUTH_URL&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="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="o"&gt;&amp;lt;&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="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;)
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/AuthProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="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;MyApp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;[...nextauth.js]&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally we need to add our NextAuth configuration for Azure AD B2C to the &lt;a href="https://nextjs.org/docs/routing/dynamic-routes"&gt;dynamic route file&lt;/a&gt;. This lives in &lt;code&gt;pages/api/auth/[...nextauth].js&lt;/code&gt;. For this basic example, you shouldn't need to make any changes to the options below - all of the Azure AD B2C tenant-specific customizations are pulled from &lt;code&gt;.env&lt;/code&gt; variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/api/auth/[...nextauth].js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;NextAuth&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-auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tenantName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_TENANT_NAME&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tenantGuid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_TENANT_GUID&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userFlow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;USER_FLOW&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;jwt&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="na"&gt;secret&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;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/auth/signout&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;providers&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;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;azureb2c&lt;/span&gt;&lt;span class="dl"&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;Azure B2C&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&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;oauth&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;debug&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;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline_access openid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;grant_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;authorization_code&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;accessTokenUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tenantName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.b2clogin.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tenantName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.onmicrosoft.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userFlow&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/oauth2/v2.0/token`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// requestTokenUrl: `https://login.microsoftonline.com/${process.env.AUTH_TENANT_GUID}/oauth2/v2.0/token`,&lt;/span&gt;
      &lt;span class="na"&gt;authorizationUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tenantName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.b2clogin.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tenantName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.onmicrosoft.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userFlow&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/oauth2/v2.0/authorize?response_type=code+id_token&amp;amp;response_mode=form_post`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;profileUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://graph.microsoft.com/oidc/userinfo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;THE PROFILE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;fName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;given_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;lName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;surname&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;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emails&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="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emails&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="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;clientId&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;AUTH_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;clientSecret&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;AUTH_CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;idToken&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;state&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;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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;NextAuth&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="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Some Notes
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;providers.id&lt;/code&gt; string must match what you've used in your callback (Redirect URI) in Azure B2C, which for us was &lt;code&gt;http://localhost:3000/api/auth/callback/azureb2c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;profile&lt;/code&gt; property is used to map values returned from the authorization flow to the users token. Auzre AD B2C does some weird stuff, like returning an array of email addresses, so if you want any of these available make sure to understand the values that are coming back in the &lt;code&gt;profile&lt;/code&gt; obejct and map them accordingly to the return properties.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;state&lt;/code&gt; property is false. I had some issues when NextAuth release v3 and this was enabled, &lt;a href="https://github.com/nextauthjs/next-auth/issues/468"&gt;but it doesn't sound like disabling it should be a problem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;See more details on &lt;a href="https://next-auth.js.org/configuration/providers#using-a-custom-provider"&gt;all the options for using a custom provider here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a id="test-nextauth"&gt;&lt;/a&gt;Test the NextAuth Signin
&lt;/h2&gt;

&lt;p&gt;You &lt;em&gt;should&lt;/em&gt; now (assuming you're running the project) be able to navigate to &lt;a href="http://localhost:3000/api/auth/signin/azureb2c"&gt;&lt;/a&gt;&lt;a href="http://localhost:3000/api/auth/signin/azureb2c"&gt;http://localhost:3000/api/auth/signin/azureb2c&lt;/a&gt; and run through the login flow! In order to actually test that it's working though, you can add a little code to your &lt;code&gt;pages/index.js&lt;/code&gt; file to check for the session - &lt;a href="https://next-auth.js.org/getting-started/client#usesession"&gt;the &lt;code&gt;useSession&lt;/code&gt; hook!&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/index.js&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&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;../styles/Home.module.css&lt;/span&gt;&lt;span class="dl"&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;useSession&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-auth/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&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;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSession&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, anywhere else in the file you can add some conditional logic to show messaging based on whether or not there is a user session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/index.js&lt;/span&gt;
&lt;span class="c1"&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;&amp;lt;&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    You are 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;/&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    You are not signed in! &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&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;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/api/auth/signin"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;You must sign in to access documentation!&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="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="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a id="add-signout"&gt;&lt;/a&gt;Add Signout Functionality
&lt;/h2&gt;

&lt;p&gt;NextAuth exposes a &lt;a href="https://next-auth.js.org/getting-started/client#signout"&gt;SignOut&lt;/a&gt; function that we can leverage, but this will only clear the local session. If the user signs out via this method, then signs in again via Azure AD B2C, they will not be prompted to re-enter their credentials since a session in B2C still exists.&lt;/p&gt;

&lt;p&gt;That may not be a problem for you 🤷‍♂️ but if it is you can call the Azure B2C signout url, then redirect the user to the NextAuth signout url. The B2C sign-out URL looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://${process.env.AUTH_TENANT_NAME}.b2clogin.com/${process.env.AUTH_TENANT_NAME}.onmicrosoft.com/${process.env.USER_FLOW}/oauth2/v2.0/logout?post_logout_redirect_uri=${process.env.NEXTAUTH_URL}/auth/signout
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wherever you want the user to be able to log out, you can include that in a link. If you don't need the full B2C signout, you can also call the NextAuth API signout route instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Addition to `index.js`&lt;/span&gt;
&lt;span class="c1"&gt;// Can also `useSession` to show only if signed in!&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;signed&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;also&lt;/span&gt; &lt;span class="nx"&gt;sign&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;like&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/auth/signout/azureb2c&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Sign&lt;/span&gt; &lt;span class="nx"&gt;Out&lt;/span&gt; &lt;span class="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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://&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;AUTH_TENANT_NAME&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.b2clogin.com/&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;AUTH_TENANT_NAME&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.onmicrosoft.com/&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;USER_FLOW&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/oauth2/v2.0/logout?post_logout_redirect_uri=&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;NEXTAUTH_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/auth/signout`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Sign&lt;/span&gt; &lt;span class="nx"&gt;Out&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;FULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you notice on the end of the url, we've specified the &lt;code&gt;post_logout_redirect_uri&lt;/code&gt; set to &lt;code&gt;${process.env.NEXTAUTH_URL}/auth/signout&lt;/code&gt; - so we also need to make another route to facilitate this. The &lt;code&gt;signOut&lt;/code&gt; method only works on the client, so this can not be an API route, and it should not run on the server. Create the file at &lt;code&gt;pages/auth/signout.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/auth/signout.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;signOut&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-auth/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Signout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&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;signOut&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;callbackUrl&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;NEXTAUTH_URL&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="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  And Is That It?
&lt;/h2&gt;

&lt;p&gt;In theory you're all set...but given some of the idiosyncrasies I've experienced with Azure (and sometimes Next.js) maybe not? Hopefully this at least helps you in the right direction if you were also struggling with this integration. My experience so far with Azure AD B2C has not been particularly pleasant, but given that it's &lt;em&gt;significantly&lt;/em&gt; cheaper than a lot of the alternatives out there I'll be sticking with it for the forseeable future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issues? Questions? Comments?
&lt;/h2&gt;

&lt;p&gt;Find me on Twitter — &lt;a href="http://twitter.com/benjaminwfox"&gt;@BenjaminWFox&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>authentication</category>
      <category>nextjs</category>
      <category>nextauth</category>
    </item>
  </channel>
</rss>
