<?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>Forem: Konstantin Komelin</title>
    <description>The latest articles on Forem by Konstantin Komelin (@kkomelin).</description>
    <link>https://forem.com/kkomelin</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%2F279591%2Fb27922e2-ab08-4f7a-bc41-7452be32686b.png</url>
      <title>Forem: Konstantin Komelin</title>
      <link>https://forem.com/kkomelin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kkomelin"/>
    <language>en</language>
    <item>
      <title>Recording 'From Vanilla JS to Solid.js' Video Series</title>
      <dc:creator>Konstantin Komelin</dc:creator>
      <pubDate>Thu, 04 Jan 2024 01:07:21 +0000</pubDate>
      <link>https://forem.com/kkomelin/recording-from-vanilla-js-to-solidjs-video-series-4a4f</link>
      <guid>https://forem.com/kkomelin/recording-from-vanilla-js-to-solidjs-video-series-4a4f</guid>
      <description>&lt;p&gt;I had always wanted to have a Youtube channel where I could share my video tutorials, but had never been brave enough to start... until recently.&lt;/p&gt;

&lt;p&gt;Meet my brand-new &lt;a href="https://www.youtube.com/@kkomelin" rel="noopener noreferrer"&gt;personal Youtube channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.youtube.com/watch?v=Xv-2qg0nQPY&amp;amp;list=PL8y_ITxCUCl02UvoPsct6lL0hWu0ueqTv" rel="noopener noreferrer"&gt;first video series&lt;/a&gt; is about porting a small vanilla JS web app to Solid.js and implementing push notifications for it through Firebase.&lt;/p&gt;

&lt;p&gt;It's not because I'm a pro in Solid.js, Firebase or Youtube. In fact, I'm not. I'm still learning all this stuff while recording. It's rather about building something in public, sharing my approaches and collecting feedback from the community.&lt;/p&gt;

&lt;p&gt;I see it as something like Video Open Source. Just the next step for my Open Source activities and blogging.&lt;/p&gt;

&lt;p&gt;Watch &lt;a href="https://www.youtube.com/@kkomelin" rel="noopener noreferrer"&gt;my progress&lt;/a&gt;. Who knows where it can lead me in a few years.&lt;/p&gt;

</description>
      <category>pwa</category>
      <category>solidjs</category>
      <category>firebase</category>
      <category>youtube</category>
    </item>
    <item>
      <title>The most underestimated freelance habit</title>
      <dc:creator>Konstantin Komelin</dc:creator>
      <pubDate>Thu, 28 Sep 2023 06:03:25 +0000</pubDate>
      <link>https://forem.com/kkomelin/the-most-underestimated-freelance-habit-6dl</link>
      <guid>https://forem.com/kkomelin/the-most-underestimated-freelance-habit-6dl</guid>
      <description>&lt;p&gt;So what is it? It's simple - always trying to &lt;strong&gt;exceed the expectations&lt;/strong&gt;. But if it's so simple, why don't all freelancers have this habit?&lt;/p&gt;

&lt;h2&gt;
  
  
  Most freelancers underestimate the effort required
&lt;/h2&gt;

&lt;p&gt;It's especially typical for large projects and for junior-to-middle freelancers whose experience is somewhat limited.&lt;/p&gt;

&lt;p&gt;I solve the large project problem by splitting the project into a few milestones and estimating the first milestone only, or suggesting hourly payments.&lt;/p&gt;

&lt;p&gt;The lack of experience is usually solved by multiplying to a risk factor. Let's say, if you have no experience in the area, multiply your estimated time to 2. If you have 1-3 years of experience, multiply to 1.3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some people are naturally greedy
&lt;/h2&gt;

&lt;p&gt;Greedy people don't care about investing some time into developing long-term relationships with their clients. That's a huge mistake because clients can come for a quick one-time project and stay for years if they like you, and on top of that they recommend you to their friends.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some freelancers don't care about their reputation enough
&lt;/h2&gt;

&lt;p&gt;Not keeping promises is totally Okay for some freelancers. They feel that there is a demand for them in the market, so they think they can afford delivering late or not delivering at all.&lt;/p&gt;

&lt;p&gt;You know what, it won't last long. More and more people are coming to the market from other industries and they are hungry for work, while AI is destroying some jobs completely. So it's your choice - develop your reputation now and stay in the market or disappear.&lt;/p&gt;




&lt;p&gt;My formula is to &lt;strong&gt;deliver 110% quicker than expected and give 110% more value&lt;/strong&gt;. Are you with me, my friends?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;// Photo by &lt;a href="https://unsplash.com/@cytonn_photography?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Cytonn Photography&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/vWchRczcQwM?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>freelance</category>
      <category>career</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What I Learned While Building My First Web3 Project</title>
      <dc:creator>Konstantin Komelin</dc:creator>
      <pubDate>Mon, 12 Dec 2022 11:18:30 +0000</pubDate>
      <link>https://forem.com/kkomelin/what-i-learned-while-building-my-first-web3-project-cf8</link>
      <guid>https://forem.com/kkomelin/what-i-learned-while-building-my-first-web3-project-cf8</guid>
      <description>&lt;p&gt;I started building &lt;a href="https://marrysign.com/?utm_source=dev-to&amp;amp;utm_medium=content&amp;amp;utm_campaign=first-web3-project-learnings" rel="noopener noreferrer"&gt;MarrySign&lt;/a&gt;, a crypto-marriage app, during the Chainlink Hackathon Fall 2022 because I wanted to give any couple regardless of their gender, location or any other factors, a chance to register their union quickly and transparently from the comfort of their homes. Now after the hackathon, I continue working on the project in my spare time.&lt;/p&gt;

&lt;p&gt;Since it's the first web3 project I'm building, I'd like to share my learnings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/addyosmani/status/1600553460180869120" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3tut0ld4lhuayd1gabjr.png" alt="Addy Osmani tweet about learning through writing" width="552" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Blockchain
&lt;/h2&gt;

&lt;p&gt;I wish I could explain it briefly ;) But let me try to use familiar examples for that...&lt;/p&gt;

&lt;p&gt;Blockchain is a distributed database with an acknowledgement mechanism, like in MongoDB, and stored procedures, like in Postgres, directly connected to a payment gateway, like Stripe, but for Crypto.&lt;/p&gt;

&lt;p&gt;For the Ethereum network, the “stored procedures” (functions) are grouped together into a “class” (contract). The contract code is written in the Solidity language which resembles a mixture of JS and Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix bugs in advance
&lt;/h2&gt;

&lt;p&gt;If you once deployed your Solidity contract to the blockchain, you can't change its code. It means that if you find a bug in it, you can't deploy a hotfix. You will need to deploy an updated version to a new address leaving the old contract and user data intact. It adds some challenges, for example migration of user data from an old version of the contract to a new one. &lt;a href="https://blog.chain.link/upgradable-smart-contracts/" rel="noopener noreferrer"&gt;There are solutions for that&lt;/a&gt; but it's not one button click.&lt;/p&gt;

&lt;p&gt;So the idea is to deploy good-quality code to production, well-tested and well-documented.&lt;/p&gt;

&lt;p&gt;Taking that into account, I test my Solidity contract with &lt;a href="https://hardhat.org/" rel="noopener noreferrer"&gt;the Hardhat framework&lt;/a&gt;, document it properly to generate human readable docs automatically with &lt;a href="https://www.npmjs.com/package/solidity-docgen" rel="noopener noreferrer"&gt;solidity-docgen&lt;/a&gt;. To format my Solidity code, I use &lt;a href="https://www.npmjs.com/package/solhint" rel="noopener noreferrer"&gt;solhint&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/solhint-plugin-prettier" rel="noopener noreferrer"&gt;solhint-plugin-prettier&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gas fees
&lt;/h2&gt;

&lt;p&gt;You pay fees (aka gas fees) for writing to the blockchain, but read data from the blockchain for free. However, it's not guaranteed that your read-only function will return results if it exceeds some network limits.&lt;/p&gt;

&lt;p&gt;The Hardhat framework lets you estimate gas fees for running your functions. Not sure if it's 100% accurate but it helps identify heavy functions.&lt;/p&gt;

&lt;p&gt;There are also solutions for gas-less payments. It's when the contract creator pays fees for their users through a special gas station, for example &lt;a href="https://opengsn.org/" rel="noopener noreferrer"&gt;Ethereum Gas Station Network&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staging networks
&lt;/h2&gt;

&lt;p&gt;Since the price of a mistake is normally high on the blockchain, there are a few test networks which you can use to test your contract without paying gas fees on the Ethereum mainnet.&lt;/p&gt;

&lt;p&gt;I use the Goerli Ethereum network. People don't like it for some issues but other options are not widely supported yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web3 UX
&lt;/h2&gt;

&lt;p&gt;The UX of some tools and services is not yet ideal, so more and more companies are focusing on web3 UI/UX. I think good UX is a competitive advantage today. I personally liked &lt;a href="https://www.youtube.com/watch?v=6f0zxmvLmZs" rel="noopener noreferrer"&gt;presentation by Rahat Chowdhury from the Polygon team&lt;/a&gt; with ideas on how to improve web3 UX.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back yourself up with a withdraw() function
&lt;/h2&gt;

&lt;p&gt;I heard stories about contract developers forgetting to implement a withdrawal function and having to lose their earned funds. So if you're going to collect fees from your users or receive any funds to your contract address, make sure you add a withdraw function right from the beginning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful resources
&lt;/h2&gt;

&lt;p&gt;Web3 and Hardhat starters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hardhat.org/hardhat-runner/docs/getting-started" rel="noopener noreferrer"&gt;Official Hardhat Starter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/G3root/nextjs-dapp-starter-ts" rel="noopener noreferrer"&gt;Full-stack dApp Starter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/smartcontractkit/hardhat-starter-kit" rel="noopener noreferrer"&gt;Chainlink Hardhat Starter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Solidity libraries: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.openzeppelin.com/contracts" rel="noopener noreferrer"&gt;OpenZeppelin Contracts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/transmissions11/solmate" rel="noopener noreferrer"&gt;Solmate building blocks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Video: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtube.com/playlist?list=PLVP9aGDn-X0Q1L67bV_AbDd75qTY6Ylxw" rel="noopener noreferrer"&gt;Chainlink Fall 2022 Hackathon Playlist&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Communities, hackathons and accelerators
&lt;/h2&gt;

&lt;p&gt;Looks like current crypto-winter doesn't slow down web3 progress because a lot is going on in the area actually.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are growing Discord groups for almost every blockchain project.&lt;/li&gt;
&lt;li&gt;There are many hackathons, dedicated to a blockchain protocol or network, that are happening now.&lt;/li&gt;
&lt;li&gt;The Techstars accelerator partners up with big players in the area to help web3 and blockchain startups grow.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;To sum up, developing for web3 has its challenges and opportunities, so when you get familiar with tools and services available and discover best practices, you can develop something really new, something disruptive.&lt;/p&gt;

&lt;p&gt;I wish you best of luck with your current and future blockchain adventures! And if you like the idea of crypto-marriages, &lt;a href="https://twitter.com/marrysign" rel="noopener noreferrer"&gt;follow us on twitter&lt;/a&gt; or &lt;a href="https://marrysign.com/?utm_source=dev-to&amp;amp;utm_medium=content&amp;amp;utm_campaign=first-web3-project-learnings" rel="noopener noreferrer"&gt;get crypto-married with us&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I originally wrote this post for &lt;a href="https://komelin.com/blog/first-web3-project-learnings" rel="noopener noreferrer"&gt;my blog&lt;/a&gt; but after receiving good feedback decided to share with the dev.to community. Hope you guys like it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>books</category>
    </item>
    <item>
      <title>The Uploadcare Image Loader for Next.js Has Been Released</title>
      <dc:creator>Konstantin Komelin</dc:creator>
      <pubDate>Sat, 27 Nov 2021 14:32:13 +0000</pubDate>
      <link>https://forem.com/kkomelin/the-uploadcare-image-loader-for-nextjs-has-been-released-3fc</link>
      <guid>https://forem.com/kkomelin/the-uploadcare-image-loader-for-nextjs-has-been-released-3fc</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0w1fsfx1zlmeeofsorv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0w1fsfx1zlmeeofsorv.png" alt="Next.js plus Uploadcare banner" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First of all, what's Uploadcare? Uploadcare through their API provides file uploading, processing and delivery for web apps, and does it really well.&lt;/p&gt;

&lt;p&gt;While working on a series of Next.js tutorials for Uploadcare blog (&lt;a href="https://uploadcare.com/blog/next-js-tutorial/" rel="noopener noreferrer"&gt;first&lt;/a&gt;, &lt;a href="https://uploadcare.com/blog/next-js-image-optimization/" rel="noopener noreferrer"&gt;second&lt;/a&gt;), I thought people would benefit from integrating Uploadcare services into Next.js, so I offered my help with an Open Source integration. &lt;/p&gt;

&lt;p&gt;As it turned out, the Uploadcare guys had already &lt;a href="https://github.com/vercel/next.js/pull/18688" rel="noopener noreferrer"&gt;tried&lt;/a&gt; to add their image loader to the Next.js core but for some reason Next.js team stopped accepting new third-party loaders to the core, so the Uploadcare loader remained unused in a pull request on Github.  &lt;/p&gt;

&lt;p&gt;I started with the pull request but went much further. Here is what I did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extracted the loader code into a separate package&lt;/li&gt;
&lt;li&gt;Refactored and optimized the code&lt;/li&gt;
&lt;li&gt;Made it possible to configure the loader through environment variables (custom CDN domain, custom proxy domain, image transformation settings, etc.)&lt;/li&gt;
&lt;li&gt;Developed the UploadcareImage component with the loader integrated&lt;/li&gt;
&lt;li&gt;Created automated tests for the loader function and the Next.js component&lt;/li&gt;
&lt;li&gt;Added a Github workflow for testing and linting the project&lt;/li&gt;
&lt;li&gt;Added &lt;a href="https://github.com/uploadcare/nextjs-loader" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for the project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, &lt;a href="https://github.com/nd0ut" rel="noopener noreferrer"&gt;Alex Grenishin&lt;/a&gt; from the Uploadcare team added &lt;a href="https://github.com/algolia/shipjs" rel="noopener noreferrer"&gt;ShipJs&lt;/a&gt; integration, improved auto-deployments and helped fix some issues.&lt;/p&gt;

&lt;p&gt;You can test the project in action &lt;a href="https://uploadcare-nextjs-loader.vercel.app" rel="noopener noreferrer"&gt;here&lt;/a&gt; and check out its code on Github &lt;a href="https://github.com/uploadcare/nextjs-loader" rel="noopener noreferrer"&gt;@uploadcare/nextjs-loader&lt;/a&gt;. Feel free to suggest your improvements in the issue queue on Github.&lt;/p&gt;

&lt;p&gt;And if you want to experiment with the Uploadcare file uploading widget for React, check out &lt;a href="https://github.com/uploadcare/react-widget" rel="noopener noreferrer"&gt;@uploadcare/react-widget&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to the Uploadcare team for their support and assistance.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>HTTP Basic Auth for Next.js</title>
      <dc:creator>Konstantin Komelin</dc:creator>
      <pubDate>Wed, 21 Apr 2021 05:23:07 +0000</pubDate>
      <link>https://forem.com/kkomelin/http-basic-auth-for-next-js-d8m</link>
      <guid>https://forem.com/kkomelin/http-basic-auth-for-next-js-d8m</guid>
      <description>&lt;p&gt;You may need the HTTP basic authentication to protect your secrets/innovations when the app is not ready for production or when your normal authorization mechanism is not yet ready. Let's look at a few possible solutions for the problem in the Next.js context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Protect separate routes with &lt;a href="https://www.npmjs.com/package/nextjs-basic-auth" rel="noopener noreferrer"&gt;nextjs-basic-auth&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Install the package &lt;code&gt;nextjs-basic-auth&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i nextjs-basic-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a utility file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; util &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;util/httpAuthCheck.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And put the following code into it:&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;// util/httpAuthCheck.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;initializeBasicAuth&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;nextjs-basic-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;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;initializeBasicAuth&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can add the HTTP auth to any of your pages/routes, for example &lt;code&gt;page/index.js&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Open &lt;code&gt;page/index.js&lt;/code&gt; and put the following code right after the imports section:&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;// pages/index.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;httpAuthCheck&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;../util/httpAuthCheck&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getServerSideProps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&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;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;httpAuthCheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="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;To test it, run the app with &lt;code&gt;npm run dev&lt;/code&gt; and open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have to enable the HTTP auth on per page/route basis. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. (not working currently) Document-level check with &lt;a href="https://www.npmjs.com/package/nextjs-basic-auth-middleware" rel="noopener noreferrer"&gt;nextjs-basic-auth-middleware&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Install nextjs-basic-auth-middleware:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i nextjs-basic-auth-middleware
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create &lt;code&gt;pages/_document.js&lt;/code&gt; to override the &lt;a href="https://nextjs.org/docs/advanced-features/custom-document" rel="noopener noreferrer"&gt;default Document component&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ./pages/_document.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put the following code into it:&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;// pages/_document.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Head&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;NextScript&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/document&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;basicAuthMiddleware&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;nextjs-basic-auth-middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDocument&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Document&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getInitialProps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&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;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;basicAuthMiddleware&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInitialProps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;initialProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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;Html&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;Head&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;body&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;Main&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;NextScript&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;/body&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;/Html&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then put your auth credentials into your &lt;code&gt;.env&lt;/code&gt; file like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# .env
&lt;/span&gt;&lt;span class="py"&gt;BASIC_AUTH_CREDENTIALS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;user:password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test it, run the app with &lt;code&gt;npm run dev&lt;/code&gt; and open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unfortunately, this solution causes the &lt;a href="https://github.com/labd/nextjs-basic-auth-middleware/issues/2" rel="noopener noreferrer"&gt;TypeError: Cannot read property 'url' of undefined&lt;/a&gt; because it doesn't properly handle the isomorphic nature of Next and may need some adaptation for the client-side rendering.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not working because of &lt;a href="https://github.com/labd/nextjs-basic-auth-middleware/issues/2" rel="noopener noreferrer"&gt;TypeError: Cannot read property 'url' of undefined&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Custom server with &lt;a href="https://www.npmjs.com/package/basic-auth" rel="noopener noreferrer"&gt;basic-auth&lt;/a&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i basic-auth tsscmp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please refer to &lt;a href="https://nextjs.org/docs/advanced-features/custom-server" rel="noopener noreferrer"&gt;the official Next documentation&lt;/a&gt; if you're not familiar with the custom server creation.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;server.js&lt;/code&gt; file in the project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put the following code into it:&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;// server.js&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;createServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&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;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&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;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;basic-auth&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;compare&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tsscmp&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;dev&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;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;dev&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;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRequestHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;createServer&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="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parsedUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse&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;url&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;credentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;credentials&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;checkHttpAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;credentials&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;credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;))&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;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;401&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;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WWW-Authenticate&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;Basic realm="example"&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Access denied&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;handle&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;parsedUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt; Ready on http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkHttpAuth&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;pass&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="nf"&gt;compare&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&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;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&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;Finally, you need to adapt your &lt;code&gt;package.json&lt;/code&gt; to run the custom server:&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;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&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 server.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&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;"NODE_ENV=production node server.js"&lt;/span&gt;&lt;span class="w"&gt;
  &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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As usual, test it with &lt;code&gt;npm run dev&lt;/code&gt; and open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With the custom server approach, we will need to track changes in the built-in Next server code and apply them to our server manually with every Next update.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Possible improvements for all code fragments:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extract helper functions to separate files, e.g. &lt;code&gt;checkHttpAuth()&lt;/code&gt; function in the custom server solution.&lt;/li&gt;
&lt;li&gt;Move the user credentials to environment variables.&lt;/li&gt;
&lt;li&gt;Use TypeScript.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;In this post, we have learned three ways to implement HTTP auth in Next.js and looked at two ways to extend a Next.js app, such as overriding the default Document component and creating a custom server.&lt;/p&gt;

&lt;p&gt;At the moment, I personally stick with the custom server solution for HTTP auth because I need to protect all routes at once and because it worked for me from the first try.&lt;/p&gt;

&lt;p&gt;The solutions I listed here are code-level ones but it's also possible to implement an Nginx proxy which would provide the HTTP auth layer. Please let me know if you're interested in the Nginx solution and I will add it to the list.&lt;/p&gt;




&lt;p&gt;Originally published on &lt;a href="https://komelin.com/articles/http-basic-auth-nextjs/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>auth</category>
      <category>httpbasicauth</category>
      <category>basicauth</category>
    </item>
    <item>
      <title>Node.js Certification: My Experience and Advice</title>
      <dc:creator>Konstantin Komelin</dc:creator>
      <pubDate>Mon, 11 May 2020 18:54:39 +0000</pubDate>
      <link>https://forem.com/kkomelin/node-js-certification-my-experience-and-advice-9bj</link>
      <guid>https://forem.com/kkomelin/node-js-certification-my-experience-and-advice-9bj</guid>
      <description>&lt;p&gt;In the beginning of the COVID-19 lockdown I made a decision to use the isolation for self-improvement and invest time in something future-proof, so I signed up for &lt;a href="https://training.linuxfoundation.org/certification/jsnad/" rel="noopener noreferrer"&gt;OpenJS Node.js Application Developer (JSNAD) certification&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It took me a few weeks and two attempts to pass the exam, and a couple of days ago I finally received my certificate. Now it's time to reflect on the preparation process and test itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  About the exam
&lt;/h3&gt;

&lt;p&gt;The OpenJS Node.js Application Developer certification exam is not a dry theoretical test. Not at all, it's a performance based test consisting of a few coding assignments which you solve in a remote environment using one of the available IDEs (VSCode or WebStorm). &lt;/p&gt;

&lt;p&gt;You're given two hours, IDE and terminal to get the job done. You can only use Node and JS docs during the exam.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preparation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;I've reviewed Node.js 10 documentation. Yes, correct, the certification is for Node 10 (at the moment of writing).
&lt;/li&gt;
&lt;li&gt;I've completed &lt;a href="https://github.com/workshopper/learnyounode" rel="noopener noreferrer"&gt;learnyounode&lt;/a&gt; and &lt;a href="https://github.com/workshopper/stream-adventure" rel="noopener noreferrer"&gt;stream-adventure&lt;/a&gt; free interactive courses.
&lt;/li&gt;
&lt;li&gt;I've watched the first part of &lt;a href="https://learn.javascript.ru/screencast/nodejs" rel="noopener noreferrer"&gt;the Ilya Kantor's free screencast&lt;/a&gt; in Russian.
&lt;/li&gt;
&lt;li&gt;I've read and reproduced code examples from the following chapters of &lt;a href="https://www.packtpub.com/web-development/node-cookbook-third-edition" rel="noopener noreferrer"&gt;Node Cookbook&lt;/a&gt;:

&lt;ul&gt;
&lt;li&gt;Ch 1: Debugging process&lt;/li&gt;
&lt;li&gt;Ch 2: Writing Modules&lt;/li&gt;
&lt;li&gt;Ch 3: Coordinating I/O&lt;/li&gt;
&lt;li&gt;Ch 4: Using Streams&lt;/li&gt;
&lt;li&gt;Ch 9: Optimizing Performance&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I was so impressed by the Node streams that I even &lt;a href="https://komelin.com/articles/nodejs-certification-my-experience-advice/" rel="noopener noreferrer"&gt;wrote about them&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  First attempt
&lt;/h3&gt;

&lt;p&gt;9 in the morning. Said Hi to my exam proctor through their chat. Showed my ID, desk and room to the proctor. Forgot to close thousands of tabs in Chrome. Experienced screen sharing issue. The proctor motivated to close the tabs. It fixed the issue.&lt;/p&gt;

&lt;p&gt;Was solving tasks one by one. Enjoyed the problems and process.&lt;/p&gt;

&lt;p&gt;Not enough time.&lt;/p&gt;

&lt;p&gt;Result: 62. Passing score: 68.&lt;/p&gt;

&lt;h3&gt;
  
  
  Second attempt
&lt;/h3&gt;

&lt;p&gt;One retake was free, so I happily used the second chance. &lt;/p&gt;

&lt;p&gt;To prepare for the retake, I reviewed all the topics I was not confident about during the first attempt. During the second attempt, I tried to manage my time better and avoid the same organizational mistakes, such as chaotically switching between windows, working on one task for too long, double-checking whether I saved my solution or not, etc.&lt;/p&gt;

&lt;p&gt;That worked. In 36 hours, I received my PDF certificate.&lt;/p&gt;

&lt;p&gt;Result 76. Passing score: 68.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advice for future test takers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Make sure you can comprehend written English to follow proctor's instructions.&lt;/li&gt;
&lt;li&gt;Dedicate some time to learn &lt;a href="https://training.linuxfoundation.org/openjs-certification-candidate-resources/" rel="noopener noreferrer"&gt;candidate resources&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Learn &lt;em&gt;cd&lt;/em&gt; and &lt;em&gt;clear&lt;/em&gt; Linux commands. You will probably need them to effectively work with terminal.&lt;/li&gt;
&lt;li&gt;Make sure you know where to find Node 10 docs.&lt;/li&gt;
&lt;li&gt;Practice before the exam. Seriously, try to solve foundational Node problems, such as writing to a file, executing a command in a child process, dealing with promises, getting system info, debugging, etc. Focus on fundamentals rather than on a particular framework or database access layer.&lt;/li&gt;
&lt;li&gt;On exam day, make sure you don't have anyone else in your room and anything on your desk except your ID. Move away all electronic devices to not cause redundant questions from the proctor.&lt;/li&gt;
&lt;li&gt;Close all apps (except Chrome) which are not necessary for normal functioning of your OS.&lt;/li&gt;
&lt;li&gt;Close all browser windows/tabs (except one).&lt;/li&gt;
&lt;li&gt;When you first open VSCode, configure it. Turn on auto save (File -&amp;gt; Auto Save) and enable word wrap (View -&amp;gt; Toggle Word Wrap). Believe me, it will save your time.&lt;/li&gt;
&lt;li&gt;Use VSCode integrated terminal (Terminal -&amp;gt; New Terminal) to avoid switching between windows.&lt;/li&gt;
&lt;li&gt;Every task folder has a README file with the task description. Don't waste your time on reading it in the browser.&lt;/li&gt;
&lt;li&gt;Control your time and try not to spend too much time on a single task. Better come back to it later if some time is left.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  To sum up
&lt;/h3&gt;

&lt;p&gt;The Node.js certification was not my first technical certification, so I can compare. The first one was &lt;a href="https://www.zend-zce.com/en/yellow-pages/ZEND021715" rel="noopener noreferrer"&gt;Zend PHP Certification&lt;/a&gt; back in 2013. That exam had mostly theoretical questions. However, it gave me a big picture of the language and deepened my knowledge. Besides, the PHP certificate favorably distinguished my freelance profile from myriads of others, which helped with job search.&lt;/p&gt;

&lt;p&gt;Let's see what opportunities Node.js certificate can bring for my future career. Even though I'm 100% sure the certification has made me a better developer, I still have a lot of things to learn, and I'm not going to stop evolving.&lt;/p&gt;

</description>
      <category>node</category>
      <category>certification</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
