<?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: Austin Shelby</title>
    <description>The latest articles on Forem by Austin Shelby (@austinshelby).</description>
    <link>https://forem.com/austinshelby</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%2F698096%2F4e0749fe-4dc6-439d-bf5f-4cf49751fbc5.jpg</url>
      <title>Forem: Austin Shelby</title>
      <link>https://forem.com/austinshelby</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/austinshelby"/>
    <language>en</language>
    <item>
      <title>What Is Next.js And Why Developers Love It</title>
      <dc:creator>Austin Shelby</dc:creator>
      <pubDate>Tue, 19 Jul 2022 11:07:59 +0000</pubDate>
      <link>https://forem.com/austinshelby/what-is-nextjs-and-why-developers-love-it-42lk</link>
      <guid>https://forem.com/austinshelby/what-is-nextjs-and-why-developers-love-it-42lk</guid>
      <description>&lt;p&gt;Next.js is a web development framework used by companies of all sizes to build websites that are secure, scalable, and quick to build.&lt;/p&gt;

&lt;p&gt;This article is for developers who are already familiar with React and want to have a deep dive into the pros and cons of Next.js and for businesses looking to evaluate new technologies to use in their organization.&lt;/p&gt;

&lt;p&gt;We will be covering the main features and benefits of Next.js and for what kinds of websites it is best suited. You will learn what companies use Next.js in production and how it has treated them so far.&lt;/p&gt;

&lt;p&gt;By the end of this article, you will have the necessary knowledge to decide if Next.js is the correct tool to build your next website project and how you can get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
What is Next.js

&lt;ul&gt;
&lt;li&gt;Static site generation&lt;/li&gt;
&lt;li&gt;Server-side rendering&lt;/li&gt;
&lt;li&gt;Incremental static regeneration&lt;/li&gt;
&lt;li&gt;Client-side rendering&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;What makes Next.js unique?&lt;/li&gt;

&lt;li&gt;What kinds of websites is Next.js best suited for?&lt;/li&gt;

&lt;li&gt;

Who uses Next.js

&lt;ul&gt;
&lt;li&gt;Backlinko&lt;/li&gt;
&lt;li&gt;Hulu&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Pros of Next.js&lt;/li&gt;

&lt;li&gt;Cons of Next.js&lt;/li&gt;

&lt;li&gt;

How to start a new Next.js project

&lt;ul&gt;
&lt;li&gt;Page Routing&lt;/li&gt;
&lt;li&gt;Rendering Pages&lt;/li&gt;
&lt;li&gt;Deploying Next.js&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is Next.js
&lt;/h2&gt;

&lt;p&gt;Next.js is a React based web development framework that works both as a front-end and a back-end. It allows developers to easily build fully fledged websites—saving time and effort.&lt;/p&gt;

&lt;p&gt;The main selling point of Next.js is the ability to choose a different page rendering method for each page—server-side, static, client-side, incremental static regeneration, or on-demand revalidation. This flexibility makes Next.js suitable for most kinds of websites.&lt;/p&gt;

&lt;p&gt;Next.js provides an amazing developer experience with features like TypeScript and ESLing integrations and fast refreshing when developing your website. When deployed, Next.js does automatic compiling, bundling and minifying.&lt;/p&gt;

&lt;p&gt;Compared to React you don’t have to worry about using bundlers like Webpack and Babel or production optimizations such as code splitting.&lt;/p&gt;

&lt;p&gt;Next.js does all of this boring stuff automatically so you can focus on building the actual business logic of your application.&lt;/p&gt;

&lt;p&gt;Let’s take a look at all of the different rendering methods provided by Next.js and see where they might be the most useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static site generation
&lt;/h3&gt;

&lt;p&gt;Next.js provides the ability to render your pages at build time—making them faster and more secure. Static pages can be served from a content delivery network(CDN) uncovering numerous benefits.&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%2F00r2kqg7kkctglj6xt32.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%2F00r2kqg7kkctglj6xt32.jpg" alt="Next.js static site generation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pages loaded from a CDN are available from multiple different locations around the world giving users the least amount of latency when loading a page.&lt;/p&gt;

&lt;p&gt;Because there is no server, the exposed attack surface is much smaller, leading to more resilient and secure websites.&lt;/p&gt;

&lt;p&gt;Static sites are dead simple to deploy and fortunately the most cost-efficient too.&lt;/p&gt;

&lt;p&gt;The downside is that the content on the website will stay the same before the next build of the website which can take anywhere from a few seconds to over ten minutes depending on the size of your website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server-side rendering
&lt;/h3&gt;

&lt;p&gt;The exact opposite of static site generation is server-side rendering. Instead of rendering the page at build time, pages are now rendered on-demand on the server whenever users request them. This might sound great at first as users get the freshest possible data possible but there are some drawbacks that you should be aware of.&lt;/p&gt;

&lt;p&gt;As you might have guessed, serving a server-side rendered page takes a lot more time than serving a static page. And the fact that the server has to do this for every single page request it gets the time starts to add up.&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%2F3ynzryxvbqmq9aot1qbh.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%2F3ynzryxvbqmq9aot1qbh.jpg" alt="Next.js server-side rendering"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next.js is notoriously slow when doing server-side rendering so you will have to think if it fits your use case.&lt;/p&gt;

&lt;p&gt;Server-side rendering happens on the server (as the name suggests). Users who are physically far away from this server have increased latency.&lt;/p&gt;

&lt;p&gt;To decrease latency you need to have more servers around the world—increasing costs and complexity.&lt;/p&gt;

&lt;p&gt;To alleviate these drawbacks, Next.js can be deployed into a serverless environment.&lt;/p&gt;

&lt;p&gt;A serverless environment is very similar to a CDN except instead of just serving static files, these distributed endpoints can also run code for purposes such as server-side rendering. This might help reduce latency, but there is another huge drawback that you need to be aware of.&lt;/p&gt;

&lt;p&gt;Serverless functions have notoriously long wake-up times. This means that if a serverless function endpoint hasn’t been requested in a while it goes to sleep so to say. Any new request then has to wake it up which might take several seconds.&lt;/p&gt;

&lt;p&gt;No, that wasn’t a joke. Doing server-side rendering with Next.js in a serverless environment might increase your page load times to several seconds. I have seen some Next.js sites deployed to Vercel take up to 5 seconds to load.&lt;/p&gt;

&lt;p&gt;The fastest way to do server-side rendering is by using a server instead of a serverless environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incremental static regeneration
&lt;/h3&gt;

&lt;p&gt;Incremental static regeneration or ISR for short is a hybrid of static site generation and server-side rendering. It allows you to statically generate your pages but also generate updated versions of them periodically.&lt;/p&gt;

&lt;p&gt;It also allows you to statically render your pages on-demand and not on build time.&lt;/p&gt;

&lt;p&gt;This technique allows you to only generate a subset of your website’s pages, and then the rest on-demand whenever users request them.&lt;/p&gt;

&lt;p&gt;Your build times will be a lot shorter but you will still get to enjoy the benefits of static site generation, the best of both worlds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client-side rendering
&lt;/h3&gt;

&lt;p&gt;Client-side rendering is what you do when using React, but even in Next.js apps, it has its purpose.&lt;/p&gt;

&lt;p&gt;If you want to have ultra-fast page loads but still have dynamic data, client-side rendering might be the option for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes Next.js unique?
&lt;/h2&gt;

&lt;p&gt;Next.js has gathered a lot of buzz around tech communities as it makes building highly customizable websites easy.&lt;/p&gt;

&lt;p&gt;Next.js cleverly abstracts the data loading methods into their own serverless or server functions making loading data into your pages incredibly simple. This simplifies your website architecture significantly.&lt;/p&gt;

&lt;p&gt;Unlike in traditional React applications, with Next.js you can query your CMS or a database directly on your pages.&lt;/p&gt;

&lt;p&gt;This makes having a proxy backend service redundant. Next.js developers can focus on integrating the frontend with their preferred data source without worrying too much about backend web development.&lt;/p&gt;

&lt;p&gt;Next.js comes out of the box with a ton of utilities used in common web applications.&lt;/p&gt;

&lt;p&gt;Dynamic page routes, redirects, rewrites, middlewares, and i18n are just some of the things that make Next.js such a great solution.&lt;/p&gt;

&lt;p&gt;With these utilities, developers can build features that will help businesses with their goals.&lt;/p&gt;

&lt;p&gt;Marketers will love the A/B content split testing and autonomy to create pages through a CMS.&lt;/p&gt;

&lt;p&gt;Search engine optimizers will love the fast page load speed and fully customizable metadata such as Open Graph tags and structured data.&lt;/p&gt;

&lt;p&gt;Developers love the freedom to create new features using all the tools that come with the React ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What kinds of websites is Next.js best suited for?
&lt;/h2&gt;

&lt;p&gt;The multiple different rendering methods, dynamic routes, and the ease of fetching data in your pages make it possible to build all kinds of websites with Next.js.&lt;/p&gt;

&lt;p&gt;Next.js is most commonly used to build content-driven websites such as corporate blogs, customer portals, documentation sites, and e-commerce stores.&lt;/p&gt;

&lt;p&gt;There are a few things that you need to keep in mind though.&lt;/p&gt;

&lt;p&gt;Next.js API routes can handle simple JSON requests but if you need anything more advanced such as webhooks or server-sent events you will have to look elsewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who uses Next.js
&lt;/h2&gt;

&lt;p&gt;Next.js is used by everyone from hobby programmers to Fortune 500 companies.&lt;/p&gt;

&lt;p&gt;Every day more and more companies are moving to Next.js for its performance and developer experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backlinko
&lt;/h3&gt;

&lt;p&gt;One of the most prominent SEO blogs out there, Backlinko, was struggling with severe performance issues.&lt;/p&gt;

&lt;p&gt;Their old WordPress website wasn’t cutting it in 2021 so they decided to do a complete rebuild with Next.js while still keeping all of their data in WordPress.&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%2Fjdee51a36mmt4smv2ecd.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%2Fjdee51a36mmt4smv2ecd.png" alt="Backlinko Next.js website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This solution worked perfectly as their new website loads three times faster.&lt;/p&gt;

&lt;p&gt;Backlinko is a great case of how updating your old website into Next.js can bring great performance benefits which will affect your site’s SEO.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hulu
&lt;/h3&gt;

&lt;p&gt;One of the global leading TV and movie streaming platforms, Hulu has big stakes on the line when it comes to its website.&lt;/p&gt;

&lt;p&gt;One of the main requirements for Hulu was the ability of server-side rendering. Next.js made implementing this requirement incredibly easy for them.&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%2Ff5deab0axgjdmihelhh9.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%2Ff5deab0axgjdmihelhh9.png" alt="Hulu Next.js website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The automatic code splitting by Next.js allowed the team at Hulu to implement features that didn’t slow the website down.&lt;/p&gt;

&lt;p&gt;Thanks to Next.js Hulu now enjoys fewer bugs and increased developer productivity.&lt;/p&gt;

&lt;p&gt;Hulu is a great example of how Next.js can handle even the most critical requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros of Next.js
&lt;/h2&gt;

&lt;p&gt;So far we have talked about who is using Next.js and what their reasons are. Let’s break it all down.&lt;/p&gt;

&lt;p&gt;Next.js allows you to build full-fledged web applications thanks to its already large set of internal functionality and the massive library of third-party tools.&lt;/p&gt;

&lt;p&gt;These third-party tools allow you to quickly and easily implement common features such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication with next-auth&lt;/li&gt;
&lt;li&gt;Search engine optimization with next-seo&lt;/li&gt;
&lt;li&gt;Type-safe API routes with trpc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other than Next.js specific packages, you get to use all React packages as well.&lt;/p&gt;

&lt;p&gt;These will speed up development time drastically and decrease your time to market.&lt;/p&gt;

&lt;p&gt;The static rendering methods allow you to take full advantage of SEO, especially if you are doing client-side rendering currently.&lt;/p&gt;

&lt;p&gt;Rendering your pages statically allows you to say goodbye to traditional servers and enjoy the additional speed, scalability, and security that CDNs bring.&lt;/p&gt;

&lt;p&gt;Now it is important to understand that Next.js is just a tool. It won’t magically make your website rank super high on search engines or increase your sales—like some other agencies are advertising.&lt;/p&gt;

&lt;p&gt;I’m all about giving you a holistic view of things without selling you snake oil.&lt;/p&gt;

&lt;p&gt;Let’s take a look at why you shouldn’t use Next.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cons of Next.js
&lt;/h2&gt;

&lt;p&gt;Next.js is not all sunshine and roses and there are some drawbacks that you should be aware of.&lt;/p&gt;

&lt;p&gt;Unlike most full-stack frameworks like Django, Spring, or Rails—Next.js hasn’t matured that much yet.&lt;/p&gt;

&lt;p&gt;What I mean is that certain things that should be simple, are not.&lt;/p&gt;

&lt;p&gt;There are not that many agreed-upon patterns on how you should build your web application which leads to a lot of guesswork and mistakes.&lt;/p&gt;

&lt;p&gt;That’s why Next.js is recommended to developers who already have experience with building full-stack web applications because they know what to look out for.&lt;/p&gt;

&lt;p&gt;Things that are not working well are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Databases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next.js provides a lot of choices on which direction to take your project, but with this abundance of choice comes big responsibility.&lt;/p&gt;

&lt;p&gt;It is easy to take a Next.js project in the wrong direction if you don’t know what you are doing.&lt;/p&gt;

&lt;p&gt;There are a lot of weird kinks in Next.js that only seasoned pros know about. Things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No default locale prefix&lt;/li&gt;
&lt;li&gt;A lot of things will opt you out of full static generation&lt;/li&gt;
&lt;li&gt;Performance issues server-side rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to take Next.js for a test run I’m going to give you the instructions on how to get started in just a few minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to start a new Next.js project
&lt;/h2&gt;

&lt;p&gt;To start a new Next.js project you need to have Node.js installed on your computer.&lt;/p&gt;

&lt;p&gt;Create a new Next.js project with npx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is going to bring up a wizard that will guide you through the creation of the project.&lt;/p&gt;

&lt;p&gt;Next.js will automatically set you up for a good start by creating the recommended folder structure and useful scripts to run your application.&lt;/p&gt;

&lt;p&gt;The page in the location &lt;code&gt;pages/index.jsx&lt;/code&gt; is mapped to / in your website.&lt;/p&gt;

&lt;p&gt;Run the command &lt;code&gt;npm run dev&lt;/code&gt; to start your development server and visit &lt;code&gt;http://localhost:3000&lt;/code&gt; to view your application running.&lt;/p&gt;

&lt;p&gt;Feel free to change the contents inside &lt;code&gt;pages/index.jsx&lt;/code&gt; file to see it change in real-time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Page routing
&lt;/h3&gt;

&lt;p&gt;To see Next.js’s page routing in action create a file called &lt;code&gt;about.jsx&lt;/code&gt; inside the &lt;code&gt;pages/&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;This file will map to &lt;code&gt;/about&lt;/code&gt; in your application.&lt;/p&gt;

&lt;p&gt;Fill the file with this code to create a simple page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AboutPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello World&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;AboutPage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rendering pages
&lt;/h3&gt;

&lt;p&gt;The default behavior of Next.js is to pre-render every page. This is the most optimal way to render your web application.&lt;/p&gt;

&lt;p&gt;Let’s see how we can load some data on our about page.&lt;/p&gt;

&lt;p&gt;To keep our pre-rendering we need to use the static data fetching method &lt;code&gt;getStaticProps&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Change the contents of the about page to fetch the latest daily cat facts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AboutPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;facts&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;facts&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;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getStaticProps&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="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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cat-fact.herokuapp.com/facts&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;json&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="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;AboutPage&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 have created your very own cat facts application!&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying Next.js
&lt;/h3&gt;

&lt;p&gt;Deploying your Next.js application depends on what types of rendering methods you are using in your application.&lt;/p&gt;

&lt;p&gt;If your application is 100% static you can do what is called a static export. Next.js will build the website into completely static files.&lt;/p&gt;

&lt;p&gt;Using static export will opt out of features such as server-side rendering, incremental static regeneration, i18n, and API routes so you have to consider it carefully.&lt;/p&gt;

&lt;p&gt;Static sites are the easiest and cheapest to render. I recommend using a dedicated Next.js host such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Netlify&lt;/li&gt;
&lt;li&gt;Vercel&lt;/li&gt;
&lt;li&gt;DigitalOcean&lt;/li&gt;
&lt;li&gt;Render&lt;/li&gt;
&lt;li&gt;layer0&lt;/li&gt;
&lt;li&gt;Heroku&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these services start for free and come with features such as SSL certificates, CDN, custom domain integrations, and CI pipelines. All you have to do is just connect your GitHub repository to get started.&lt;/p&gt;

&lt;p&gt;If your application uses any of the features that opt out of static export, you have two choices.&lt;/p&gt;

&lt;p&gt;Serverless platform or server platform.&lt;/p&gt;

&lt;p&gt;To note the differences quickly:&lt;/p&gt;

&lt;p&gt;Serverless takes care of the infrastructure and scaling for you at the cost of less control, functionality, and slow start times.&lt;/p&gt;

&lt;p&gt;Served might take more time to set up if you are not using a Next.js specific host, has a cost attached to running your server 24/7 but comes with performance benefits.&lt;/p&gt;

&lt;p&gt;For serverless you have the following choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Netlify&lt;/li&gt;
&lt;li&gt;Vercel&lt;/li&gt;
&lt;li&gt;layer0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for the server you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DigitalOcean&lt;/li&gt;
&lt;li&gt;Heroku&lt;/li&gt;
&lt;li&gt;Render&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, you can always self-host Next.js but this will require knowledge of technologies such as Nginx, Kubernetes, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article we covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How Next.js helps you build fully-fledged websites quickly and efficiently.&lt;/li&gt;
&lt;li&gt;How the multiple different rendering methods of Next.js allow you to optimize your website's pages to your specific needs.&lt;/li&gt;
&lt;li&gt;How Next.js can simplify your infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that you know what Next.js is used for and how it can help you build websites quicker you can start learning more about the internals of Next.js by going over the official Next.js quick start guide.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Build a React Form with react-hook-form and zod</title>
      <dc:creator>Austin Shelby</dc:creator>
      <pubDate>Mon, 13 Jun 2022 09:23:50 +0000</pubDate>
      <link>https://forem.com/austinshelby/build-a-react-form-with-react-hook-form-and-zod-1a7j</link>
      <guid>https://forem.com/austinshelby/build-a-react-form-with-react-hook-form-and-zod-1a7j</guid>
      <description>&lt;p&gt;In this tutorial you will learn how to use react-hook-form and zod to build a form with validation.&lt;/p&gt;

&lt;p&gt;If you prefer a video tutorial instead, you can watch it below.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4zt1eadehKQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AustinShelby/react-hook-form-and-zod-tutorial" rel="noopener noreferrer"&gt;Clone the project from GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is what we are going to be building:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1gkxlce0vw71xm65csfh.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%2F1gkxlce0vw71xm65csfh.jpg" alt="React form with validation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start with a little bit of boilerplate code for our form component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;FC&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="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Tiers&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BRONZE&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="s2"&gt;Bronze&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get average points&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.99&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="s2"&gt;SILVER&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="s2"&gt;Silver&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get extra points&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.99&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="s2"&gt;GOLD&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="s2"&gt;Gold&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The highest possible tier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;19.99&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&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;space-y-10&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="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;label&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;block&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="nx"&gt;span&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;block&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;Email&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&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;input&lt;/span&gt;
            &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&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="s2"&gt;`block border text-lg px-4 py-3 mt-2 rounded-lg border-gray-200 focus:bg-white text-gray-900 focus:border-blue-600 focus:ring-0 outline-none w-full  disabled:bg-gray-100 disabled:text-gray-400 disabled:cursor-not-allowed`&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;/label&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="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;label&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;flex items-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="nx"&gt;input&lt;/span&gt;
            &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkbox&lt;/span&gt;&lt;span class="dl"&gt;"&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;block border text-lg rounded w-6 h-6 border-gray-200 text-blue-600 focus:ring-0 focus:outline-none focus:ring-offset-0 disabled:text-gray-200 disabled:cursor-not-allowed&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="nx"&gt;span&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;block ml-4&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;I&lt;/span&gt; &lt;span class="nx"&gt;accept&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;Terms&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;Service&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&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;/label&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="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="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;block&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;Payment&lt;/span&gt; &lt;span class="nx"&gt;Tier&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="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;space-y-2 mt-2&lt;/span&gt;&lt;span class="dl"&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;Tiers&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;tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&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="s2"&gt;`border rounded-lg border-gray-200 text-gray-900`&lt;/span&gt;&lt;span class="p"&gt;}&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;tier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;label&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="s2"&gt;`flex justify-between px-6 py-4 items-center cursor-pointer`&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;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="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="s2"&gt;`font-medium text-lg`&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;tier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;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;p&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="s2"&gt;`text-sm opacity-80`&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;tier&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="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="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;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;flex items-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="nx"&gt;p&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="s2"&gt;`font-medium mr-4 text-sm`&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;tier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&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;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currency&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;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;input&lt;/span&gt;
                      &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;radio&lt;/span&gt;&lt;span class="dl"&gt;"&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;w-6 h-6 border ring-0 border-gray-200 text-blue-600 disabled:text-gray-300 outline-none focus:ring-0 focus:ring-offset-0 cursor-pointer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                      &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/label&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="p"&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;/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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
        &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&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;w-full px-8 py-4 flex items-center justify-center uppercase text-white font-semibold bg-blue-600 rounded-lg disabled:bg-gray-100 disabled:text-gray-400&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;Create&lt;/span&gt; &lt;span class="nx"&gt;account&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&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;This just gets us the form with styling without any functionality added yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a form validation schema with zod
&lt;/h2&gt;

&lt;p&gt;Let's build a schema that matches the values in our form.&lt;/p&gt;

&lt;p&gt;Let's start off by importing the necessary libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;z&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="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SubmitHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useForm&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="s2"&gt;react-hook-form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;zodResolver&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="s2"&gt;@hookform/resolvers/zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And let's define our schema with some custom error messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FormSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&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;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;literal&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;invalid_type_error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You must accept Terms and Conditions.&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;tier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;invalid_type_error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Please select a payment tier.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refine&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;val&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;Tiers&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;tier&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;tier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use a string validation chained with an email validation for our email field.&lt;/p&gt;

&lt;p&gt;For the accept terms of service checkbox we will use literal validator with the value of true. Literal just means that the field must be exactly this value. Notice that we are also using a custom error message for invalid_type_error. Later in this tutorial you will learn how to show the error messages.&lt;/p&gt;

&lt;p&gt;For our payment tier validation we first check if the value is a string and then use a custom validation using refine to check if the string matches one of the IDs from our predefined Tiers array.&lt;/p&gt;

&lt;p&gt;Let's infer a type from it that we are going to use moving forward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FormSchemaType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;FormSchema&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;We can see that TypeScript inferred the following type from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FormSchemaType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;accept&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="nl"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will help us keep all our functions type safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using react-hook-form
&lt;/h2&gt;

&lt;p&gt;Let's use react-hook-form to handle our form state.&lt;/p&gt;

&lt;p&gt;Add this code inside your Form component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;Form&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;formState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isSubmitting&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useForm&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FormSchemaType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;zodResolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;FormSchema&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="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SubmitHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FormSchemaType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;data&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;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&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;await&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have used the &lt;code&gt;useForm&lt;/code&gt; function and given it the type of our schema. This will help TypeScript to properly keep our code type safe.&lt;/p&gt;

&lt;p&gt;We have created a &lt;code&gt;onSubmit&lt;/code&gt; function that after a 3 second delay will log the validated form data into the console. I wanted to add an artificial delay to better emulate a real world scenario.&lt;/p&gt;

&lt;p&gt;If we try filling the form and submitting it, nothing happens. This is because we haven't yet registered the form inputs or made the form to use our custom &lt;code&gt;onSubmit&lt;/code&gt; function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registering inputs
&lt;/h3&gt;

&lt;p&gt;We can register the form inputs by using the register function we get from &lt;code&gt;useForm&lt;/code&gt; by giving the name of the field that matches the one in our schema.&lt;/p&gt;

&lt;p&gt;For example for the email field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
            &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&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="s2"&gt;`block border text-lg px-4 py-3 mt-2 rounded-lg border-gray-200 focus:bg-white text-gray-900 focus:border-blue-600 focus:ring-0 outline-none w-full  disabled:bg-gray-100 disabled:text-gray-400 disabled:cursor-not-allowed`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And accept terms of service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
            &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkbox&lt;/span&gt;&lt;span class="dl"&gt;"&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;block border text-lg rounded w-6 h-6 border-gray-200 text-blue-600 focus:ring-0 focus:outline-none focus:ring-offset-0 disabled:text-gray-200 disabled:cursor-not-allowed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accept&lt;/span&gt;&lt;span class="dl"&gt;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for the payment tier radio button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
                      &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;radio&lt;/span&gt;&lt;span class="dl"&gt;"&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;w-6 h-6 border ring-0 border-gray-200 text-blue-600 disabled:text-gray-300 outline-none focus:ring-0 focus:ring-offset-0 cursor-pointer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                      &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                      &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tier&lt;/span&gt;&lt;span class="dl"&gt;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using custom onSubmit handler
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;handleSubmit&lt;/code&gt; function we get from &lt;code&gt;useForm&lt;/code&gt; does two things. First it disables any default form submission behaviors, and second it calls our custom &lt;code&gt;onSubmit&lt;/code&gt; function with the validated data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&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;space-y-10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if you try filling the form and submitting it you will see that after 3 seconds the validated form values get logged into the console.&lt;/p&gt;

&lt;p&gt;If you fill the form with invalid values you will see that the correct error messages appear.&lt;/p&gt;

&lt;p&gt;One problem you might have noticed is that you can click on the create account button multiple times and the form will submit multiple times. This is obviously something we don't want to happen.&lt;/p&gt;

&lt;p&gt;Let's fix that by disabling all form inputs and the submit button when the form is submitting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disabling form inputs
&lt;/h3&gt;

&lt;p&gt;We will use the &lt;code&gt;isSubmitting&lt;/code&gt; value we get from &lt;code&gt;formState&lt;/code&gt; which we get from &lt;code&gt;useForm&lt;/code&gt; to check whether the form is currently submitting or not.&lt;/p&gt;

&lt;p&gt;For our inputs and submit button we will disable them using this value.&lt;/p&gt;

&lt;p&gt;Example for our email input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
            &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&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="s2"&gt;`block border text-lg px-4 py-3 mt-2 rounded-lg border-gray-200 focus:bg-white text-gray-900 focus:border-blue-600 focus:ring-0 outline-none w-full  disabled:bg-gray-100 disabled:text-gray-400 disabled:cursor-not-allowed`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
            &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isSubmitting&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the &lt;code&gt;disabled={isSubmitting}&lt;/code&gt; attribute to other fields and the submit button.&lt;/p&gt;

&lt;p&gt;Now when you submit the form you will notice that all the fields and the submit button get disabled until the data gets logged into the console.&lt;/p&gt;

&lt;p&gt;But what about if the form is not valid?&lt;/p&gt;

&lt;h3&gt;
  
  
  Show error messages
&lt;/h3&gt;

&lt;p&gt;Currently if you try submitting a form with invalid fields, nothing happens.&lt;/p&gt;

&lt;p&gt;Let's change that by conditionally showing error messages for each of the fields if they are invalid.&lt;/p&gt;

&lt;p&gt;For our email field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
            &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&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="s2"&gt;`block border text-lg px-4 py-3 mt-2 rounded-lg border-gray-200 focus:bg-white text-gray-900 focus:border-blue-600 focus:ring-0 outline-none w-full  disabled:bg-gray-100 disabled:text-gray-400 disabled:cursor-not-allowed`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
            &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isSubmitting&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;/label&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;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;text-sm text-red-600 mt-1&lt;/span&gt;&lt;span class="dl"&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;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and accept terms of service button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accept&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;text-sm text-red-600 mt-1&lt;/span&gt;&lt;span class="dl"&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;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accept&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="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="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and for payment tiers after the &lt;code&gt;ul&lt;/code&gt; tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tier&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;text-sm text-red-600 mt-1&lt;/span&gt;&lt;span class="dl"&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;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tier&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="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="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you try submitting the form with invalid fields you should see the error messages showing.&lt;/p&gt;

&lt;p&gt;The default behavior of react-hook-form is to validate the form when submitting for the first time. After this it will validate the form after every key press and blur event.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial you learned how to combine react-hook-form and zod to create a fully fledged form with validation.&lt;/p&gt;

&lt;p&gt;For next steps, dive into the &lt;a href="https://react-hook-form.com/advanced-usage" rel="noopener noreferrer"&gt;react-hook-form documentation&lt;/a&gt; to learn more advanced concepts such as: dynamically generated fields and multi step forms.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>react</category>
    </item>
    <item>
      <title>Why I Specialize in Next.js Website Development</title>
      <dc:creator>Austin Shelby</dc:creator>
      <pubDate>Fri, 20 May 2022 08:58:27 +0000</pubDate>
      <link>https://forem.com/austinshelby/why-i-specialize-in-nextjs-website-development-3ha6</link>
      <guid>https://forem.com/austinshelby/why-i-specialize-in-nextjs-website-development-3ha6</guid>
      <description>&lt;p&gt;If you are just wondering if Next.js is a good choice for building a website, the answer is definitely YES. I will be telling you all about how Next.js compares to other frameworks like Django or Java Spring and why it might even be better is certain areas.&lt;/p&gt;

&lt;p&gt;Over the years I have tried tons of different website development frameworks such as Django and Flask that are written in Python, and Java Spring.&lt;/p&gt;

&lt;p&gt;All of these frameworks lacked something and I felt like I was fighting against the limitations of them.&lt;/p&gt;

&lt;p&gt;During this time I was heavily into making React.js websites using create-react-app. It worked great.&lt;/p&gt;

&lt;p&gt;Until it didn't.&lt;/p&gt;

&lt;p&gt;If you are a react developer you have probably faced these same issues too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Client side rendering is bad for SEO and website performance&lt;/li&gt;
&lt;li&gt;    You are required to create a separate backend service if you are dealing with sensitive data such as API keys, authentication or private information&lt;/li&gt;
&lt;li&gt;    Bundle sizes are huge&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During this time I heard about Next.js and from the first look it seemed to solve all of these issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes Next.js different
&lt;/h2&gt;

&lt;p&gt;The main selling points of Next.js for me are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Multiple different rendering methods (static, server-side, client-side)&lt;/li&gt;
&lt;li&gt;    Backend capabilities with API routes&lt;/li&gt;
&lt;li&gt;    Using server side code directly in your frontend pages&lt;/li&gt;
&lt;li&gt;    Incredible tools that will make your life so much easier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let's take a deep dive and see why these reasons made Next.js a no brainer to me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Built for SEO
&lt;/h3&gt;

&lt;p&gt;There are two things that make Next.js a killer website framework for SEO.&lt;/p&gt;

&lt;p&gt;Its incredible performance and multiple different page rendering methods.&lt;/p&gt;

&lt;p&gt;Next.js allows you to pre-render your pages before your users request them, gaining huge performance boost. The only downside is that if you want to make any changes to the page's content you have rebuild the whole site.&lt;/p&gt;

&lt;p&gt;An average website with ten to a hundred pages takes around one to two minutes to build.&lt;/p&gt;

&lt;p&gt;Always calculate these risks and rewards before you choose a certain rendering method. Check how many pages you have, how often they are going to be updated on average, and how long does building them take.&lt;/p&gt;

&lt;p&gt;An alternative for pages that update often is to use server-side rendering.&lt;/p&gt;

&lt;p&gt;This will cause the page to be built on demand whenever users request it. This takes a little longer than statically rendering it ahead of time. Especially if you are using serverless functions.&lt;/p&gt;

&lt;p&gt;If you are using server-side rendering a lot consider hosting your website on a platform like DigitalOcean App Platform which is not going to slow you down as much serverless platforms like Netlify or Vercel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Web Vitals
&lt;/h3&gt;

&lt;p&gt;Google's Core Web Vital metrics have become an important thing to consider if SEO is important for your website.&lt;/p&gt;

&lt;p&gt;Thankfully Next.js performs extremely well in this regard thanks to its multiple different render methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  API routes
&lt;/h3&gt;

&lt;p&gt;Basic React websites suffer from a major problem. All of your code will be visible to all users.&lt;/p&gt;

&lt;p&gt;This means that you cannot store secrets like API keys in your code. Most common use cases for API keys are fetching data from a database or a content management system, or submitting forms for example.&lt;/p&gt;

&lt;p&gt;If your website was built with React only you would be forced to built a separate back-end service just so you can keep your API keys hidden. This obviously increases development time significantly and makes your architecture more complex.&lt;/p&gt;

&lt;p&gt;Next.js solves this problem by allowing you to create API routes within your regular Next.js application. This allows you to build your website significantly faster and more securely.&lt;/p&gt;

&lt;p&gt;Another benefit is that you can use your backend code directly in your frontend pages without exposing any confidential data. This means that you can query your database or content management system within your website pages, allowing you to skip creating API routes altogether.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incredible tooling
&lt;/h3&gt;

&lt;p&gt;The open source community has built some incredible tools for Next.js that make building some common features fast and easy.&lt;/p&gt;

&lt;p&gt;For authentication there is &lt;a href="https://next-auth.js.org/"&gt;next-auth&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For end-to-end typesafe APIs there is &lt;a href="https://trpc.io/"&gt;tRPC&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For SEO there is &lt;a href="https://github.com/garmeeh/next-seo"&gt;next-seo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These tools are some of my favorites which I use in almost all of my website projects.&lt;/p&gt;

&lt;p&gt;In addition to these you will of course have access to all React tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Next.js advantage
&lt;/h2&gt;

&lt;p&gt;All of these things are nice, but how do they translate to actual business results?&lt;/p&gt;

&lt;p&gt;After I switched to Next.js I noticed that my client projects took less time, were less error prone, and performed better in regards to SEO.&lt;/p&gt;

&lt;p&gt;That's why when clients come to ask me for help for their website I usually end up recommending Next.js&lt;/p&gt;

&lt;p&gt;Next.js is the perfect website framework for websites such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Real estate websites&lt;/li&gt;
&lt;li&gt;    Blogs&lt;/li&gt;
&lt;li&gt;    Landing pages&lt;/li&gt;
&lt;li&gt;    Complex web applications&lt;/li&gt;
&lt;li&gt;    Information heavy sites&lt;/li&gt;
&lt;li&gt;    eCommerce sites&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of my clients, StartSteps Digital Education, got up-to 600 percent performance increase on certain pages. &lt;a href="https://media.graphassets.com/ElxlrwmlT3uQYSeCLf1t"&gt;Read the whole case study here&lt;/a&gt;. This ended up increasing the amount of traffic they are getting from search engines thanks to its SEO boost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;p&gt;You should consider using Next.js if SEO and website performance are important for your business.&lt;/p&gt;

&lt;p&gt;Next.js is a great solution especially for freelancers as it allows just a single person to take control of the whole website architecture saving tons of time and money.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>So you have an idea for a startup—here's how to build it</title>
      <dc:creator>Austin Shelby</dc:creator>
      <pubDate>Tue, 30 Nov 2021 11:36:33 +0000</pubDate>
      <link>https://forem.com/austinshelby/so-you-have-an-idea-for-a-startup-heres-how-to-build-it-5cpj</link>
      <guid>https://forem.com/austinshelby/so-you-have-an-idea-for-a-startup-heres-how-to-build-it-5cpj</guid>
      <description>&lt;p&gt;So you have an idea for the next unicorn startup and the only thing between you and success is actually building it.&lt;/p&gt;

&lt;p&gt;I have been there too and while my side projects never got to a billion dollar evaluation—I learned how to build them. Quickly and efficiently.&lt;/p&gt;

&lt;p&gt;After reading this article you will have the knowledge to choose the correct tech stack for your startup that the top 0.1% of companies are using.&lt;/p&gt;

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

&lt;p&gt;The most important factor for startups is to create websites quickly without compromising the development of features added in the future.&lt;/p&gt;

&lt;p&gt;There have been numerous website architectures emerging from this need but only one of them has really gotten mainstream attention.&lt;/p&gt;

&lt;p&gt;It’s called Jamstack.&lt;/p&gt;

&lt;p&gt;Some of the main benefits of Jamstack architecture are speed, security, developer experience, and the ease of scaling.&lt;/p&gt;

&lt;p&gt;Just like the technology director at Pac Macmillan—James Luscombe says about moving their tech stack to Jamstack:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The move to the Jamstack was about speed, accessibility, and taking the worry out of deployment&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this article we will be building a Jamstack based architecture where most of your efforts can be put into actually programming the core business logic of your website instead of having to worry about the boring stuff.&lt;/p&gt;

&lt;p&gt;Instead of focusing on individual technologies, I want you to understand the general concepts behind choosing each piece.&lt;/p&gt;

&lt;h2&gt;
  
  
  The best frontend
&lt;/h2&gt;

&lt;p&gt;The best tool to build a frontend for startups is Next.js. Even people not so familiar with frontend web development have heard about Next.js&lt;/p&gt;

&lt;p&gt;There are a few good reasons for it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It comes &lt;em&gt;batteries included&lt;/em&gt; greatly reducing the time to setup a project&lt;/li&gt;
&lt;li&gt;It has exceptionally low page load times which is great for Core Web Vitals and SEO&lt;/li&gt;
&lt;li&gt;It comes with kick ass features like i18n, routing, server-side rendering, and now middlewares.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are not sure if your website's performance is limiting your ranking on search engine results, take my &lt;a href="https://www.austinshelby.com/resources/core-web-vitals-test" rel="noopener noreferrer"&gt;core web vitals test&lt;/a&gt; (takes 3 seconds) to check your score.&lt;/p&gt;

&lt;p&gt;Instead of having to build a backend just to create a few API endpoints so you can get the data to your frontend, Next.js allows you to directly query data source of your choice from the frontend.&lt;/p&gt;

&lt;p&gt;Of course they ingeniously keep this secure by using either static site generation or server side rendering.&lt;/p&gt;

&lt;p&gt;Which, as I mentioned earlier greatly reduces development time as you don’t need a dedicated backend.&lt;/p&gt;

&lt;p&gt;Instead, you can put your efforts into building a more smart content management solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The best backend
&lt;/h2&gt;

&lt;p&gt;When choosing a backend you have to consider who is going to be using your website and for what purpose.&lt;/p&gt;

&lt;p&gt;Do they need a visual interface?&lt;/p&gt;

&lt;p&gt;Are they going to be manually entering data?&lt;/p&gt;

&lt;p&gt;Based on what we know so far about building minimum viable products we are going to be looking at two different solutions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GraphCMS&lt;/li&gt;
&lt;li&gt;Fauna&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again to remind you, the main thing we are looking for is a backend that allows us to focus on the business logic without having to worry about the boring stuff—&lt;strong&gt;greatly reducing the development time&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The easiest solution
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://graphcms.com/" rel="noopener noreferrer"&gt;GraphCMS&lt;/a&gt; comes with an easy to use and simple graphical UI that allows non-technical people to add, edit, delete, and publish content.&lt;/p&gt;

&lt;p&gt;Unlike most content management systems GraphCMS allows you to also create items programmatically, not only read.&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%2Ffv339guqgdruwfgbetgk.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%2Ffv339guqgdruwfgbetgk.png" alt="GraphCMS UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the name suggests, it comes out of the box with a GraphQL API. The documentation is excellent and the very generous free tier allows you to kick-start your business in record time.&lt;/p&gt;

&lt;p&gt;It comes with some pro features like localization and remote data fetching to federate content from external sources.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;GraphCMS gives you instant GraphQL Content APIs to create, enrich, unify, and deliver your content across platforms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The best solution for speed
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://fauna.com/" rel="noopener noreferrer"&gt;FaunaDB&lt;/a&gt; is the closest you can get to the database without compromising developer experience or productivity.&lt;/p&gt;

&lt;p&gt;Simply put, it is the best solution when you need high performance, scalability, ACID transactions and advanced features like streaming.&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%2Fkcmvfuu2nfxmp7eucgj4.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%2Fkcmvfuu2nfxmp7eucgj4.png" alt="Fauna UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fauna prides itself in &lt;em&gt;Get started in minutes, without the heavy lift&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Fauna comes with a graphical user interface but it’s most powerful when used through the API with its own query language FQL.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Focus on your application instead of managing database clusters, provisioning capacity, creating replicas, or sharding data. Fauna does all the work for you behind the API so that you don’t have to.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Hosting
&lt;/h2&gt;

&lt;p&gt;Hosting is traditionally considered a very difficult thing to do.&lt;/p&gt;

&lt;p&gt;For example—you have to take care of CI/CD pipelines. This includes automated build and test setups. Deployment scripts, rollbacks and all kings of other boring stuff.&lt;/p&gt;

&lt;p&gt;The problem of creating all of this from scratch by yourself is that the time spent doing all of that is time NOT spent on building your actual product.&lt;/p&gt;

&lt;p&gt;We want a solution that already comes with all of those features.&lt;/p&gt;

&lt;p&gt;The hosting solution that I recommend is &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&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%2F778yi5xvab3mockk1hwg.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%2F778yi5xvab3mockk1hwg.png" alt="Netlify UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Netlify brings tons of features that you love and even more features that you probably didn’t even know you want like A/B testing.&lt;/p&gt;

&lt;p&gt;First of all their CDN is globally available meaning people from all over the world can access your website lightning fast.&lt;/p&gt;

&lt;p&gt;They are fully supporting the git feature branch workflow that agile teams all over the world love.&lt;/p&gt;

&lt;p&gt;They have preview deployments for each branch or pull request you make, making it easy to test your website on every change.&lt;/p&gt;

&lt;p&gt;Netlify has a very generous free tier meaning that you can get started without paying a single cent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Third party services
&lt;/h2&gt;

&lt;p&gt;Another major thing you have to focus on when building your startups is not reinventing the wheel.&lt;/p&gt;

&lt;p&gt;Time is money. So don’t waste it by building something from scratch when an already made solution exists.&lt;/p&gt;

&lt;p&gt;Instead of adding an elastic search database to your stack to get full text search, just use Algolia.&lt;/p&gt;

&lt;p&gt;Instead of reinventing video streaming and automatic image optimizations and sharing, just use Bunny CDN.&lt;/p&gt;

&lt;p&gt;By using third party services you can take the stress out of building your product by not having to worry about coding every little thing by yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now that you know why Jamstack won't slow you down when coding your product, you can confidently start to build your startup.&lt;/p&gt;

&lt;p&gt;Just like we covered, Jamstack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows you to focus on programming the core business logic of your application&lt;/li&gt;
&lt;li&gt;Makes your website fast and secure&lt;/li&gt;
&lt;li&gt;Is easy to extend with third party APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are interested in the actual technical side of building a startup, take a look at &lt;a href="https://www.youtube.com/c/AustinShelby" rel="noopener noreferrer"&gt;my YouTube channel&lt;/a&gt; where I teach exactly that—using modern web development techniques.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>You are reading environment variables the wrong way in Next.js</title>
      <dc:creator>Austin Shelby</dc:creator>
      <pubDate>Mon, 18 Oct 2021 12:38:54 +0000</pubDate>
      <link>https://forem.com/austinshelby/you-are-reading-environment-variables-the-wrong-way-in-nextjs-45da</link>
      <guid>https://forem.com/austinshelby/you-are-reading-environment-variables-the-wrong-way-in-nextjs-45da</guid>
      <description>&lt;p&gt;If you have ever written code that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://www.example.com/api/blog?api_key=&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;API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Then you are doing it wrong!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's why this is a bad idea.&lt;/p&gt;

&lt;p&gt;In a scenario where you build the application without having set the &lt;code&gt;API_KEY&lt;/code&gt; environment variable the application will use &lt;code&gt;undefined&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;Obviously &lt;code&gt;undefined&lt;/code&gt; is not the correct api key which will make any request using that URL fail.&lt;/p&gt;

&lt;p&gt;The problem here is that when the error surfaces, the message will be very misleading and look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Unauthorized
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this error will only show up when you try to use the url to fetch the blog posts.&lt;/p&gt;

&lt;p&gt;If fetching the blog posts is an essential feature, &lt;strong&gt;the application should not have even compiled without the api key being available&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Naively expecting the &lt;code&gt;API_KEY&lt;/code&gt; environment variable to exist will hide the bug and make this problem a pain to debug due to the misleading error message.&lt;/p&gt;

&lt;p&gt;To fix this issue we need two things.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When a problem exists that causes the application to not function, the application needs to fail immediately and visibly.&lt;/li&gt;
&lt;li&gt;A meaningful abstraction to encapsulate the loading of environment variables.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to load environment variables in Next.js
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This works with any node.js application. Next.js just makes this easier, as it comes with a lot of necessary boilerplate code&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let me show you how to use environment variables in Next.js correctly, and then explain why this works.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.env.local&lt;/code&gt; file. Here you will put all of your environment variables you want to use on your local development environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API_KEY=secret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next.js automatically adds this file to &lt;code&gt;.gitignore&lt;/code&gt; so you don't have to worry about it ending up in your version control system.&lt;/p&gt;

&lt;p&gt;If you are using any other framework than Next.js you need to use a package like &lt;a href="https://www.npmjs.com/package/dotenv"&gt;dotenv&lt;/a&gt; to read the environment variables from a file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now to the bread and butter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;config.ts&lt;/code&gt; file with this code to read the environment variables into your config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getEnvironmentVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environmentVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&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;unvalidatedEnvironmentVariable&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;environmentVariable&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;unvalidatedEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`Couldn't find environment variable: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;environmentVariable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;unvalidatedEnvironmentVariable&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;API_KEY&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;And change code that we wrote earlier into this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;config&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="s2"&gt;./config&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://www.example.com/api/blog?api_key=&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;apiKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why this is the correct way to load environment variables
&lt;/h2&gt;

&lt;p&gt;In a case where you forgot to add the environment variable &lt;code&gt;API_KEY&lt;/code&gt; the application won't even build/compile, and it will throw an error like this: &lt;code&gt;Couldn't find environment variable: API_KEY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our application now fails immediately and visibly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is called &lt;em&gt;failing fast&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It is part of the clean code principles, which you can read more about here: &lt;a href="https://www.martinfowler.com/ieeeSoftware/failFast.pdf"&gt;https://www.martinfowler.com/ieeeSoftware/failFast.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because we are using TypeScript, we can be 100% sure that all the values in the config exist.&lt;/p&gt;

&lt;p&gt;Additionally, TypeScript helps us avoid small bugs.&lt;/p&gt;

&lt;p&gt;If we make a typo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://www.example.com/api/blog?api_key=&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;apiKeu&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TypeScript will give us the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property 'apiKeu' does not exist on type '{ apiKey: string; }'. Did you mean 'apiKey'?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How cool is that!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's like coding with superpowers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encapsulating logic
&lt;/h2&gt;

&lt;p&gt;Let's look at the example we started with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://www.example.com/api/blog?api_key=&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;API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you notice that &lt;code&gt;process.env&lt;/code&gt; part there?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why should the functionality of fetching blog posts know anything about the user environment the application is currently running in?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well it shouldn't.&lt;/p&gt;

&lt;p&gt;The logic of fetching blog posts doesn't care where it gets the api key from. If it comes from the user environment, text file, or an API doesn't make any difference to it.&lt;/p&gt;

&lt;p&gt;Therefore, it shouldn't rely on &lt;code&gt;process.env&lt;/code&gt; or any other low-level abstractions.&lt;/p&gt;

&lt;p&gt;Creating a config for the sole purpose of reading environment variables encapsulates this functionality and creates a meaningful high-level abstraction.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A config&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to this, we can change the way we get the config values (like the api key) without touching the blog post functionality at all!&lt;/p&gt;

&lt;p&gt;Another very hidden benefit is that unit testing just became ten times easier. Instead of playing around with our user environment, we can just mock the config with the values we want to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While this might seem pedantic, keeping these small things in your mind while writing code will make you a better software engineer.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Before Building a Website You Need to Design a Sitemap [Here's why]</title>
      <dc:creator>Austin Shelby</dc:creator>
      <pubDate>Mon, 06 Sep 2021 11:01:45 +0000</pubDate>
      <link>https://forem.com/austinshelby/before-building-a-website-you-need-to-design-a-sitemap-here-s-why-5aij</link>
      <guid>https://forem.com/austinshelby/before-building-a-website-you-need-to-design-a-sitemap-here-s-why-5aij</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Give me six hours to chop down a tree and I will spend the first four sharpening the axe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;- Abraham Lincoln&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are struggling to start building your website this blog post will help you develop a plan that will get you started.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We are going to be designing a sitemap for your website using a easy-to-use visual tool.&lt;/p&gt;

&lt;p&gt;To learn all the necessary techniques we are going to break down Product Hunt's website and see how they have designed their sitemap.&lt;/p&gt;

&lt;p&gt;Once you have made a plan for your website's structure, building it will become easy and straightforward.&lt;/p&gt;




&lt;h2&gt;
  
  
  Analyzing Product Hunt's sitemap
&lt;/h2&gt;

&lt;p&gt;If you haven't heard, Product Hunt is a massively popular website where founders can post their SaaS products and get feedback on them.&lt;/p&gt;

&lt;p&gt;I took the time and crawled their website to reverse engineer how they have built their website's page hierarchy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O1RpGCK---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hef1ni06ahs0lg3ono1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O1RpGCK---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hef1ni06ahs0lg3ono1j.png" alt="Website sitemap design"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By breaking down their sitemap we are going to learn the techniques they use to rank high for competitive keywords, get massive amounts of users, and create tons of engagement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At the end of this article I'm going to give you the exact checklist you can apply to your own website.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Identify main content on your website
&lt;/h2&gt;

&lt;p&gt;People visit Product Hunt to discover and share the latest products.&lt;/p&gt;

&lt;p&gt;These product posts are the bread and butter of their website and why they are so popular. They are the most essential content and everything else on the website should only exists to emphasize their importance and discoverability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8YJ12-zt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2w251yu4oyl4157rdelh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8YJ12-zt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2w251yu4oyl4157rdelh.png" alt="Sitemap main content"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the diagram the Post objects have the most lines leading into it.&lt;/p&gt;

&lt;p&gt;This means that it's being linked into from many different places.&lt;/p&gt;

&lt;p&gt;This helps people to discover new posts wherever they are in the website.&lt;/p&gt;

&lt;p&gt;These products posts are user generated content but in your case the content might be created by yourself.&lt;/p&gt;

&lt;p&gt;For AirBnb it's apartments.&lt;/p&gt;

&lt;p&gt;For YouTube it's videos.&lt;/p&gt;

&lt;p&gt;For Twitch it's live streams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create list pages
&lt;/h2&gt;

&lt;p&gt;Now that you have figured out what content your users are most likely wanting to find on your website, &lt;strong&gt;it is your job to make it as easy as possible for them to find it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You want to create pages where you can list the content.&lt;/p&gt;

&lt;p&gt;Let's look at how Product Hunt does it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E2O4OP3K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u429fjhalh2eqcqoj5i0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E2O4OP3K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u429fjhalh2eqcqoj5i0.png" alt="List pages"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They have multiple different Topic pages where they can list the appropriate posts.&lt;/p&gt;

&lt;p&gt;You can also find posts on user profiles. Either submitted by the user or in their collection.&lt;/p&gt;

&lt;p&gt;Posts in collections can be from other people too. This will create a lot of engagement as you will have multiple different ways to interact with other people's posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build ultra specific pages
&lt;/h2&gt;

&lt;p&gt;Ultra specific list pages are exactly what they sound like.&lt;/p&gt;

&lt;p&gt;They are used to group similar items together in categories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating separate pages for each category helps your users to find what they want effortlessly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lkeiuXwK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uzd8in5xh3u1ouavum1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lkeiuXwK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uzd8in5xh3u1ouavum1y.png" alt="Ultra specific pages"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Product Hunt's case they have pages like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Productivity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tech&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Analytics&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internet of Things&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artificial Intelligence&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Writing Tools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Virtual Reality&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The great thing about this is that you don't have to create any new content. You can reuse your already existing content and just categorize them in new ways.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A lesser known benefit of this is that it helps you with search engine optimization. Using specific keywords as the title on these pages and listing related content makes this a super SEO strategy.&lt;/p&gt;

&lt;p&gt;This has allowed Product Hunt to rank for competitive keywords like &lt;em&gt;Touch Bar Apps 2021&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D8GEGvYE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tstv5r4m7ynwj5wp5c3d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D8GEGvYE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tstv5r4m7ynwj5wp5c3d.jpg" alt="Product Hunt Specific Keyword"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's look at some ways other websites categorize their content.&lt;/p&gt;

&lt;p&gt;Twitch.tv has categories for each of the games on the platform.&lt;/p&gt;

&lt;p&gt;AirBnb has category pages for each location in the world. That's a lot!&lt;/p&gt;

&lt;p&gt;If you have large amounts of content you can and should absolutely create these pages programmatically if possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use a secret Google tool to create a sitemap
&lt;/h2&gt;

&lt;p&gt;Now to make everything come together we are going to be using a secret Google tool that almost no one knows about.&lt;/p&gt;

&lt;p&gt;This tool is so rare that Google itself doesn't list it on their products page: &lt;a href="https://about.google/intl/en/products/"&gt;https://about.google/intl/en/products/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's called Drawings and you can use it to create all kinds of diagrams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you like the sitemap designs on this page you can download the &lt;a href="https://www.austinshelby.com/resources/free-website-sitemap-template"&gt;free website sitemap template here&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or alternatively you can make yours from scratch using the tool here: &lt;a href="https://docs.google.com/drawings"&gt;https://docs.google.com/drawings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On the top bar choose &lt;code&gt;Insert &amp;gt; Diagram&lt;/code&gt; and on the panel that opens on the left choose &lt;code&gt;Hierarchy&lt;/code&gt; and choose any style you want.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aLFWZZmV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wjt4pqosao66h8mofywo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aLFWZZmV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wjt4pqosao66h8mofywo.jpg" alt="Google drawings sitemap"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now that we have learned the techniques Product Hunt uses to organize their website and get massive traffic through SEO it's time for you to apply it on your website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a sitemap checklist:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Write down what is the most essential content on your website. It might not be so easy to find as these examples but make sure you get it right as it leads us to the next point.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Figure out how users can interact with the content on your website and where can you list the content most efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Look at your already existing content and write down 7 categories that you can fit them in. Search those categories on Google to see what kind of keywords pop up on the results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now that you know how to organize the pages on your website think about the other &lt;a href="https://www.austinshelby.com/blog/5-website-features-to-optimize-conversion"&gt;website features you should have on your website for it to be successful&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Google Drawings to create a sitemap for your website using my &lt;a href="https://www.austinshelby.com/resources/free-website-sitemap-template"&gt;free sitemap template&lt;/a&gt;. After you are done message me on twitter &lt;a href="https://twitter.com/theaustinshelby"&gt;https://twitter.com/theaustinshelby&lt;/a&gt; or send me an email and I will give you feedback on it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>architecture</category>
      <category>seo</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
