<?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: Jan Hoogeveen</title>
    <description>The latest articles on DEV Community by Jan Hoogeveen (@janhoogeveen).</description>
    <link>https://dev.to/janhoogeveen</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%2F68881%2F01d73f8f-874c-4581-a4de-ce02ae1a5b0f.jpeg</url>
      <title>DEV Community: Jan Hoogeveen</title>
      <link>https://dev.to/janhoogeveen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/janhoogeveen"/>
    <language>en</language>
    <item>
      <title>Refactoring web applications</title>
      <dc:creator>Jan Hoogeveen</dc:creator>
      <pubDate>Sat, 14 Dec 2019 12:44:33 +0000</pubDate>
      <link>https://dev.to/janhoogeveen/refactoring-web-applications-3g6d</link>
      <guid>https://dev.to/janhoogeveen/refactoring-web-applications-3g6d</guid>
      <description>&lt;p&gt;Does this sound familiar?&lt;/p&gt;

&lt;p&gt;You've started this great new project and have been hammering out new features at a great pace. Lately your velocity has dropped. It was only a minor decrease in the beginning, but it's becoming a severe slowdown now. Now you're at a point where you feel that you're having to defend yourself to stakeholders on why it's taking so long to deliver new features.&lt;/p&gt;

&lt;p&gt;You're probably dealing with something that's called tech debt. Tech debt is the accumulation of technological decisions that favor short-term velocity over long-term maintenance. It's the result of making choices that made you look good at the start of the project by cutting corners, but it's slowly becoming a more serious problem now that your project has matured.&lt;/p&gt;

&lt;p&gt;Just like financial debt in the real world, it's better to pay off your debt before it accumulates in even more debt.&lt;/p&gt;

&lt;p&gt;When working in software development, paying off your (tech) debt is called &lt;em&gt;refactoring&lt;/em&gt;. During refactoring, you take existing code and change it in such a way that results in more maintainable, readable code. One important condition is that the external behavior of the code stays the same. In the case of this example, that means our features still perform the same pieces of functionality as before.&lt;/p&gt;

&lt;p&gt;Note: Some people might tell you that "&lt;em&gt;refactoring is only for people who write bad code in the first place&lt;/em&gt;". Please, ignore those people! It's simply not true. There's plenty of reasons why tech debt is introduced in a project, and I'd argue the most important one is agile development.&lt;/p&gt;

&lt;p&gt;While working agile, you're dealing with constantly evolving requirements. You're building working software, releasing it to the world and based on feedback from going to production you'll re-iterate again. This, by definition, makes it impossible to design a scaleable, maintainable solution from the start.&lt;/p&gt;

&lt;p&gt;An encompassing overview, which you'd need to make all the right choices from the start, of the product will only be possibly by the time that a substantial amount of time and energy has already been invested in the project already. Only by the time that the product contains a decent amount of consumer facing features will you be able to fully understand the results of your initial choices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approaching the refactor
&lt;/h2&gt;

&lt;p&gt;Refactoring can sound like a daunting task. It can involve changing critical parts of your application in an all-or-nothing approach. That's why you have to treat it just like any other enormous issue in an agile project. Consider "refactoring" as an epic and break it up in tons of smaller stories. The goal is for every story to reduce tech debt, piece by piece.&lt;/p&gt;

&lt;p&gt;Accept refactoring as a recurring part of your sprint cycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps to refactoring
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a list of annoyances/items that you want to solve. Involve the whole development team in these discussions. Do not let designers or product owners join these discussions. The idea is that developers can figure out on their own which parts of the codebase are blocking their progress the most. Let them own both the problem of tech debt, but more importantly the solution to these problems. Nothing is more empowering than knowing you can solve problems on your own.&lt;/li&gt;
&lt;li&gt;When doing sprint refinement, go over the refactoring list and discuss in broad strokes how you want to solve this issue.&lt;/li&gt;
&lt;li&gt;Deprecate methods or options. Use JSDoc to document which methods/classes you're deprecating and why. This helps with tools like IntelliSense. Also write down which alternative methods should be used instead, so developers will know what to do when confronted with the deprecation warning.&lt;/li&gt;
&lt;li&gt;Ensure you have a solid set of tests written for your deprecated methods, so you know when refactoring everything still works.&lt;/li&gt;
&lt;li&gt;Write a replacement method and apply it to at least one place of your codebase. When everything works as expected, refine the API. Take a step back. What annoyed you about the previous solution, and did you solve what you set out to do? If you're happy with the new API, write and/or port tests.&lt;/li&gt;
&lt;li&gt;Replace all other instances of the deprecated message too. Update tests/mocks where needed.&lt;/li&gt;
&lt;li&gt;Rinse and repeat.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another way to get the message across is to use console.log to provide information to developers while they are in development mode. Take care not to ship this to production, as it can look unprofessional. For our React projects we've created a small utility hook called useDeprecationMessage that checks if you're running in development mode,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useDeprecationMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No group specified&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;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&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;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;development&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groupCollapsed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Deprecation warning: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;group&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groupEnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;message&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;



</description>
      <category>javascript</category>
      <category>technicaldebt</category>
      <category>refactoring</category>
      <category>jsdoc</category>
    </item>
    <item>
      <title>How to whitelist your Next.js serverless deployments on Now</title>
      <dc:creator>Jan Hoogeveen</dc:creator>
      <pubDate>Fri, 22 Feb 2019 19:56:19 +0000</pubDate>
      <link>https://dev.to/janhoogeveen/how-to-whitelist-your-nextjs-serverless-deployments-on-now-5d3f</link>
      <guid>https://dev.to/janhoogeveen/how-to-whitelist-your-nextjs-serverless-deployments-on-now-5d3f</guid>
      <description>&lt;p&gt;Originally published on &lt;a href="https://janhoogeveen.eu/blog/whitelisting-access-to-now-serverless-deployments"&gt;janhoogeveen.eu&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I like Next.js. It allows me to build rich data-driven web applications in React that are generated server-side. What I don't like is setting up servers and installing process managers to run node applications for my development and staging servers. To solve this, the clever people at Zeit have developed Now, a serverless platform where you can deploy your web applications with ease. I'd love to use it more, but right now I only see it being a valid choice for production environments.&lt;/p&gt;

&lt;p&gt;One simple requirement from my side is that I want to shield my web applications from the public world while I'm still working on it. Unfortunately, that's something Now.sh is not facilitating.&lt;/p&gt;

&lt;p&gt;The way Now handles security, is by prefixing your project name with a random unique identifier. For instance, if your project is named &lt;em&gt;my-hidden-project&lt;/em&gt;, you can access your deployment on a url like &lt;a href="http://my-hidden-project-**kdoe2jfh2**.now.sh"&gt;http://my-hidden-project-**kdoe2jfh2**.now.sh&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The UID is derived from a large cryptographically random number encoded as 9 alphanumeric characters. However, if you want additional privacy, you can also replace the .now.sh suffix with any custom domain of your choice, making the URL 100% unguessable, so that not even the very existence of the deployment can be verified by third parties."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This sounds like &lt;a href="https://en.wikipedia.org/wiki/Security_through_obscurity"&gt;security through obscurity&lt;/a&gt; to me. That's simply not good enough. I want to be 100% certain that I can deploy a web application and that it's only viewable by me or my team members, even if it has a predictable URL.&lt;/p&gt;

&lt;p&gt;I've googled around but I could not find a solution to this problem. So, here's my hacky solution to this serious problem which I hope gets solved in a native way soon.&lt;/p&gt;

&lt;h1&gt;
  
  
  Checking for visitor IP address in your Now Lambdas
&lt;/h1&gt;

&lt;p&gt;When running a Next.js project with a serverless target in the Next.js Builder (@now/next), it passes the request and response objects, or &lt;a href="https://nextjs.org/docs/#serverless-deployment"&gt;IncomingMessage and ServerResponse&lt;/a&gt; as the docs call them to your lambdas. It also passes these arguments to the getInitialProps method, which is always executed on the server before the server returns any DOM representation at all.&lt;/p&gt;

&lt;p&gt;Here's a barebone example of disallowing everyone to visit your page.&lt;/p&gt;

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

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to next.js!&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="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInitialProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;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="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;403&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;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Not allowed`&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;Page&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Go ahead and try that out. It's not very useful yet, but it proves you can exit your render early and return a 403 response to the browser. From here, it's a matter of expanding on the example to your liking.&lt;/p&gt;

&lt;p&gt;Here's an enhanced version that disallows everyone by default, and whitelists a few IP addresses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to next.js! Your IP address is: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInitialProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;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="c1"&gt;// Disallow access by default&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;shouldDisallowAccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="c1"&gt;// Specify IP's that you want to whitelist. This could be an office/VPN IP address.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allowedIps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;192.168.100.100&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;192.168.100.101&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="c1"&gt;// Read the request objects headers to find our who's trying to access this page&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ip&lt;/span&gt; &lt;span class="o"&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;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-forwarded-for&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remoteAddress&lt;/span&gt;

  &lt;span class="c1"&gt;// This if statement is only valid if the app is deployed through Now. It gets ignored on other environments.&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;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;NOW_REGION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Check if the visitors IP address is allowed&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;allowedIps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;shouldDisallowAccess&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// Return the 403 status code&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;shouldDisallowAccess&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;403&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;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Not allowed for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// This object gets injected into the Pages props, if you want to use them&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;shouldDisallowAccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ip&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;Page&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Alternative solutions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If you don't want to use lambdas, it should be possible to use the &lt;a href="https://nextjs.org/docs/#custom-server-and-routing"&gt;Next.js middleware&lt;/a&gt; and wrap it in your own server. I haven't tried it yet, but I imagine it would be easy to add basic authentication for disallowd IP addresses with this solution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you have control over your own custom domain, it should be possible to point it to Cloudflares DNS servers, and use their firewall to only allow access from specific IP addresses or even IP ranges. That way it should be possible to have a single source of truth of protection - &lt;em&gt;for all projects under that domain&lt;/em&gt; - without having to call the getInitialProps method on every page. Of course you lose the benefits of letting Now manage your domain, but do you really need that for your development servers?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>nextjs</category>
      <category>now</category>
      <category>serverless</category>
      <category>lambda</category>
    </item>
  </channel>
</rss>
