<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Livecycle</title>
    <description>The latest articles on DEV Community by Livecycle (@livecycle).</description>
    <link>https://dev.to/livecycle</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%2Forganization%2Fprofile_image%2F6511%2Fb7b80edd-2953-4dda-a9b2-90acf961448d.png</url>
      <title>DEV Community: Livecycle</title>
      <link>https://dev.to/livecycle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/livecycle"/>
    <language>en</language>
    <item>
      <title>How to collaborate better with your team on Localhost</title>
      <dc:creator>Pradumna Saraf</dc:creator>
      <pubDate>Wed, 07 Feb 2024 07:38:48 +0000</pubDate>
      <link>https://dev.to/livecycle/how-to-collaborate-better-with-your-team-on-localhost-45bo</link>
      <guid>https://dev.to/livecycle/how-to-collaborate-better-with-your-team-on-localhost-45bo</guid>
      <description>&lt;p&gt;Collaborating on localhost sounds unusual, doesn't it?&lt;/p&gt;

&lt;p&gt;Yes, it's not conventional because it's nearly impossible to collaborate with others when you're running something locally on localhost and they are not sitting next to you. By "collaborate" here, I mean that the other person may be able to check your work, visualize your changes, check the logs of the running app, access the terminal, execute commands, debug together, etc.&lt;/p&gt;

&lt;p&gt;And yes, we have tools and other methods, which do some of the things I mentioned above, like test environments, branching strategies, etc., for sharing our work with other teammates, but it takes time to go through these typical processes and can be a blocker when you need instant help and feedback. Also, many times replication of errors and bugs becomes quite difficult. Of course, it leads to a slower SDLC and review cycle. Also, it costs both time and money (the cost of running CI and deployment).&lt;/p&gt;

&lt;p&gt;We at &lt;a href="https://livecycle.io/" rel="noopener noreferrer"&gt;Livecycle&lt;/a&gt; are trying to solve this broken "Review Cycle". Every company and team face this issue, but no one is solving it and providing an end-to-end solution without creating any friction in the existing development cycle. This is why we built the &lt;a href="https://hub.docker.com/extensions/livecycle/docker-extension" rel="noopener noreferrer"&gt;Livecycle Docker Extension&lt;/a&gt; to achieve all the collaboration (and more) mentioned in the opening paragraph. The only thing you need before starting to use the extension is to have your application Dockerized and make your application compose-ready. Almost every team uses compose to dev, and in case you don't have it already, you can use &lt;code&gt;docker init&lt;/code&gt;. The reason for using Docker Compose under the hood for all these tunnelling and sharing is to ensure replication and, most importantly, not impact your actual application code or dependencies. This way, there's no need to modify your application to leverage this tool. &lt;/p&gt;

&lt;p&gt;Let's see how you use this: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installing the extension&lt;/strong&gt;: Navigate to this link or search for "Livecycle" in the Docker Desktop Extensions Marketplace. Click the "Install" button to install the extension.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1j1ykzmeoxpr081jpr9d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1j1ykzmeoxpr081jpr9d.png" alt="Docker Desktop Screen" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up a Livecycle account&lt;/strong&gt;: Once you have installed the extension and opened it, you will be greeted with a login screen. You can choose to log in with your GitHub account or Google account. If you previously used Livecycle and created an organization, you can log in with your Livecycle account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnamtl7ftdrnif7yj4xbj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnamtl7ftdrnif7yj4xbj.png" alt="Docker Desktop Screen" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting shareable URLs&lt;/strong&gt; As soon as you log in, you will be able to see a list of running docker compose applications and all the services that are running in them. To get a public shareable URL for every service, click on the "Share" button below the service name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcd48li1tb26cvxuauhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcd48li1tb26cvxuauhd.png" alt="Docker Desktop Screen" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can choose between Local and Cloud. The local option will create a tunnel to your local machine, and the cloud option will put your application into the cloud and create a tunnel to it. You can choose depending on your use case. For example, if you want the environment to stay for a small amount of time (this one is a good option for quick feedback), you can choose the local option. If you want the environment to stay for a longer time, and the team can access it over a few days, you can choose the cloud option.&lt;/p&gt;

&lt;p&gt;After that, you can choose public access, you will get a public URL that you can share with anyone. If you choose private access, you will get a private URL that requires authentication and can only be used by your organization members. Then click on the "Share" button to get the shareable URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0t19efnuqqlebqa176aj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0t19efnuqqlebqa176aj.png" alt="Docker Desktop Screen" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accessing the shared URL&lt;/strong&gt;: URLs created by the extension are consistent, shareable, and can be used by a browser or any other HTTP client. Using these URLs, your team members will be able to see and interact with your local version of the app as long as the tunnel is open and your workstation is running. Private environments require adding team members to your organization, and upon access, your team members will be prompted to authenticate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxrd9c1mjzr6ifj0p48y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxrd9c1mjzr6ifj0p48y.png" alt="Docker Desktop Screen" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accessing Livecycle dashboard&lt;/strong&gt;: You can also access the Livecycle dashboard to see the logs and debug your application. Click on the "Open Link" button to open the Livecycle dashboard. On the dashboard, you can see all the running applications and services. The Livecycle dashboard requires authentication and organization membership, similar to private environments/services&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3ed0ci61inakbe1v6r8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3ed0ci61inakbe1v6r8.png" alt="Docker Desktop Screen" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging, inspecting, and logging&lt;/strong&gt;: Once you have opened the Livecycle dashboard, you can see all the environments/apps that are running. Click on the environment name for which you want to see the logs, terminal, etc. You can view the logs, terminal, and container inspection for each service. Soon we will support on-screen comments for improve the feedback cycle. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmvyfcwmocnofdw9wxzu8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmvyfcwmocnofdw9wxzu8.png" alt="Docker Desktop Screen" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it! You have successfully installed the Livecycle Docker Extension and shared your local development environment with your team. Now you can easily share your work with anyone in the world with a single click of a button and &lt;/p&gt;

&lt;p&gt;And if you want to go through the cloud route, you can check out this blog:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/livecycle" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F6511%2Fb7b80edd-2953-4dda-a9b2-90acf961448d.png" alt="Livecycle" width="800" height="800"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F682769%2F6d44570c-3d95-4656-ba55-c8a4b0e95f9e.jpg" alt="" width="800" height="800"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/livecycle/feat-deploy-to-cloud-livecycle-docker-extension-3c88" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;feat: Deploy To Cloud - Livecycle Docker Extension&lt;/h2&gt;
      &lt;h3&gt;Pradumna Saraf for Livecycle ・ Jan 25 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#docker&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cloud&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#development&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Also, you can check out the video below for a step-by-step guide on how to get started with it.&lt;/p&gt;

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

&lt;p&gt;We also have detailed documentation and an FAQ section to clear all your doubts. In case you need any help or just want to have fun chat join our &lt;a href="https://community.livecycle.io/" rel="noopener noreferrer"&gt;Livecycle community&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>development</category>
      <category>productivity</category>
      <category>docker</category>
      <category>opensource</category>
    </item>
    <item>
      <title>feat: Deploy To Cloud - Livecycle Docker Extension</title>
      <dc:creator>Pradumna Saraf</dc:creator>
      <pubDate>Thu, 25 Jan 2024 13:11:12 +0000</pubDate>
      <link>https://dev.to/livecycle/feat-deploy-to-cloud-livecycle-docker-extension-3c88</link>
      <guid>https://dev.to/livecycle/feat-deploy-to-cloud-livecycle-docker-extension-3c88</guid>
      <description>&lt;p&gt;In our recent blog post, "In-Flight Collaboration With The Livecycle Docker Extension," we introduced Livecycle's newest tool, the Livecycle Docker Extension. This extension allows developers to instantly share local development environments, facilitating early collaboration and feedback in the software development lifecycle.&lt;/p&gt;

&lt;p&gt;It complements Livecycle's existing tools, offering multiple entry points into the development workflow. The key feature is enabling in-flight UI reviews and debugging, addressing challenges of delayed feedback. You can check out that blog &lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/livecycle" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F6511%2Fb7b80edd-2953-4dda-a9b2-90acf961448d.png" alt="Livecycle" width="800" height="800"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F682769%2F6d44570c-3d95-4656-ba55-c8a4b0e95f9e.jpg" alt="" width="800" height="800"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/livecycle/in-flight-collaboration-with-the-livecycle-docker-extension-o3e" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;In-Flight Collaboration With The Livecycle Docker Extension&lt;/h2&gt;
      &lt;h3&gt;Pradumna Saraf for Livecycle ・ Oct 4 '23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#docker&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#development&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#collaboration&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;In the past, when you shared your work using Livecycle Docker Extension, everything ran locally—your application, tunnel, and more. This meant that as long as your system was up and running, the people you shared the URL with could access your work. It was great for short-term reviews.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now, we're taking it to the next level. With our latest update "Deploy to Cloud"&lt;/strong&gt;, you can deploy your applications on the cloud—be it AWS, GCP, Azure, or Kubernetes. This means the sharing process isn't limited to your local setup anymore; you can have an environment running for longer with more stability for long-term review and feedback, all happening in the cloud.&lt;/p&gt;

&lt;p&gt;Let's see how you can use this amazing feature!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installing the extension&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Navigate to this &lt;a href="https://open.docker.com/extensions/marketplace?extensionId=livecycle/docker-extension" rel="noopener noreferrer"&gt;link&lt;/a&gt; or search for "Livecycle" in the Docker Desktop Extensions Marketplace. Click the "Install" button to install the extension.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1hyx3ezp4pw01rvtwa1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1hyx3ezp4pw01rvtwa1.png" alt="Livecycle Docker Extension" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up a Livecycle account&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you have installed the extension and opened it, you will be greeted with a login screen. You can choose to log in with your GitHub account or Google account. If you previously used Livecycle and created an organization, you can log in with your Livecycle account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22zhlyux1wfbk3fxxnld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22zhlyux1wfbk3fxxnld.png" alt="Livecycle Docker Extension" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Share to Cloud&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can either deploy a fresh new environment directly to the cloud or deploy the existing local shared one to the cloud.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Deploy a new shareable environment to the cloud&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As soon as you log in, you will see a list of running Docker Compose applications. Click on the "Share" button below the app name. Choose the cloud option. After that, you will be prompted to choose a cloud provider. You can choose between AWS, GCP, and Azure, or use Kubernetes if you have a Kubernetes cluster. Make sure you have the credentials for the chosen cloud provider setup in your local system, for Kubernetes, the kubeconfig file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxdej5fukn9wa25vxlij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxdej5fukn9wa25vxlij.png" alt="Livecycle Docker Extension" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will choose AWS as my cloud provider. As you can see, it asks for region, bundle ID, etc. You can leave the region as default or choose the region you want. Also, some columns are optional, so you can leave them blank. After that, click on the "Share" button to get the shareable URL. It will take some time to deploy and generate those URLs. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbm2sggwpmg7py4q42ena.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbm2sggwpmg7py4q42ena.png" alt="Livecycle Docker Extension" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can see the environment is deployed to AWS, and you can access it using the shareable URL. You can also see the environment in the Livecycle dashboard. To access it click on the "Open Link" button to open the dashboard. On the dashboard, you can see all the running applications and services. The Livecycle dashboard requires authentication and organization membership, similar to private environments/services &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevg16xcyc6y09y3659rj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevg16xcyc6y09y3659rj.png" alt="Livecycle Docker Extension" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Deploy an existing locally shared environment to the cloud&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can also deploy an existing local environment to the cloud. To do that, simply click on the three dots next to the environment name and click on the "Deploy" option. After that, you will be prompted to choose the cloud provider or if you don't get the prompt to choose the cloud provider, it will deploy to the provider you chose previously for the environment. In my case, I chose AWS previously, so it will deploy to AWS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsaekj8kvvksed84hid9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsaekj8kvvksed84hid9g.png" alt="Livecycle Docker Extension" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, a new environment will be created with the same name as the local environment. So, now you have two environments, one local and one cloud. To ensure the environment is deployed to the cloud, you can see the cloud icon next to the environment name. You can also see the environment in the Livecycle dashboard like we did above&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcix1omc51g0h3x3vsnf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcix1omc51g0h3x3vsnf.png" alt="Livecycle Docker Extension" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Certainly! Here's the corrected version:&lt;/p&gt;

&lt;p&gt;If you are experiencing any issues or wish to provide feedback, feel free to join the &lt;a href="https://community.livecycle.io" rel="noopener noreferrer"&gt;Livecycle Community&lt;/a&gt; on Slack. Additionally, please visit &lt;a href="https://livecycle.io/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=livecycle" rel="noopener noreferrer"&gt;livecycle.io&lt;/a&gt; to learn more about Livecycle and find more details.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>cloud</category>
      <category>development</category>
      <category>devops</category>
    </item>
    <item>
      <title>👀 Under the Hood at DevHunt 🚀</title>
      <dc:creator>Zevi Reinitz</dc:creator>
      <pubDate>Tue, 26 Dec 2023 07:36:33 +0000</pubDate>
      <link>https://dev.to/livecycle/under-the-hood-at-devhunt-94j</link>
      <guid>https://dev.to/livecycle/under-the-hood-at-devhunt-94j</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;The Challenge of Launching DevTools&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One of the unique challenges for any DevTools company is finding the right platforms for launching the product. &lt;/p&gt;

&lt;p&gt;There are many places to launch products in general, but DevTools by definition have a unique audience and that renders many of the standard launch platforms less relevant and less effective. &lt;/p&gt;

&lt;p&gt;That's why I was pleasantly surprised when I discovered DevHunt - a product launch platform built by developers for developers, focused solely on launching DevTools to a relevant audience. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiu6on5bquoep5ql8mifb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiu6on5bquoep5ql8mifb.gif" alt="suprised" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Launching Livecycle on DevHunt&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In my experience, the best way to learn about a new platform is to use it myself. And the second best way is to speak to the founders directly about what motivated them to build it in the first place.&lt;/p&gt;

&lt;p&gt;So this week, I'm checking both of these boxes at the same time:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Livecycle is Live on DevHunt this week (🚀🚀&lt;strong&gt;Shameless plug... &lt;a href="https://devhunt.org/tool/livecycle-docker-extension" rel="noopener noreferrer"&gt;please upvote Livecycle on DevHunt&lt;/a&gt;!!&lt;/strong&gt;🚀🚀)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I reached out to DevHunt founder John Rush to learn more about his career and his motivation for building a dev-centric product launch platform. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the first installment of a launch-in-public diary that I'll be sharing so that other dev tools companies can (hopefully) learn and benefit from our experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;My Conversation with DevHunt Founder John Rush&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How did you get started as a developer?
&lt;/h3&gt;

&lt;p&gt;I was building electronics since I was 5 years old and started coding when I was 12. I also studied computer science so I’m a typical coder who did it since he remembers himself.&lt;/p&gt;

&lt;h3&gt;
  
  
  You clearly have a lot of product ideas and you’ve built a bunch of them… How do you decide when an idea is good enough to actually build?
&lt;/h3&gt;

&lt;p&gt;I only build stuff I really wanna use myself, but can’t find anything on the market that suits my needs 100%.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does your early go-to-market process look like? How do you start promoting the product to developers and get those first 100 users?
&lt;/h3&gt;

&lt;p&gt;I use X a lot. Trying to make a viral tweet that’s not a promotion, but indirect promotion. I post on Hacker News, Hackernoon, Devto, Product Hunt, Dev Hunt and 100 more directories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why did you decide to build DevHunt? What makes it unique?
&lt;/h3&gt;

&lt;p&gt;Product Hunt is a closed company. They have no dialog with the maker community. This is unacceptable for such a platform. Everyone complains, including me. This leads to issues, often we see products cheating there. The last drop for me was when I got the #2 spot of the day because the top product was cheating with fake upvotes, it seemed obvious based on indirect metrics (such as upvote speed). That day I decided to make Dev Hunt and make it 100% open and transparent. The community loves it. We won PH product of the day and we have grown every week since the launch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can you give some tips on how developers can get the most out of a DevHunt product launch?
&lt;/h3&gt;

&lt;p&gt;Promote it on social media, direct messages to friends, blog posts and add the Dev Hunt banner on your site. If all 15 tools do that, it means we merge all audiences and actually cross-promote these products. On top of that, the generic Devhunt audience checks all the tools. So in total, these actions create great traffic.&lt;/p&gt;

&lt;p&gt;Beyond the initial launch, winning on DevHunt means you stay on the home page for years. This is so valuable for a brand and traffic, I can’t even describe it. Your tool is among the best tools in a short list visible all year long, every day to every visitor of DevHunt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can you share an epic failure you experienced as a developer? What did you learn from it?
&lt;/h3&gt;

&lt;p&gt;Every time I put too much effort and time into coding a product, it fails. There is one product we spent almost a year building and when we launched, we got 0 users, because users didn’t really need it. We closed down that company later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building and testing so many products requires a lot of positivity and optimism. How do you maintain a positive perspective even when things seem to be going wrong?
&lt;/h3&gt;

&lt;p&gt;I’m an optimist by nature. I think founders must be optimistic. If not, I’d rather not start a business, because almost everything I do fails, and almost every decision I make is wrong, but sometimes I’m right and sometimes my products are useful, these moments make me happy enough to go grind further forever.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tell us about a new project you're excited about or something new you're learning
&lt;/h3&gt;

&lt;p&gt;My goal for 2024 is to have 100 projects launched in total. I am at 20 now. So I need to launch 80 more. The one I’m working on right now is a tool to make websites/directories/CVs/roadmaps out of Google Sheet or Notion. Super simple. No advanced cms. Also I’m launching indexgoogle.com this week and listingbott.com next week.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the best piece of advice you’ve ever received?
&lt;/h3&gt;

&lt;p&gt;Kill your EGO&lt;/p&gt;

&lt;h3&gt;
  
  
  More About John Rush
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt;&lt;br&gt;
16 years in the startup world. 25 failures. 4 successes in VC funded startups. Pivoted into the bootstrapped indie world in 2023.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;20+ projects:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Marsx.dev&lt;/strong&gt;, &lt;strong&gt;Unicornplatform.com&lt;/strong&gt; website builder, &lt;strong&gt;Devhunt.org&lt;/strong&gt; Open Source PH alternative for dev tools, &lt;strong&gt;SeoBotAI.com&lt;/strong&gt; SEO on 100% autopilot, zero actions needed), &lt;strong&gt;Listingbott.com&lt;/strong&gt; lists a tool on up to 1000 directories with 1 click for traffic/backlinks, &lt;strong&gt;AllGPTs.co&lt;/strong&gt; most popular custom GPT directory in the world, &lt;strong&gt;filmgrail.com&lt;/strong&gt; cinema SaaS platform - powers cinemas on all continents, processing over $50M in ticket sales a year, &lt;strong&gt;lorem.space&lt;/strong&gt; image placeholder api, &lt;strong&gt;marketsy.ai **e-commerce and marketplaces powered by AI, **uigenerator.org&lt;/strong&gt; generate UI mockups for your website, &lt;strong&gt;cofondr.com&lt;/strong&gt; cofounder as a service for busy solo makers, &lt;strong&gt;indexgoogle.com&lt;/strong&gt; index your new pages really fast, in just hours, &lt;strong&gt;saasemailer.com&lt;/strong&gt; dead simple emailers/CRM for solo makers, &lt;strong&gt;nextjsstarter.com&lt;/strong&gt; directory of all NextJS starters and boilerplates, &lt;strong&gt;startupstools.com&lt;/strong&gt; startup tools used by famous makers, &lt;strong&gt;osssoftware.org&lt;/strong&gt; vetted OSS alternatives for the tool you pay for, &lt;strong&gt;My newsletter &amp;gt;&amp;gt;&amp;gt; &lt;a href="https://100xfounder.beehiiv.com/" rel="noopener noreferrer"&gt;100xfounder.beehiiv.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>marketing</category>
      <category>tooling</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to Get Preview Environments for Every Pull Request</title>
      <dc:creator>Pradumna Saraf</dc:creator>
      <pubDate>Wed, 13 Dec 2023 08:34:45 +0000</pubDate>
      <link>https://dev.to/livecycle/how-to-get-preview-environments-for-every-pull-request-3fg0</link>
      <guid>https://dev.to/livecycle/how-to-get-preview-environments-for-every-pull-request-3fg0</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;TL;DR&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this article you’ll learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What preview environments are and how they can help you&lt;/li&gt;
&lt;li&gt;How to easily set up preview environments &lt;/li&gt;
&lt;li&gt;How to add this capability to your CI pipeline and get automatically produced environments for every pull request&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is an ephemeral preview environment?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ephemeral preview environments are production-like environments that are created per commit so that the branch in question can be easily reviewed and tested before it gets merged.&lt;/p&gt;

&lt;p&gt;Preview environments enable dev teams to shift the review process to “pre-merge” where it’s easier to identify bugs and avoid the single staging-server roadblock. They give you the ability to “preview” the code changes present in a pull request BEFORE you merge it to master, which is why it’s called “preview environment” or “deploy preview”. Some people prefer to call it an “ephemeral environment” because unlike production environments, it is ephemeral and temporary by design.&lt;/p&gt;

&lt;p&gt;You can think of a preview environment as a feature-specific version of the staging or production environment, giving teams the ability to see changes in “live” mode before merging to production. This is a powerful capability that carries many potential benefits.&lt;/p&gt;

&lt;p&gt;And with the right tooling, preview environments can be set up to be generated automatically for every pull request, so review cycles can gt started automatically without DevOps backlogs and other human delays.&lt;/p&gt;

&lt;p&gt;Sound too good to be true?&lt;/p&gt;

&lt;p&gt;It’s not.&lt;/p&gt;

&lt;p&gt;And in this article, we’ll show you how you can use Livecycle’s open source tool “Preevy” to easily add preview environments to your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;An easy way to create preview environments&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Preevy is a CLI Tool built by &lt;a href="https://livecycle.io/" rel="noopener noreferrer"&gt;Livecycle&lt;/a&gt; that is designed to easily provision, manage, and expose ephemeral environments for containerized applications in the cloud.&lt;/p&gt;

&lt;p&gt;These environments are inexpensive, easy to integrate, customizable, and accessible for both technical and non-technical users.&lt;/p&gt;

&lt;p&gt;It’s simple, flexible, and doesn’t require deep DevOps knowledge, making it ideal for adding preview environments to your “pull/merge request” flows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flivecycle.io%2F8aa0a8b86e4ac965bd9dc100dc0bd9d3%2Fterminal.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flivecycle.io%2F8aa0a8b86e4ac965bd9dc100dc0bd9d3%2Fterminal.gif" alt="terminal gif" width="600" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s walk through the steps of using Preevy to adding preview environments to your “pull/merge request” workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Preevy is designed to be easily run in CI/CD workflows, such as &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GH Actions&lt;/a&gt;, &lt;a href="https://circleci.com/" rel="noopener noreferrer"&gt;Circle CI&lt;/a&gt; and others.&lt;/p&gt;

&lt;p&gt;The most common use-case for a CI job that runs Preevy is to have a live preview environment for every Pull Request as part of the review process. This allows for &lt;a href="https://livecycle.io/blogs/preevy-preview-environments-for-everyone/" rel="noopener noreferrer"&gt;more collaborative and inclusive review workflows&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Walkthrough: Running Preevy in your GitHub actions CI&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;In this example, we'll use GitHub Actions CI and AWS Lightsail as a cloud provider.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For GitHub Actions with Google Cloud, see a complete recipe at the &lt;a href="https://github.com/livecycle/preevy-gha-gce-demo" rel="noopener noreferrer"&gt;&lt;code&gt;livecycle/preevy-gha-gce-demo&lt;/code&gt; repo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Install Preevy and create a profile&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Preevy &lt;a href="https://preevy.dev/intro/under-the-hood#profile-configuration" rel="noopener noreferrer"&gt;profile&lt;/a&gt; provides a mechanism for storing and sharing configuration and state between different machines.&lt;br&gt;
This allows sharing of environments between different CI jobs, or different developers.&lt;br&gt;
Using the same profile between different CI runs ensures a consistent configuration and allows for stable URLs for your preview environments.&lt;/p&gt;

&lt;p&gt;Preevy includes built-in support for saving profiles on &lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;AWS S3&lt;/a&gt; and &lt;a href="https://cloud.google.com/storage/" rel="noopener noreferrer"&gt;Google Cloud Storage&lt;/a&gt;.&lt;br&gt;
You can also store the profile on the local filesystem and copy it manually before running Preevy - we won't show this method here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To create the Preevy profile, first install the Preevy CLI locally:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# npm:&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; preevy
&lt;span class="c"&gt;# yarn:&lt;/span&gt;
yarn add &lt;span class="nt"&gt;-g&lt;/span&gt; preevy
&lt;span class="c"&gt;# or use npx to run the CLI without installing it:&lt;/span&gt;
npx preevy ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Then, set up a Preevy profile:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;preevy init &lt;span class="o"&gt;[&lt;/span&gt;profile-name]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;When asked to choose a &lt;strong&gt;cloud provider&lt;/strong&gt;, choose either &lt;code&gt;AWS Lightsail&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will be asked for the default AWS region in which to create AWS resources.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next, choose where to store your profile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The profile needs to be stored in the cloud where it can be accessed by your CI machines.&lt;/p&gt;

&lt;p&gt;When asked where to &lt;strong&gt;store&lt;/strong&gt; the profile, choose &lt;code&gt;AWS S3&lt;/code&gt;.&lt;br&gt;
The URL displayed in your terminal should look something like &lt;code&gt;s3://preevy-12345678-my-profile?region=eu-west-1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uo82ed5rksdti9ns6w4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uo82ed5rksdti9ns6w4.png" alt="gif screenshot" width="800" height="159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Note the URL displayed in your terminal - this is the Preevy profile URL which we'll use in the actions below.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Make sure GitHub Actions workflows have AWS permissions&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this example, we'll be using the &lt;a href="https://github.com/aws-actions/configure-aws-credentials" rel="noopener noreferrer"&gt;&lt;code&gt;aws-actions/configure-aws-credentials&lt;/code&gt; action&lt;/a&gt; with GitHub's &lt;a href="https://github.com/aws-actions/configure-aws-credentials#oidc" rel="noopener noreferrer"&gt;OIDC provider&lt;/a&gt;.&lt;br&gt;
Make sure the configured role has the &lt;a href="https://preevy.dev/deploy-runtimes/aws-lightsail#required-aws-permissions" rel="noopener noreferrer"&gt;required permissions&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Create your GitHub Actions workflows&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We'll create two workflows:&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Deploy Preevy environment&lt;/code&gt; workflow will create the preview environments when a PR is opened or updated.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Teardown Preevy environment&lt;/code&gt; workflow will bring down the running preview environments when the PR is closed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the &lt;code&gt;Deploy Preevy environment&lt;/code&gt; workflow, create the file &lt;code&gt;preevy-up.yaml&lt;/code&gt; in the &lt;code&gt;.github/workflows&lt;/code&gt; directory of your repo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Preevy environment&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;opened&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;reopened&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;synchronize&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;

  &lt;span class="c1"&gt;# Needed to write a PR comment with the environment URLs&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;timeout-minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;

    &lt;span class="c1"&gt;# allow a single job to run per PR&lt;/span&gt;
    &lt;span class="na"&gt;concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;preevy-${{ github.event.number }}&lt;/span&gt;

    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;arn:aws:iam::12345678:role/my-role&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;eu-west-1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;livecycle/preevy-up-action@v2.0.0&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;preevy&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;profile-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;vars.PREEVY_PROFILE_URL&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
          &lt;span class="na"&gt;docker-compose-yaml-paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./docker/docker-compose.yaml"&lt;/span&gt;

      &lt;span class="c1"&gt;# Change `frontend` and `3000` in this step to your main service and port&lt;/span&gt;
      &lt;span class="c1"&gt;# This will appear as the GH environment URL&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;store_url&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Store URL of frontend&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;echo url=$(jq -r '.[] | select(.service=="frontend" and .port==3000).url' "${{ steps.preevy_up.outputs.urls-file }}") &amp;gt;&amp;gt; "$GITHUB_OUTPUT"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;For the &lt;code&gt;Teardown Preevy environment&lt;/code&gt; workflow, create the file &lt;code&gt;preevy-down.yaml&lt;/code&gt; in the &lt;code&gt;.github/workflows&lt;/code&gt; directory of your repo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Teardown Preevy environment&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;closed&lt;/span&gt;
&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;

  &lt;span class="c1"&gt;# needed to update the PR comment with the environment URLs&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;teardown&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;arn:aws:iam::12345678:role/my-role&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;eu-west-1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;livecycle/preevy-down-action@v1.1.0&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;preevy&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;profile-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;vars.PREEVY_PROFILE_URL&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
          &lt;span class="na"&gt;docker-compose-yaml-paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./docker/docker-compose.yaml"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add a &lt;a href="https://docs.github.com/en/actions/learn-github-actions/variables#defining-configuration-variables-for-multiple-workflows" rel="noopener noreferrer"&gt;GitHub action configuration variable&lt;/a&gt; named &lt;code&gt;PREEVY_PROFILE_URL&lt;/code&gt; and set the value to the URL printed at the &lt;code&gt;preevy init&lt;/code&gt; output.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Get Automatic GitHub Notifications&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You're all set! When you open a PR, Preevy will now build preview environments.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://preevy.dev/github-plugin" rel="noopener noreferrer"&gt;Preevy Github Plugin&lt;/a&gt; will automatically detect the GitHub context and post a comment on your PR with the links to each of the relevant services when they are available for review.&lt;br&gt;
Teammates can simply click these links and preview your latest changes in their browser.&lt;/p&gt;

&lt;p&gt;Learn more about Livecycle &lt;a href="https://livecycle.io/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=livecycle" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to star the Preevy repo &lt;a href="https://github.com/livecycle/preevy" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>devops</category>
      <category>github</category>
      <category>programming</category>
    </item>
    <item>
      <title>Speed Up Hackathon Collaboration 🏃🤝</title>
      <dc:creator>Zevi Reinitz</dc:creator>
      <pubDate>Sun, 12 Nov 2023 12:11:21 +0000</pubDate>
      <link>https://dev.to/livecycle/speed-up-hackathon-collaboration-2c1e</link>
      <guid>https://dev.to/livecycle/speed-up-hackathon-collaboration-2c1e</guid>
      <description>&lt;h2&gt;
  
  
  The 2023 Docker AI/ML Hackathon
&lt;/h2&gt;

&lt;p&gt;Docker recently completed their &lt;a href="http://docker.devpost.com/" rel="noopener noreferrer"&gt;AI/ML Hackathon&lt;/a&gt;. Participants were encouraged to build solutions that are innovative, applicable in real life, use Docker technology, and have an impact on developer productivity. &lt;/p&gt;

&lt;p&gt;Eligible submissions could also include non-code proof-of-concepts, &lt;a href="https://www.docker.com/products/extensions/" rel="noopener noreferrer"&gt;extensions&lt;/a&gt; that improve Docker workflows, or integrations to improve existing &lt;a href="https://www.docker.com/blog/tag/artificial-intelligence-machine-learning/" rel="noopener noreferrer"&gt;AI/ML solutions&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;All submissions were AI/ML projects or models built using Docker technology and distributed through DockerHub, AI/ML integrations into Docker products that improve the developer experience, or extensions of Docker products that make working with AI/ML more productive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizing Hackathon Speed and Productivity
&lt;/h2&gt;

&lt;p&gt;Most hackathons begin and end with a simple directive - participants build something and submit it before the deadline. &lt;/p&gt;

&lt;p&gt;But in this year's AI/ML Hackathon, Docker took things a step further. Participants were treated to a wide range of sessions focusing on helping participants build higher-quality products. &lt;/p&gt;

&lt;p&gt;And in this context, we were thrilled that Docker asked us to present our &lt;a href="https://hub.docker.com/extensions/livecycle/docker-extension" rel="noopener noreferrer"&gt;Livecycle Docker Extension&lt;/a&gt; as a tool that Hackathon participants can use to achieve a blazing-fast collaborative experience. Instead of getting held back by staging servers and CI builds, the Livecycle extension lets teams share the latest changes with one another instantly, while code is still sitting on your local development environment. And with the built-in collaboration tools, Hackathon Squads can save tons of time building great products with the Livecycle extension.&lt;/p&gt;

&lt;p&gt;Check out the complete session (given by our CTO &lt;a class="mentioned-user" href="https://dev.to/yshayy"&gt;@yshayy&lt;/a&gt;) on how to use the Livecycle extension for Hackathon collaboration:&lt;/p&gt;

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

&lt;p&gt;And check out the Livecycle Extension &lt;a href="https://hub.docker.com/extensions/livecycle/docker-extension" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>hackathon</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Anti-FAQs: Use localhost for collaboration?? Seriously?!</title>
      <dc:creator>Zevi Reinitz</dc:creator>
      <pubDate>Wed, 25 Oct 2023 09:43:13 +0000</pubDate>
      <link>https://dev.to/livecycle/anti-faqs-use-localhost-for-collaboration-seriously-39pm</link>
      <guid>https://dev.to/livecycle/anti-faqs-use-localhost-for-collaboration-seriously-39pm</guid>
      <description>&lt;h2&gt;
  
  
  What exactly are “Anti-FAQs”?
&lt;/h2&gt;

&lt;p&gt;Regular FAQs are everywhere. &lt;/p&gt;

&lt;p&gt;As the name suggests, it’s a convenient format for answering some of the standard questions asked regarding any product or service. The assumption behind these questions is that the questioner is actually interested in the product (or at least the product premise), and they are just trying to clarify some details before deciding to move forward with it.&lt;/p&gt;

&lt;p&gt;In this regard, “Anti-FAQs” are the complete opposite.&lt;/p&gt;

&lt;p&gt;This is what I like to call the cynical, skeptical questions that people ask (often rhetorically) to justify why they’re NOT interested in using the product.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpm2g5ulgg4ndwgai77d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpm2g5ulgg4ndwgai77d.gif" alt="negative" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I like to focus on the Anti-FAQs because they are usually the juicer, more interesting discussion points. And ironically, once these items are actually clarified, the skeptics can be converted to become raving fans of the product they now better understand and appreciate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Anti-FAQs of localhost sharing
&lt;/h2&gt;

&lt;p&gt;We’ve currently been thinking about several Anti-FAQs regarding a new &lt;a href="https://open.docker.com/extensions/marketplace?extensionId=livecycle/docker-extension" rel="noopener noreferrer"&gt;Docker Extension&lt;/a&gt; we just launched.&lt;/p&gt;

&lt;p&gt;The extension enables developers to to instantly share local containers with anyone, without the need for staging environments or CI builds. And we’ve included built-in collaboration tools that give technical teammates access for remote debugging and less-technical teammates the ability to leave review feedback in context, while the code is still hot off the press, on the developer’s machine.&lt;/p&gt;

&lt;p&gt;It’s an amazing way for developers to continue to “shift-left” and bring critical review cycles to earlier stages of the development workflow, saving everyone time, headache, and money.&lt;/p&gt;

&lt;p&gt;It’s a cause that &lt;a href="https://livecycle.io/blogs/dockercon-2023/" rel="noopener noreferrer"&gt;Docker themselves are championing&lt;/a&gt; as recently as this year’s DockerCon, rolling out a series of native tools and features that expand the boundaries of developer collaboration.&lt;/p&gt;

&lt;p&gt;But, pushing boundaries brings healthy skepticism. So we wanted to take the opportunity to address some of those “Anti-FAQs” you might be asking yourself about the prospect of sharing your localhost and using it to collaborate with your team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isn’t Ngrok already doing the same thing?
&lt;/h2&gt;

&lt;p&gt;Not really. Ngrok (and others like it) are great ingress-as-a-service platforms, but the Livecycle extension takes localhost sharing even further.&lt;/p&gt;

&lt;p&gt;Here are some important points to keep in mind:&lt;/p&gt;

&lt;p&gt;First and foremost - the Livecycle Docker Extension is integrated with Docker, and provides a smoother experience for Docker users. Consistent URLs, private environments, organizations and Google/Github authentication are supported out of the box. &lt;/p&gt;

&lt;p&gt;Furthermore, in order to facilitate the collaborative workflows that developers need, it’s not enough to just share the local environment. A complete workflow solution also needs to get the team’s feedback back to the developer in an effective way. Sharing work without facilitating feedback doesn’t really help get the job done.&lt;/p&gt;

&lt;p&gt;That’s why our shared environments include built-in collaboration tools that enable technical teammates access for remote debugging, and less-technical teammates the ability to leave review feedback in context, while the code is still sitting on the developer’s machine.&lt;/p&gt;

&lt;p&gt;The Livecycle dashboard provides debugging capabilities that include log inspection, shell access, and container inspection. &lt;/p&gt;

&lt;p&gt;This ability to both share &lt;em&gt;and&lt;/em&gt; collaborate is a powerful differentiator that sets Livecycle apart from other infrastructure-focused solutions. &lt;/p&gt;

&lt;p&gt;Here are two common use cases to illustrate this:&lt;/p&gt;

&lt;h4&gt;
  
  
  In-progress UI Reviews
&lt;/h4&gt;

&lt;p&gt;One of the most common use cases for the Livecycle extension is enabling collaboration between developers and non-technical stakeholders early in the workflow. Using the Livecycle extension, you can get instant feedback on the latest front-end changes you’re working on your machine.&lt;/p&gt;

&lt;p&gt;By simply opening a tunnel and creating a shareable URL, you enable anyone on the team to use a browser to securely access the relevant services.&lt;/p&gt;

&lt;p&gt;So designers, QA, marketing and management can all see the application and use built-in commenting and collaboration tools to leave clear, actionable feedback. And since everything is in context, you’ll be able to communicate quickly and fix issues MUCH earlier in the development lifecycle.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  In-progress debugging
&lt;/h4&gt;

&lt;p&gt;Another common use case is enabling developers to work together to review and debug code changes as soon as possible.&lt;/p&gt;

&lt;p&gt;With the Livecycle extension, you can instantly share any front end or back end service running on your machine.&lt;/p&gt;

&lt;p&gt;By simply opening a tunnel and creating a shareable URL, you enable your team to use their browsers to securely access these services.&lt;/p&gt;

&lt;p&gt;Your teammates can now see real-time logging, catch errors and execute commands in a terminal, so you can collaboratively fix issues MUCH earlier in the development lifecycle.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Self-hosted ephemeral environments
&lt;/h4&gt;

&lt;p&gt;And in addition to all this, Livecycle doesn’t stop with just sharing localhost. Developers can also provision self-hosted ephemeral environments in the cloud provider of their choice to maintain the current state for longer review sessions that continue even when the developers local computer is offline. &lt;/p&gt;

&lt;p&gt;We’ll talk more about this in the following question.&lt;/p&gt;

&lt;h2&gt;
  
  
  At some point, that developer needs to close their computer. What happens then??
&lt;/h2&gt;

&lt;p&gt;It’s true. Developers are people too. And sometimes even they need to close the computer and go home for the evening. &lt;/p&gt;

&lt;p&gt;Thankfully, using Livecycle, this doesn’t need to mean the end of the review cycle. &lt;/p&gt;

&lt;p&gt;Because in addition to securely sharing localhost, developers can use Livecycle to provision self-hosted ephemeral environments in the cloud provider of their choice to maintain the current state for longer review sessions that continue even when the developer's local computer is offline. &lt;/p&gt;

&lt;p&gt;This is done using “Preevy” - our open source tool for quickly provisioning preview environments to any cloud or Kubernetes cluster. It works seamlessly with the Docker Extension to publish shareable environments on demand, or as an automated part of your CI workflow, per PR or commit.&lt;/p&gt;

&lt;p&gt;To learn more about how to use Preevy, just check out the &lt;a href="https://preevy.dev/" rel="noopener noreferrer"&gt;docs site&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Come on. There’s no way this kind of thing is secure.
&lt;/h2&gt;

&lt;p&gt;Sorry to disappoint you. But you’re wrong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxyuzd68wux2mwudifp5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxyuzd68wux2mwudifp5.gif" alt="wrong" width="320" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Livecycle Docker Extension uses a secure &lt;a href="https://livecycle.io/blogs/preevy-proxy-service-2/" rel="noopener noreferrer"&gt;SSH tunnel&lt;/a&gt; to expose your local development environment using Livecycle's tunnel server, which is only accessible using HTTPS. &lt;/p&gt;

&lt;p&gt;Furthermore, you can use the settings to enable private URLs to further control and restrict access to your environments.&lt;/p&gt;

&lt;p&gt;So security is not something you’ll need to worry about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Great. But this probably has limited support for the frameworks and languages I’m working with.
&lt;/h2&gt;

&lt;p&gt;Not so fast buddy… you’ll be happy to know that Livecycle is language and framework-agnostic. It works with anything that runs in a Docker container. And if you’re using Preevy to provision preview environments to the cloud, you can use any cloud back end or Kubernetes cluster to do so.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if I run into a problem? I’m sick of wasting my time talking to AI chatbots.
&lt;/h2&gt;

&lt;p&gt;Good news - we’re 100% human. We’re a team of experienced developers building tools that are impacting the way dev teams collaborate with each other. &lt;a href="https://community.livecycle.io/" rel="noopener noreferrer"&gt;Join our Slack channel&lt;/a&gt; to get updates, or get in touch with our team at any time and with any questions.&lt;/p&gt;

&lt;p&gt;We'd be thrilled to have you join the community and try our &lt;a href="https://hub.docker.com/extensions/livecycle/docker-extension" rel="noopener noreferrer"&gt;Docker Extension&lt;/a&gt; today.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>tooling</category>
      <category>devops</category>
    </item>
    <item>
      <title>Docker’s Recent Product Announcement is Bigger than You Realize</title>
      <dc:creator>Zevi Reinitz</dc:creator>
      <pubDate>Thu, 05 Oct 2023 14:04:09 +0000</pubDate>
      <link>https://dev.to/livecycle/dockers-recent-product-announcement-is-bigger-than-you-realize-32b6</link>
      <guid>https://dev.to/livecycle/dockers-recent-product-announcement-is-bigger-than-you-realize-32b6</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;TL;DR&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This post is part our ongoing series of Docker insights, announcements and &lt;a href="https://open.docker.com/extensions/marketplace?extensionId=livecycle/docker-extension" rel="noopener noreferrer"&gt;launches&lt;/a&gt; in celebration of DockerCon 2023 and in appreciation for everything that Docker has done for the developer community at large.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Docker's Recent Product Announcements&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Docker has already &lt;a href="https://www.docker.com/press-release/announces-new-local-cloud-products-to-accelerate-delivery-of-secure-apps/" rel="noopener noreferrer"&gt;made a few announcements&lt;/a&gt; at this week’s &lt;a href="https://www.dockercon.com/" rel="noopener noreferrer"&gt;DockerCon&lt;/a&gt; 2023. Most notably, the launch of 3 new products that harness the power of local and cloud development environments, allowing developers to quickly, and securely build, share, and run any app, anywhere. &lt;/p&gt;

&lt;p&gt;And while this is newsworthy by any measure - it’s easy to overlook just how big of a deal this is for developers everywhere.&lt;/p&gt;

&lt;p&gt;First let’s appreciate the 3 new products that were announced during the conferences keynote address:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Docker Scout&lt;/strong&gt; - Today, the tools, processes, and people involved in the software supply chain require too much context switching for developers. Feedback is often late and unclear, leaving developers to wonder how they can improve software quality. Complementing Docker’s existing trusted content, build automation and SBOM tools, Docker Scout adds relevant insights, policy evaluation, and contextual remediation, all while meeting developers where they are via integrations with Sysdig, JFrog Artifactory, AWS ECR, BastionZero, GitHub, GitLab, CircleCI, and Jenkins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Build&lt;/strong&gt; - Dev teams can waste as much as an hour per day per team member (!) waiting for their image builds to finish. To address this, next-generation Docker Build speeds up builds by as much as 39 times (!) by automatically taking advantage of large, on-demand cloud-based servers and team-wide build caching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Debug&lt;/strong&gt; - Developers spend as much as 60% of their time debugging their applications. But much of that time is spent sorting and configuring tools and set-up instead of actual debugging. Docker Debug provides a language-independent, integrated toolbox for debugging local and remote containerized apps, enabling developers to find and solve problems faster.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvovff6j8bdjmdzr8bc0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvovff6j8bdjmdzr8bc0b.png" alt="DC" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Improving the “here and now” developer experience&lt;/strong&gt; 
&lt;/h2&gt;

&lt;p&gt;With these products, Docker is clearly making “shift-left” the new standard in developer experience. Each of these new tools aims to achieve a singular goal for developers everywhere: combine the responsiveness and convenience of local development with the on-demand resources, connectedness, and collaboration possibilities of the cloud. This combination enables developers to do their best work much earlier in the SDLC than they ever imagined possible.&lt;/p&gt;

&lt;p&gt;Not surprisingly, Docker CEO Scott Johnston said it best: “The cloud offers many potential benefits for development teams, but most ‘inner-loop’ solutions require a complete change in tools and workflows — and very few developers want to ship their entire laptop to the cloud. The new products we announced today meet development teams where they are with ‘just enough cloud,’ seamlessly blurring the boundaries between local and remote development. In doing so, we’re enabling these teams to accelerate their delivery of secure applications critical to their businesses.”&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1709599547058532800-377" src="https://platform.twitter.com/embed/Tweet.html?id=1709599547058532800"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1709599547058532800-377');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1709599547058532800&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;&lt;a href="https://techcrunch.com/author/frederic-lardinois/" rel="noopener noreferrer"&gt;Frederic Lardinois&lt;/a&gt; from TechCrunch &lt;a href="https://techcrunch.com/2023/10/04/docker-launches-remote-container-builds-new-debugging-tools-and-more/" rel="noopener noreferrer"&gt;further quoted&lt;/a&gt; Johnston that in the early days of the container revolution, apps typically didn’t consist of more than a handful of containers. Now, those apps are often made up of 20 or 30 containers and that puts a lot of pressure on your typical developer laptop. “Moreover, when they’re working on an app locally, it’s hard to share a running app with your colleagues,” Johnston added. “And if that app you’re working on locally is dependent on some remote service, like a database as a service in the cloud or an AI service, it’s kind of hard, especially with security and such up your grill if you’re working in a large environment.”&lt;/p&gt;

&lt;p&gt;Some companies have tried to get around this by moving the entire development process into the cloud by offering developers cloud-based IDEs, for example. But Johnston argues that this isn’t something that every company is going to be comfortable with. He also said that what Docker is hearing from its customers is that this breaks existing workflows. “Because of where we are on the local laptop, where Docker Desktop sits, we see a unique opportunity to not make it either/or — not local or cloud — but local and cloud and bring the best of both worlds together.”&lt;/p&gt;

&lt;p&gt;Put simply, Docker’s new tools are built to combine the power of local and cloud to make the ‘here and now’ developer experience as effective and efficient as possible.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;But Wait… There’s More…&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Perhaps the most amazing thing about Docker’s announcement is the part that they didn’t say explicitly. &lt;/p&gt;

&lt;p&gt;Docker users around the world are quickly realizing that these products were not launched in a vacuum. They represent an extension to the existing suite of Docker products, such as Docker Desktop, Private Repos, and Docker Hub - a marketplace for discovering and distributing trusted dev-centric content and tools. &lt;/p&gt;

&lt;p&gt;Docker is launching these new products as the newest additions to their already robust platform. And this platform, in turn, enables other developers and devtools companies throughout the ecosystem to join Dockers Shift-Left call to action and extend these capabilities even further with complementary tools and contributions of their own.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Livecycle + Docker = Extended Dev Collaboration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A perfect example of Docker’s platform in action is what’s currently happening here at Livecycle. Like Docker, our mission is to enable developer collaboration by bringing other stakeholders into the developers’ immediate context in an effective an unintrusive way.&lt;/p&gt;

&lt;p&gt;We have built tools that allow developers to share their work at any point in the workflow and get clear, actionable feedback in context so it can be addressed easily.&lt;/p&gt;

&lt;p&gt;Historically, many developers have preferred to facilitate this type of collaboration with ephemeral preview environments that are triggered with every PR or commit. And indeed, we have built robust solutions like &lt;a href="https://github.com/livecycle/preevy" rel="noopener noreferrer"&gt;“Preevy&lt;/a&gt;” to facilitate the creation of these environments for dockerized applications on any cloud or Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;The magic of these environments is not just in the creation and sharing of the preview itself, but also in our built-in collaboration tools that enable all stakeholders to join the review process immediately and leave feedback in a shared context that is dev-centric and dev-friendly.&lt;/p&gt;

&lt;p&gt;And now, in line with Docker’s strategic vision, we’ve extended this capability left-wards with the launch of our new &lt;a href="https://open.docker.com/extensions/marketplace?extensionId=livecycle/docker-extension" rel="noopener noreferrer"&gt;Docker Extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’ve leveraged the power of the Docker Extensions Marketplace to build a tool that enables developers to instantly share local containers with anyone, without the need for staging environments or CI builds. &lt;/p&gt;

&lt;p&gt;And our built-in collaboration tools enable technical teammates access for remote debugging and less technical teammates the ability to leave review feedback in context, while the code is still sitting on the developer’s machine. &lt;/p&gt;

&lt;p&gt;These local ENVs can also be provisioned to the cloud as self-hosted preview environments, giving developers the local + cloud flexibility and accessibility they have been so clearly asking for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3arfw2gl39x68z3866a7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3arfw2gl39x68z3866a7.png" alt="lc d" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;‘Docker Collaborate’ with Livecycle&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You could argue that Livecycle’s collaboration layer can also be called “Docker Collaborate” - a fourth contribution to the wider Docker community that is rolling out this week. &lt;/p&gt;

&lt;p&gt;Docker’s three native products focus on empowering the developers themselves, and Livecycle’s tools extend this to also empower the rest of the team to create a truly collaborative development experience.&lt;/p&gt;

&lt;p&gt;Focusing on both the developer's developer experience and the ability to include other stakeholders early in the process is the two-way street that is needed to deliver optimal development efficiency and productivity.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;In-Flight UI Reviews&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;One of the most common use cases for the new Livecycle extension is enabling collaboration between developers and non-technical stakeholders early in the workflow. Using the Livecycle extension, you can get instant feedback on the latest front-end changes you’re working on your machine. &lt;/p&gt;

&lt;p&gt;By simply opening a tunnel and creating a shareable URL, you enable anyone on the team to use a browser to securely access the relevant services.  &lt;/p&gt;

&lt;p&gt;So designers, QA, marketing and management can all see the application and use built-in commenting and collaboration tools to leave clear, actionable feedback. And since everything is in context, you’ll be able to communicate quickly and fix issues MUCH earlier in the development lifecycle.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;In-Flight Debugging&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Another common use case is enabling developers to work together to review and debug code changes as soon as possible. &lt;/p&gt;

&lt;p&gt;With the Livecycle extension, you can instantly share any front end or back end service running on your machine. &lt;/p&gt;

&lt;p&gt;By simply opening a tunnel and creating a shareable URL, you enable your team to use their browsers to securely access these services. &lt;/p&gt;

&lt;p&gt;Your teammates can now see real-time logging, catch errors and execute commands in a terminal, so you can collaboratively fix issues MUCH earlier in the development lifecycle.&lt;/p&gt;

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

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

&lt;p&gt;We'll conclude with the words of Larry Carvalho, Principal Consultant at RobustCloud who said this about Docker's latest product initiatives:  "Enhancing developer productivity has been the holy grail of the software industry for years, but many efforts to do so have severely underdelivered. By combining the power of the cloud with local development environments, these new offerings from Docker can potentially solve the festering pain points of software engineers. Delivering productivity improvements across the ‘inner loop’ accelerates the development lifecycle of next-generation innovative solutions.”&lt;/p&gt;

&lt;p&gt;We’re excited about the work that Docker is doing, and we're excited about how this mission dovetails with our mission at Livecycle to enable optimal developer productivity and a "shift-left" developer experience for the entire team.&lt;/p&gt;

&lt;p&gt;We invite you to &lt;a href="https://open.docker.com/extensions/marketplace?extensionId=livecycle/docker-extension" rel="noopener noreferrer"&gt;try the Livecycle Extension&lt;/a&gt;, and join &lt;a href="https://join.slack.com/t/livecyclecommunity/shared_invite/zt-22w8arcmu-dIs~ZN6ECC93murxXc4PAA" rel="noopener noreferrer"&gt;our Slack community&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>tooling</category>
      <category>fullstack</category>
      <category>webdev</category>
    </item>
    <item>
      <title>In-Flight Collaboration With The Livecycle Docker Extension</title>
      <dc:creator>Pradumna Saraf</dc:creator>
      <pubDate>Wed, 04 Oct 2023 12:05:33 +0000</pubDate>
      <link>https://dev.to/livecycle/in-flight-collaboration-with-the-livecycle-docker-extension-o3e</link>
      <guid>https://dev.to/livecycle/in-flight-collaboration-with-the-livecycle-docker-extension-o3e</guid>
      <description>&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We've launched our new &lt;a href="https://open.docker.com/extensions/marketplace?extensionId=livecycle/docker-extension" rel="noopener noreferrer"&gt;Docker Extension&lt;/a&gt;! Developers use it to share local dev environments and get feedback MUCH earlier in the SDLC. We invite you to use it and benefit from it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We're also inviting everyone to join our &lt;a href="https://community.livecycle.io/" rel="noopener noreferrer"&gt;Slack community&lt;/a&gt; focused on developer collaboration, developer experience and anything needed to get started with Livecycle.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Software developers hate context switching
&lt;/h3&gt;

&lt;p&gt;For software developers, context switching is a buzzkill. And context switching into past tasks is even worse. Getting A DM from your PM that starts with “So, about the feature you worked on two weeks ago…” is never good news. &lt;/p&gt;

&lt;p&gt;It means not only pulling your head out of the code, and out of the flow - but also out of the present and into your past self - the person who designed “that feature”, built it, tested it and fixed it, and knew all about its countless, beautiful, intricate details. &lt;/p&gt;

&lt;p&gt;But that past self has been gone for two weeks now. So to deal with this issue, you’re going to have to find a way to conjure them up. And you can expect this to bring you extra work, because it’s becoming rapidly apparent that your two-weeks ago past self was a moron who couldn’t code properly, and couldn’t document to save their life, and they built embarrassingly broken stuff which the “present-you” has to fix right now.&lt;/p&gt;

&lt;h3&gt;
  
  
  There's gotta be a better way
&lt;/h3&gt;

&lt;p&gt;But what if I told you there’s a way to ensure that you get that message about the feature from two weeks ago… two weeks ago? &lt;/p&gt;

&lt;p&gt;What if your your past could get the feedback they need while they were still in context. This would allow your present self could keep their head in the code and in the current flow.&lt;/p&gt;

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

&lt;p&gt;Well, if this resonates with you, then you’ve come to the right place. Because here at Livecycle this is what we do best. &lt;/p&gt;

&lt;p&gt;We cut the feedback loop short by allowing you to share your work while you’re still in context. Using Livecycle, developers can share their work with whomever they want at any point in the SDLC and get instant feedback in context. This ensures that issues are raised, understood and addressed ASAP and not two weeks later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Livecycle's multiple workflow entry points
&lt;/h3&gt;

&lt;p&gt;Livecycle supports multiple entry points into your development workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our OSS CLI tool, &lt;a href="https://github.com/livecycle/preevy" rel="noopener noreferrer"&gt;Preevy&lt;/a&gt; provisions &lt;a href="https://livecycle.io/blogs/the-magic-of-ephemeral-preview-environments/" rel="noopener noreferrer"&gt;preview environments&lt;/a&gt; on your cloud provider or &lt;a href="https://livecycle.io/blogs/preevy-now-supports-kubernetes/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt; cluster&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/livecycle/preevy" rel="noopener noreferrer"&gt;Preevy&lt;/a&gt; also integrates into your &lt;a href="https://preevy.dev/ci/overview" rel="noopener noreferrer"&gt;CI pipeline&lt;/a&gt; to convert your pull requests into easily shareable ephemeral environments&lt;/li&gt;
&lt;li&gt;And now, our new Docker Desktop Extension allows you to do the same for your local development environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Share local dev environments instantly with the Docker Extension
&lt;/h3&gt;

&lt;p&gt;With the launch of the Livecycle Docker Extension, teams working on dockerized applications can shift the review process much farther left than ever before. Changes, bug fixes and new features can get reviewed instantly without the hassle of staging environments or CI builds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqke02joj9kptv8gkbdb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqke02joj9kptv8gkbdb.jpg" alt="Livecycle extension" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ability to share local dev environments instantly has many useful applications. Here are a few to illustrate the value it can bring to you and your team:&lt;/p&gt;

&lt;h4&gt;
  
  
  In-Flight UI Reviews
&lt;/h4&gt;

&lt;p&gt;One of the most common use cases is enabling collaboration between developers and non-technical stakeholders early in the workflow. Using the Livecycle extension, you can get instant feedback on the latest front-end changes you’re working on your machine.&lt;/p&gt;

&lt;p&gt;By simply opening a tunnel and creating a shareable URL, you enable anyone on the team to use a browser to securely access the relevant services.&lt;/p&gt;

&lt;p&gt;So designers, QA, marketing and management can all see the application and use built-in commenting and collaboration tools to leave clear, actionable feedback. And since everything is in context, you’ll be able to communicate quickly and fix issues MUCH earlier in the development lifecycle.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  In-Flight Debugging
&lt;/h4&gt;

&lt;p&gt;Another common use case is enabling developers to work together to review and debug code changes as soon as possible.&lt;/p&gt;

&lt;p&gt;With the Livecycle extension, you can instantly share any front-end or back-end service running on your machine.&lt;br&gt;
By simply opening a tunnel and creating a shareable URL, you enable your team to use their browsers to securely access these services.&lt;/p&gt;

&lt;p&gt;Your teammates can now see real-time logging, catch errors and execute commands in a terminal, so you can collaboratively fix issues MUCH earlier in the development lifecycle.&lt;/p&gt;

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

&lt;p&gt;These are just two of the many ways in which the extension can bring you fewer headaches and a better developer experience. So be sure to try the &lt;a href="https://open.docker.com/extensions/marketplace?extensionId=livecycle/docker-extension" rel="noopener noreferrer"&gt;Livecycle Extension&lt;/a&gt; today! Also, now we have the &lt;a href="https://preevy.dev/integrations/docker-extension" rel="noopener noreferrer"&gt;docs&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;Getting started with Livecycle Extension video:&lt;/p&gt;

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

&lt;p&gt;And, you're also invited to join our &lt;a href="https://community.livecycle.io/" rel="noopener noreferrer"&gt;Slack community&lt;/a&gt; focused on developer collaboration, developer experience and anything needed to get started with Livecycle.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>productivity</category>
      <category>development</category>
      <category>collaboration</category>
    </item>
    <item>
      <title>The (Detailed &amp; Creative) Playbook for Getting More GitHub Stars</title>
      <dc:creator>Zevi Reinitz</dc:creator>
      <pubDate>Mon, 14 Aug 2023 12:53:40 +0000</pubDate>
      <link>https://dev.to/livecycle/the-detailed-creative-playbook-for-more-github-stars-5fo5</link>
      <guid>https://dev.to/livecycle/the-detailed-creative-playbook-for-more-github-stars-5fo5</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;My team and I recently launched an &lt;a href="https://github.com/livecycle/preevy" rel="noopener noreferrer"&gt;open source tool for developers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;This was my first time promoting an open source tool. It was hard to find meaningful early-tage growth advice, so I had to get creative.&lt;/li&gt;
&lt;li&gt;We've quickly grown to more than 1.5k stars in a short time. I've compiled a detailed list of growth tactics that worked to bring us traffic and stars&lt;/li&gt;
&lt;li&gt;I’m sharing it all here so that others can apply these tactics and grow their own projects&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Launching an open source project for the first time
&lt;/h2&gt;

&lt;p&gt;Anyone involved in marketing knows that no two days are the same. You are constantly facing new challenges and unique situations.&lt;/p&gt;

&lt;p&gt;And so it was a few months back when I was tasked with promoting a new open source project that we built, called &lt;a href="https://github.com/livecycle/preevy" rel="noopener noreferrer"&gt;Preevy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezi0dldonh3380cesoi0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezi0dldonh3380cesoi0.jpeg" alt="Repo" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve spent years leading go to market efforts at various companies for dozens of products, but this was my first time doing so for an open source developer tool. Don't get me wrong - the devs on my team are seasoned OSS pros. But as the head of marketing, I was the open source newbie facing a learning curve. &lt;/p&gt;

&lt;p&gt;I looked at my lack of open source marketing experience as both an advantage and a disadvantage.&lt;/p&gt;

&lt;p&gt;On the one hand, I had a lot of catching up to do in a short period of time. On the other hand, it's always good when you can eliminate any preconceived notions of to how things "should" be done. I was free to research, question and develop a creative strategy with an open mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the post I wish I found 6 months ago
&lt;/h2&gt;

&lt;p&gt;Google quickly dampened my initial wave of enthusiasm. I looked for good advice to accelerate my learning, but most of the early-stage, open source growth content was shallow at best. I read articles promising to show me “How to get your first 1k Github stars” but was repeatedly left without the clear, tactical direction I was looking for.&lt;/p&gt;

&lt;p&gt;The next couple of months became a whirlwind of research and experimentation to figure out what works and what doesn't.&lt;/p&gt;

&lt;p&gt;And today, 12 weeks after launching Preevy, the project has 1.5k GitHub stars, and we’re seeing a week-over-week increase in repository traffic, forks and contributions. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzc79pda6wjjzw4sronx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzc79pda6wjjzw4sronx.png" alt="stars" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are several repeatable actions that have been effective in growing our traffic and our star count. In retrospect, some of them were buried in those generic "How to" articles, but most of them were not. Many of the creative steps we took (and continue to take) are lessons we learned the old-fashioned way.&lt;/p&gt;

&lt;p&gt;So in the spirit of true open source, I've outlined some of our most effective tactics in one place. It’s the kind of resource I wish I had found 6 months ago, and hopefully you will find this outline helpful as you launch and growing your own open source projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Focusing specifically on traffic GitHub stars
&lt;/h2&gt;

&lt;p&gt;To be clear - my specific focus is to show you how I got &lt;strong&gt;traffic&lt;/strong&gt; and &lt;strong&gt;GitHub stars&lt;/strong&gt; for my project. &lt;/p&gt;

&lt;p&gt;I won’t be focusing on other (important) aspects of open source growth such as: converting visitors to active users, encouraging contributions to the project, best practices for repo maintenance, building a community around your project, or deciding what to build in the first place.&lt;/p&gt;

&lt;p&gt;These are all worthy topics, but for another time. &lt;/p&gt;

&lt;p&gt;For now, I only care about stars.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why are GitHub stars so important?
&lt;/h2&gt;

&lt;p&gt;The underlying assumption here is that GitHub stars have value. But what exactly are they valuable for? &lt;/p&gt;

&lt;p&gt;Increasing your star count has several benefits clear and present benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It focuses the team's efforts and motivates everyone to rally around a single cause and a single metric that is constantly increasing&lt;/li&gt;
&lt;li&gt;Stars = credibility and trustworthiness in the eyes of potential users and contributors&lt;/li&gt;
&lt;li&gt;Your pool of stargazers can teach you a lot about your target audience &lt;/li&gt;
&lt;li&gt;Stars can help you reach &lt;a href="https://github.com/trending" rel="noopener noreferrer"&gt;GitHub trending&lt;/a&gt; status and a TON of visibility. (there are several factors that go into trending, but stars is an important one).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if you’re trying to promote your GitHub library, you should be thinking about how you can get more people to star it, especially in the first couple of months after you go live.&lt;/p&gt;

&lt;p&gt;So without further ado, let's take a deep dive into the key growth levers that worked for me and my team.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falq0b4ygiy8uaviovsc2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falq0b4ygiy8uaviovsc2.gif" alt="1" width="352" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites: Basic repo health
&lt;/h2&gt;

&lt;p&gt;The first thing I focused on was making sure our repository was set up for success. &lt;/p&gt;

&lt;p&gt;Those generic articles spend a lot of time on this, and like with any good cliche - there's a lot of truth to it. So we established a baseline for repo health that included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A clear description of what the tool does&lt;/li&gt;
&lt;li&gt;A Readme that is both informative and aesthetically pleasing (screenshot/GIF at the top, clearly structured, use of some emojis to mix it up a bit). I also upgraded the social card that appeared when the repo is linked on social.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://preevy.dev/" rel="noopener noreferrer"&gt;dedicated docs site&lt;/a&gt; with relevant technical information and how-to guides for people who want to use it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I don't have a lot of wisdom to add here. Just make a best effort at communicating clearly in your documentation (without any fluff) and don't be afraid to iterate as needed.  &lt;/p&gt;

&lt;p&gt;Once we covered the basics for Preevy, we set our sights on brining attention to the tool we had built.&lt;/p&gt;

&lt;p&gt;From a bird's eye view, our GTM strategy had two "phases": &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get our first 100 stars artificially&lt;/li&gt;
&lt;li&gt;Maintain natural growth from 100 stars and beyond&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The first 100 stars - artificial growth
&lt;/h2&gt;

&lt;p&gt;We wanted to get our first 100 stars quickly, so we started close to home. I assumed that between all of us on the team, we could find 100 relevant, first-degree connections willing to click a button and congratulate us on launching a new project.&lt;/p&gt;

&lt;p&gt;Here are the main actions that worked for us in this phase:&lt;/p&gt;

&lt;h3&gt;
  
  
  Kick-off message to friends and family
&lt;/h3&gt;

&lt;p&gt;We started simple. I composed a message announcing that we’ve just launched our first open source project, and asking people please check it out and show us support by leaving us a star. The message was simple and friendly, but also direct. &lt;/p&gt;

&lt;p&gt;Don't just reply with a thumbs up. Go to GitHub and give me a star (please). &lt;/p&gt;

&lt;p&gt;Each team member sent it out to people in their network: Relevant friends and family members, via email, Whatsapp, LinkedIn and Twitter DMs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ask the neighbors in our shared office space
&lt;/h3&gt;

&lt;p&gt;Our company office is in a shared workspace. Which means there are dozens of other startups and active GitHub accounts within a few meters of my desk. &lt;/p&gt;

&lt;p&gt;So I swallowed my pride, printed a QR code (to make it easy for others to open our repo on their device) and made a few causal rounds around the floor asking people if they could do us a quick favor and show us some GitHub-love. The vast majority of people were happy to help. &lt;/p&gt;

&lt;p&gt;My non-scientific assessment is that early morning had the best conversion rates, while people were still small-talking over coffee and before they got focused on their more serious daily tasks. &lt;/p&gt;

&lt;h3&gt;
  
  
  Show it off (for free) at conferences
&lt;/h3&gt;

&lt;p&gt;It just so happened that I attended a local tech conference shortly after Preevy launched. So I adapted  the shared office space strategy to the conference showroom floor. I walked around and tried to use my smalltalk opportunities to get a few more stars from the developers walking around. &lt;/p&gt;

&lt;h3&gt;
  
  
  First launch announcements on social media
&lt;/h3&gt;

&lt;p&gt;Once we had a few dozen stars, I posted about our launch on our social channels. &lt;/p&gt;

&lt;p&gt;I wanted new visitors to the repository to see that at least a few dozen people had already been there and liked what we are doing. &lt;/p&gt;

&lt;p&gt;Pretty soon, we celebrated our first 100 stars milestone, and we were ready to move into phase 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the first 100
&lt;/h2&gt;

&lt;p&gt;I probably could have used the above tactics alone to get us to 500 stars or more, but it would have been inefficient, and regardless - I wasn’t interested in this approach. My phase 1 focus was only on the 100-star threshold so as to establish the minimal credibility needed to convert future traffic.&lt;/p&gt;

&lt;p&gt;Our first 100 stars were decidedly artificial. And I wanted all the rest to be authentic and organic.&lt;/p&gt;

&lt;p&gt;Organic stargazers tell you a lot about who is interested in your tool. Analyzing a growing list of stargazers gives you product and marketing insights that you need to move forward effectively. So it was important to me that our list of stargazers grow naturally, as soon as possible. &lt;/p&gt;

&lt;p&gt;Here’s what worked for us as we moved into growth phase 2:&lt;/p&gt;

&lt;h3&gt;
  
  
  Content creation
&lt;/h3&gt;

&lt;p&gt;Content creation and distribution was a big part of our strategy (and this continues to be the case). This topic alone deserves a dedicated blog post or two, but we’ll summarize the key elements here. &lt;/p&gt;

&lt;p&gt;As far as content creation, we set out to create an ongoing flow of blog posts. These posts fell into one of four categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Present the tool directly&lt;/strong&gt; - We wrote a number of posts that talk about Preevy directly. What it is, why we built it, who we think can benefit from it. These can be very effective when they are written in an authentic, human way&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Present the tool indirectly as part of a larger project&lt;/strong&gt; - We wrote a number of “How-to” posts that show how to build a cool project, including Preevy as part of the stack&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listicles&lt;/strong&gt; - We put together a few list-based articles that had an open source angle to them. “5 Projects that will help you learn [some framework]” or “10 new open source repositories you need to know about in 2023” or something similar. We included Preevy in the list when relevant, but not every time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building in public&lt;/strong&gt; - Open source is about sharing with others.  So we wrote  several posts explaining how we solved an interesting problem or how we achieved a relevant milestone (like this post, for example)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each post had clear section headings. We added a TL;DR at the top and emojis/GIFs to keep it friendly and fun to read. We mentioned explicitly that we are building Preevy and we’d appreciate it if people could check it out and star the repository. We phrased this in-line request in different ways (sometimes more directly than others), but we always found a way to put it in the body of the article as a clear call to action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Content distribution
&lt;/h3&gt;

&lt;p&gt;Writing content is great, but it won't help you if you don’t have a good plan for distributing it to the relevant people. Here’s how we distributed our Preevy content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dev-centric blogging platforms&lt;/strong&gt; - We published our content on dev-centric blogging platforms like Dev.to, Hashnode, Hackernoon, and Medium. These are the main platforms we’ve been using, but there are others you might consider as well. When doing this, be mindful of any platform-specific tags you can use to better position your content (for example, DevTo has a #showdev tag that can help show your new tool off to other developers). Also note that on platforms like Dev.to, you can create a company blog with a fixed call to action that appears on the right side of any article you publish there. This helps to get more people clicking through from your content to your GitHub repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Here's one of our posts trending on Dev.to:&lt;/em&gt; &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fguzz9ttfxsgu2oedx654.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fguzz9ttfxsgu2oedx654.jpeg" alt="devto" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reddit and social media&lt;/strong&gt; - Once the content was published on the above platforms, we promoted it on social media and in relevant subreddits. We did not drive traffic to our company blog (we’ll get to that in a minute). Rather, we intentionally directed people to the articles hosted on these outside blogging platforms. We did this because each of these blogging platforms has a built-in trending algorithm that boosts high-performing posts. By driving traffic to these links, we got the platform algorithms to work for us and get our posts many more views in a short period of time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Our company blog&lt;/strong&gt; - Don’t worry. We didn’t forget about our own site. We also published all content on our company blog. After all, SEO is still a thing, and so it’s good to have all that relevant content hosted on the company domain. As extra credit, we also managed to get our blog approved as a content source by dev-centric content aggregators like &lt;a href="https://app.daily.dev/sources/livecycle" rel="noopener noreferrer"&gt;daily.dev&lt;/a&gt;. This helps us to distribute the content posted on our company’s blog, in addition to the content published on those external blogging sites.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Github Lists and Topics
&lt;/h3&gt;

&lt;p&gt;There are tons of great lists on GitHub (often called “Awesome Lists”) where maintainers aggregate tools, projects and resources with a particular focus. We found several lists relevant to our tool, and opened a pull request to suggest Preevy as an addition. &lt;/p&gt;

&lt;p&gt;Note that in some cases, you’ll need to make minor adjustments to your project or documentation to meet the list membership requirements. But this could be worth it if it's a popular list that has a lot of visitors.&lt;/p&gt;

&lt;p&gt;In addition to “Lists” which are privately maintained, GitHub also maintains &lt;a href="https://github.com/topics" rel="noopener noreferrer"&gt;“Topics”&lt;/a&gt;. Open source projects can be submitted for inclusion under a relevant topic, but only by someone who is not connected to the project in an official way. So if you have friends or early adopters of your tool who love what you’re doing, you might consider asking them for a favor and having them submit your project to a few of these GitHub "Topics".&lt;/p&gt;

&lt;p&gt;We’ve used both Lists and Topics to promote Preevy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Sites and Newsletters
&lt;/h3&gt;

&lt;p&gt;We found a number of sites and newsletters focused on promoting open source tools. We used these resources to promote Preevy. Here are two examples that were effective for us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://libraries.github20k.com/" rel="noopener noreferrer"&gt;GitHub20K&lt;/a&gt; - Add your library here for free (maintained by &lt;a class="mentioned-user" href="https://dev.to/nevodavid"&gt;@nevodavid&lt;/a&gt; ) &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://console.dev/" rel="noopener noreferrer"&gt;Console.dev&lt;/a&gt; - Submit your tool for free, or pay to sponsor a newsletter&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Relevant communities and dark social
&lt;/h3&gt;

&lt;p&gt;We joined a bunch of communities. We wanted to be a part of relevant conversations, and promote our tool and our content in a more natural way. These communities exist on platforms such as: Slack, Discord, Reddit, Whatsapp, LinkedIn and Facebook. To find communities relevant to you, just spend a few minutes searching, or ask others in your industry to guide you towards the communities that are worth joining.&lt;/p&gt;

&lt;p&gt;We noticed that each community has its own rules, nuances and opportunities. For example, on a particular Slack or Discord server, there might be a channel dedicated to showing off new tools or promoting new content you’ve written. Similarly, many subreddits have one day per week where you can self-promote something you’ve built and get feedback. Once you've found some communities, make friends and play by the rules. &lt;/p&gt;

&lt;h3&gt;
  
  
  Paid ads campaigns
&lt;/h3&gt;

&lt;p&gt;Once we generated a decent amount of organic traffic, we ran some small, paid ad campaigns. We used three advertising platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.ethicalads.io/" rel="noopener noreferrer"&gt;Ethical Ads&lt;/a&gt; (a dev-focused advertising platform)&lt;/li&gt;
&lt;li&gt;Reddit (with a focus on specific, technical subreddits)&lt;/li&gt;
&lt;li&gt;Twitter (with a focus on specific, relevant keywords)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These campaigns brought us traffic, and they also allowed us to test our messaging and learn more about what attracted people to our repository. We used these results to further optimize our content and our future ad campaigns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Influencers
&lt;/h3&gt;

&lt;p&gt;Influencer marketing can be very effective in any industry, and open source/developer tools is no different. The trick is to the right people with the right audience.&lt;/p&gt;

&lt;p&gt;We actively searched for those people in our industry, developed relationships and ran some collaborative experiments. The majority of them were successful (a few were not, which was expected).&lt;/p&gt;

&lt;p&gt;Each influencer knows their audience and their style. Be clear about your campaign objectives and work with them to create the content and campaigns that work best (co-created posts, product reviews, shout-outs on social or whatever else you all have in mind). &lt;/p&gt;

&lt;h3&gt;
  
  
  Podcasts and promotions
&lt;/h3&gt;

&lt;p&gt;I’ll keep this one brief because it’s pretty self-explanatory. If you can find other people to promote you on their podcasts, webinars, conferences, or by allowing you to publish a guest blog to their site, it can help you get a lot of traffic quickly.  &lt;/p&gt;

&lt;p&gt;We were able to do this a couple of times for Preevy so far, and we’re already working on more of these opportunities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use cases and testimonials
&lt;/h3&gt;

&lt;p&gt;Because I’m active on dev-centric blogging platforms, I kept an eye out for dev bloggers who were experienced and well-versed in our space. I looked for high-performing articles and reached out to the authors to ask them if they wanted to try Preevy and write about it. &lt;/p&gt;

&lt;p&gt;Some wanted to be paid (rightfully so), and some (surprisingly) did not. &lt;/p&gt;

&lt;p&gt;Some wanted to ghostwrite for us (without using their name) and some wanted to publish content in their own name on their own pages.&lt;/p&gt;

&lt;p&gt;It took us some time to find the right people, but once we did, all of the above arrangements worked for us.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Hackernews
&lt;/h3&gt;

&lt;p&gt;We used Hackernews to promote Preevy in two ways: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Post the GitHub repository under the &lt;a href="https://news.ycombinator.com/show" rel="noopener noreferrer"&gt;“Show HN” tag&lt;/a&gt; - Hackernews can be a great place to share your new project with other technical folks. It helps to get others to upvote and comment soon after posting (just don’t share the direct link to your post!). We added a first comment where our CTO explained what we built and inviting others to try it. I don’t know if this comment helped, but I saw a lot of other open source projects doing the same. And while I can’t say for sure, it seems like HN is friendlier to GitHub repository links as opposed to some branded URL. So with a bit of coordination, HN could give you a potent dose of traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73d6ctgb6026a5uax4fa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73d6ctgb6026a5uax4fa.png" alt="HN" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Post content - We’ve tried posting some of our content on HN. Success is hit or miss, and HN will not even accept posts from some external blogging platforms. But it’s free to try and the potential upside is huge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Social media retargeting
&lt;/h3&gt;

&lt;p&gt;From the moment we formally announced the Preevy launch, we had organic social media activity running in the background. We'll save the detailed social media strategy for another post, but suffice it to say that the account was active and the content was varied. &lt;/p&gt;

&lt;p&gt;As more people engaged with the content, I began retargeting as many of them as possible by inviting them to try/star Preevy for themselves. &lt;/p&gt;

&lt;p&gt;I had Twitter DM template that I would send them, thanking them for linking our recent post and asking if they’d be willing to star the Preevy repo. &lt;/p&gt;

&lt;p&gt;It took time, but lots of people were happy to help.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shamelessly promote other people and projects
&lt;/h3&gt;

&lt;p&gt;When I outlined my approach to “content creation” above, I mentioned that one types of content we’ve produced are listicles of other relevant projects or tools. One of the reasons this content is so effective is that is enables us to shamelessly promote other people. &lt;/p&gt;

&lt;p&gt;Open source is not a zero-sum game. There’s enough traffic and enough GitHub stars to go around. And by genuinely promoting other people, companies and projects, you can get them to promote you in return. it’s almost like a “forced” collaboration and it’s often a win-win.&lt;/p&gt;

&lt;p&gt;So for example, when we wrote listicles that included other open source projects, we tagged these companies/maintainers on Twitter when we promoted the article. Many time, they would like and retweet, adding a lot more reach to our content. This approach can be applied in many different ways, but it’s potent enough to deserve a dedicated mention in our list of open source GTM actions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xt51uekc0jx722uc7oh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xt51uekc0jx722uc7oh.png" alt="supabase" width="800" height="1046"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  My (crazy) Github retargeting experiment
&lt;/h3&gt;

&lt;p&gt;Once we reached a few hundred stargazers, I analyzed the modest audience I had built. I developed an experimental, multi-part playbook for promoting Preevy in a more targeted way to people who were more likely to be interested in it. Here’s a quick summary of what I came up with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I used tools (such at &lt;a href="https://github.com/spencerkimball/stargazers" rel="noopener noreferrer"&gt;this one&lt;/a&gt; and &lt;a href="https://clickhouse.com/" rel="noopener noreferrer"&gt;this one&lt;/a&gt;) to see what other repos our stargazers were starring most frequently. The stargazers of these "other" commonly starred repos became an expanded pool of potential stargazers for Preevy&lt;/li&gt;
&lt;li&gt;I looked through the stargazers in these other repos and identified people who had publicly exposed email addresses in their GitHub profiles. To me, this was a clue that they didn’t mind being contacted via email&lt;/li&gt;
&lt;li&gt;I further identified the people who I thought were most relevant and followed them on GitHub&lt;/li&gt;
&lt;li&gt;Then, I reached out to these folks via email, told them I had just followed them and introduced myself and my project in case they were interested to check it out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last two steps were just my personal spin. You can probably do without them. The main idea is to use your pool of authentic stargazers to point you in the direction of a wider pool of similar users who might be interested in what you have to offer.&lt;/p&gt;

&lt;p&gt;As a bonus, you can also look at what those most commonly starred repositories are doing to market their tools, and try some of it yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Celebrate milestones!
&lt;/h3&gt;

&lt;p&gt;We took every opportunity to celebrate a milestone in our Preevy growth journey. Every hundred star milestone got a celebratory GIF and a set of posts to drive as much positive attention to the repository as possible.&lt;/p&gt;

&lt;p&gt;And when we missed celebrating 700, we &lt;a href="https://twitter.com/get_livecycle/status/1681648754909216769?s=20" rel="noopener noreferrer"&gt;celebrated 735 instead&lt;/a&gt; (because it’s good to be different sometimes).&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1681648754909216769-830" src="https://platform.twitter.com/embed/Tweet.html?id=1681648754909216769"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1681648754909216769-830');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1681648754909216769&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;And when we hit the 1k star milestone, &lt;a href="https://twitter.com/get_livecycle/status/1689539582730096642?s=20" rel="noopener noreferrer"&gt;we kicked off a celebratory giveaway&lt;/a&gt; (which is actually still open until the end of this week). To enter, people need to star the repo, follow us on Twitter and retweet/tag 3 friends. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1689539582730096642-144" src="https://platform.twitter.com/embed/Tweet.html?id=1689539582730096642"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1689539582730096642-144');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1689539582730096642&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;h2&gt;
  
  
  Other ideas to consider
&lt;/h2&gt;

&lt;p&gt;These are the ideas that worked best for us to far, that can easily be applied to other projects. We had tons of other ideas that didn't work as well, or that worked but were very specific to what we were building.&lt;/p&gt;

&lt;p&gt;We have a bunch of experiments still to consider and in the spirit of open source, I'll share a couple of them here for your consideration:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Translate the readme into multiple languages&lt;/strong&gt; - At the moment, the Preevy readme is in English. But I’ve noticed that in the GitHub trending lists, you can filter by spoken language. I wonder if translating our readme into other languages will create a larger surface area for the repository to hit those trending lists with more frequency&lt;br&gt;
&lt;strong&gt;- Product Hunt&lt;/strong&gt; - We’ll soon be launching Preevy on Product Hunt. It’s a great place to launch new products and tools and we’re looking forward to leveraging it’s reach to bring a lot more attention to what we’re building.&lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;I hope our experience in starting to grow Preevy can help you grow your own project - by borrowing some of these ideas or by thinking of new ideas on your own.&lt;/p&gt;

&lt;p&gt;I'd be thrilled to get additional open source growth suggestions in the comments!&lt;/p&gt;

&lt;p&gt;And if you've made it this far, and are willing to leave Preevy a star I'd really appreciate it! &lt;a href="https://github.com/livecycle/preevy" rel="noopener noreferrer"&gt;https://github.com/livecycle/preevy&lt;/a&gt; 🙏 🙏&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>showdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Magic of Ephemeral Preview Environments</title>
      <dc:creator>Zevi Reinitz</dc:creator>
      <pubDate>Thu, 27 Jul 2023 09:55:06 +0000</pubDate>
      <link>https://dev.to/livecycle/the-magic-of-ephemeral-preview-environments-49pb</link>
      <guid>https://dev.to/livecycle/the-magic-of-ephemeral-preview-environments-49pb</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;The magic of ephemeral preview environments&lt;/strong&gt;
&lt;/h2&gt;

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

&lt;p&gt;&lt;em&gt;This article was originally written by&lt;a href="https://hashnode.com/@kunalk" rel="noopener noreferrer"&gt; Kunal Kushwaha&lt;/a&gt; and published &lt;a href="https://blog.wemakedevs.org/the-magic-of-preview-environments" rel="noopener noreferrer"&gt;here&lt;/a&gt;, on the We Make Devs blog.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;In traditional &lt;a href="https://www.atlassian.com/microservices/microservices-architecture/microservices-vs-monolith#:~:text=A%20monolithic%20architecture%20is%20a,monolith%20architecture%20for%20software%20design." rel="noopener noreferrer"&gt;monolithic systems&lt;/a&gt;, reviewing code was a relatively simple process. As the entire application is bundled as just one single component, building the entire project either locally, or in an online coding environment such as Replit or GitHub codespaces is all you needed to do to view the changes and see how they would work.&lt;/p&gt;

&lt;p&gt;However, the story changes as we move to a microservice-based architecture. In a microservice architecture, the entire application is broken down into many small components which are designed to be their own self-contained applications. This means that these small components can run without depending on the other components in the architecture. Perhaps you can already see the problems that arise while reviewing changes to such codebases.&lt;/p&gt;

&lt;p&gt;Since every application is a self-contained app, in order to review some code changes and see the impact of the change across the entire application i.e. when all the microservices are running and working together, you would need to build each and every microservice. While this type of architecture has benefits in a production system, it does make it difficult to review code and see the impact of changes across the entire application. This is where we can leverage the power of preview environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmvcvyfvgsjxzyseg1uib.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmvcvyfvgsjxzyseg1uib.png" alt="1" width="768" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://blog.wemakedevs.org/the-magic-of-preview-environments#heading-why-do-we-have-so-many-environments" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;strong&gt;Why do we have so many environments?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before the look at preview environments, let's try to understand why we have multiple different environments. By understanding this, we will be able to appreciate the benefits of preview environments even more.&lt;/p&gt;

&lt;p&gt;In a system that runs on Kubernetes, i.e. an application or multiple applications that use a microservice architecture, we have many different &lt;a href="https://www.techtarget.com/searchsoftwarequality/definition/development-environment" rel="noopener noreferrer"&gt;environments&lt;/a&gt;. These environments all have different functions and use cases. Some of the common environments include a production environment, a staging environment, a QA environment, a local development environment, etc. Each of these environments has a different use case.&lt;/p&gt;

&lt;p&gt;For example, the main use case for a local development environment would be to write code for the application. We talked about the complexities of building a microservice application earlier. You would need to build up many individual services and connect them to see the full extent of the code changes. In a local environment, this can be done either by using a docker-compose service or a local Kubernetes cluster such as Kind or Minikube.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqf1vh30kkmopwmuny5wn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqf1vh30kkmopwmuny5wn.png" alt="2" width="779" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The QA environment would be concerned with making sure that all the components are working correctly or not. The staging environment would be used to test the features before they are added to production. As you can see, there are tons of different environments for applications. There might be even more environments depending on the needs of the applications.&lt;/p&gt;

&lt;p&gt;As such, it can be difficult to efficiently manage so many different environments. The environments might not all be the same either, which can lead to some problems. For example, a local development environment runs at a much smaller scale than a production environment. While the production environment might be using 100 microservices due to scaling, a local environment would have only a fraction of that number. As such, it can be difficult to anticipate problems that might arise in the production environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://blog.wemakedevs.org/the-magic-of-preview-environments#heading-why-consider-using-preview-environments" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;strong&gt;Why consider using preview environments?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We already talked about so many different kinds of environments. Now let us talk about one more environment called preview, or ephemeral environments. These are temporary environments that live for a short period of time before getting destroyed. Why would we want to have these kinds of environments? Let's first try and understand the entire workflow without using preview environments.&lt;/p&gt;

&lt;p&gt;The first step in the entire process to add a new feature or existing one would be to write the code for the application. This would be done by a developer, someone who understands how to read and write code. After doing a bit of local testing, they will push the code to their git repository, whether it's GitHub or GitLab, and then open a PR/MR to merge the code for the new feature to the upstream repository.&lt;/p&gt;

&lt;p&gt;Assuming that the best practices for git workflows are being followed, this feature would be opened in a new branch in the upstream repository. This is where other developers will be able to review the code for this new feature, point out bugs and suggest some improvements. However, the main point to note, is that the code review is being done by other developers, who also understand how to read and write code. Product teams, designers or other stakeholders will not be able to make sense of this code.&lt;/p&gt;

&lt;p&gt;Once other developers review the code, it would get merged into the new branch, and this new branch would be visible in one of your test environments such as the staging environment. At this stage, the product managers, designers and other non-technical teams would be able to view all the changes to the application, use it and make sure all the functionality works as expected, etc.&lt;/p&gt;

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

&lt;p&gt;Now let's say that the designer finds something that is wrong with the design, or the product manager finds that certain functionality isn't working as expected. Now it is back to the developers to update the code to make sure the problems are fixed. However, developers will need to do the entire process all over again. They will need to make a new branch, open a new PR, get it reviewed once more, and then push it to staging again.&lt;/p&gt;

&lt;p&gt;This is quite a tedious process and wastes a lot of time as well as resources. It can also be an expensive process as your preview environments which are running in Kubernetes would use up more resources. Imagine the benefit if the product and other non-technical teams were able to preview the application in the PR itself before it gets pushed to staging. This not only can save time and energy but can also save money in the long run.&lt;/p&gt;

&lt;p&gt;This is the entire idea behind a preview environment. These environments are automatically created when you open a PR and get destroyed once your code is merged into the main branch. Thanks to these preview environments, other stakeholders of the product are able to view the changes and provide feedback, just as developers would provide code reviews.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvrbfbq02l7q2lg2d7ei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvrbfbq02l7q2lg2d7ei.png" alt="4" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://livecycle.io/blogs/preevy-preview-environments-for-everyone/" rel="noopener noreferrer"&gt;Preview environments&lt;/a&gt; are not beneficial only to non-technical teams. Oftentimes, when developers are asked to provide code reviews, they might be working on some other features. In order to provide a review, they would need to clone the changed code, and run it locally, which would disrupt their own development tasks. With the help of preview environments, they wouldn't need to go through the additional steps of cloning, and building the project. They can simply use the same preview environment to see the changes, and the code at the same time and make live changes as required.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://blog.wemakedevs.org/the-magic-of-preview-environments#heading-what-are-some-preview-environments-that-can-be-used" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;strong&gt;What are some preview environments that can be used?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One of the most simple use cases for preview environments is for previewing front-end applications. This is easy to do by using services such as Netlify and Vercel. These services let you preview your code changes even before you push the code into your branch. This lets you create changes to the front end and view it in real time.&lt;/p&gt;

&lt;p&gt;However, a front end is just a monolith. The process of creating these preview environments gets difficult as the application gets distributed between multiple microservices. It might even be distributed over 100s of microservers which makes it increasingly difficult to create preview environments for them.&lt;/p&gt;

&lt;p&gt;The problem of creating a preview environment is theoretically solved for a local computer. On your local system, you can very easily create a docker-compose file, and use docker-compose to deploy all the components of the application locally. However, this is limited to your local environment, which means you are the only one who is able to preview the application. A proper solution would be if these local implementations can somehow be used on the cloud.&lt;/p&gt;

&lt;p&gt;This is exactly what &lt;a href="https://github.com/livecycle/preevy?utm_source=wemakedevs&amp;amp;utm_medium=wemakedevslc&amp;amp;utm_campaign=collab1" rel="noopener noreferrer"&gt;Preevy by Livecycle&lt;/a&gt; does in order to create some preview environments. Preevy is able to take your Docker Compose files, and instead of running it on a local system, it runs it in a VM on the cloud. Preevy can also create its own HTTPS links which allows anyone from your team to access the preview website after authenticating. If your Docker Composer environment is configured correctly in a local environment, using Preevy is as simple as running a simple &lt;code&gt;preevy up&lt;/code&gt; command instead of running &lt;code&gt;docker-compose up&lt;/code&gt; as you would for a local environment. Preevy can also run on your Kubernetes cluster and create environments inside your cluster itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://blog.wemakedevs.org/the-magic-of-preview-environments#heading-some-challenges-with-setting-up-preview-environments" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;strong&gt;Some challenges with setting up preview environments&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The main problem with adopting preview environments in your entire development workflow would just be to solve the same issues that you face while setting up local environments.&lt;/p&gt;

&lt;p&gt;While creating a local docker-compose environment, there are a few challenges you might run into. These challenges can range from incorrect container build instructions to configuration issues or even an issue with how the containers talk with each other. Another challenge lies in working with data. As we know, containers are ephemeral, which means they don't work very well for storing data. This can lead to a few challenges while working with databases and applications that rely on data.&lt;/p&gt;

&lt;p&gt;In a nutshell, the only challenges that you will face while setting up a preview environment, are the same ones you face while setting up a local environment. If your docker compose environment works without any issues, then your preview environment which is created by Preevy will work in the exact same way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig7ykhrznfu6cr4snywu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig7ykhrznfu6cr4snywu.png" alt="5" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another challenge with preview environments arises if your microservices are in different repositories. Let's say that your front end exists in one repository, and your back end is in another repository. This poses a challenge while connecting the two separate environments. This is a little easier to solve if all the different microservices exist within the same repository.&lt;/p&gt;

&lt;p&gt;You also need to make sure that your preview environments are performant, while also not increasing costs. Since the preview environments use VMs, it's easy to potentially create 100s of preview environments which might increase the costs exponentially. In this case, it is important to create and destroy these preview environments quickly and not let them live for too long.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://blog.wemakedevs.org/the-magic-of-preview-environments#heading-conclusion" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In order to optimize your development workflows, and allow other stakeholders to review changes to the application before pushing your code to a staging environment, it's important to use preview environments. They help reduce the time and effort needed to make a change, and changes can be made instantly within the PR itself.&lt;/p&gt;

&lt;p&gt;Instead of pushing the changes to a staging environment and then getting the changes reviewed, you can simply review them inside the PR itself. This saves both time and energy and if done right, can save costs as well.&lt;/p&gt;

&lt;p&gt;Try setting up some staging environments for your repositories using &lt;a href="https://github.com/livecycle/preevy?utm_source=wemakedevs&amp;amp;utm_medium=wemakedevslc&amp;amp;utm_campaign=collab1" rel="noopener noreferrer"&gt;Preevy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also check out the &lt;a href="https://preevy.dev/?utm_source=wemakedevs&amp;amp;utm_medium=wemakedevslc&amp;amp;utm_campaign=collab1" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to help you get started.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>devops</category>
      <category>webdev</category>
      <category>github</category>
    </item>
    <item>
      <title>Why Developers Should Use Preview Environments</title>
      <dc:creator>Zevi Reinitz</dc:creator>
      <pubDate>Thu, 27 Jul 2023 07:52:00 +0000</pubDate>
      <link>https://dev.to/livecycle/why-developers-should-use-preview-environments-31io</link>
      <guid>https://dev.to/livecycle/why-developers-should-use-preview-environments-31io</guid>
      <description>&lt;p&gt;Check out the latest episode in the Open Source Cafe podcast, where Assaf Krintza (&lt;a class="mentioned-user" href="https://dev.to/assafkr"&gt;@assafkr&lt;/a&gt; - Co-founder &amp;amp; VP Engineering at Livecycle) sits down with Kunal Kushwaha to explore the world of preview environments.&lt;/p&gt;

&lt;p&gt;Some of the topics covered in this episode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An overview view of the various types of environments that developers encounter&lt;/li&gt;
&lt;li&gt;What are preview environments and how can developers benefit from using them in their development process&lt;/li&gt;
&lt;li&gt;About “&lt;a href="https://github.com/livecycle/preevy" rel="noopener noreferrer"&gt;Preevy&lt;/a&gt;” - an open source tool that simplifies the creation of preview environments &lt;/li&gt;
&lt;li&gt;Some of the the pain points and challenges faced by developers that Preevy addresses&lt;/li&gt;
&lt;li&gt;Preevy’s support for AWS, Azure, Google Cloud and K8s&lt;/li&gt;
&lt;li&gt;Common misconceptions and myths surrounding preview environments &lt;/li&gt;
&lt;li&gt;Several other gems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Watch this podcast episode here:&lt;/p&gt;

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

</description>
      <category>opensource</category>
      <category>devops</category>
      <category>cloud</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to build and deploy a modern-day Next.js application</title>
      <dc:creator>Andrew Baisden</dc:creator>
      <pubDate>Wed, 19 Jul 2023 14:41:17 +0000</pubDate>
      <link>https://dev.to/livecycle/how-to-build-and-deploy-a-modern-day-nextjs-application-mgn</link>
      <guid>https://dev.to/livecycle/how-to-build-and-deploy-a-modern-day-nextjs-application-mgn</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Making websites is not what it used to be. Over the past ten years, it has changed from being a very straightforward area controlled by HTML, CSS, and JavaScript to a vast ecosystem of tools and frameworks, each with its own distinct features and capabilities. You need to have a solid understanding of several cutting-edge technologies if you want to become an expert in modern web development. The complexity of today's development environment necessitates an agile mind and a strong commitment to lifelong learning, from data fetching to authentication, rendering to backend, and containerisation.&lt;/p&gt;

&lt;p&gt;This article is for people who are ready to step up their game and genuinely understand the practices of a modern JavaScript developer. Next.js, Auth.js, Databases, GraphQL, Docker, and Preevy will all be covered in this guide. We'll look at the server-side rendering and static site creation with Next.js. Auth.js will assist us in unravelling the secrets of robust and secure user authentication. We'll reimagine how we interact with APIs and handle data via the perspective of GraphQL. Docker will show us the tremendous containerisation options, and Preevy will provide us with the ability to provision a preview environment for our application. Finally, we will do a production deployment on &lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;, and &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; so that we can experience what it's like to have an application up and running on different platforms.&lt;/p&gt;

&lt;p&gt;Are you ready to push the boundaries, test your knowledge, and possibly even redefine your perception of what current web development involves? Then strap in for a detailed review of understanding contemporary web programming. We will start by going over an introduction of each technology and then we will build an app to reinforce what we have learned.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The main aim of this article will be to create a simple application and then demonstrate the relationship between the tools. With this knowledge, you will be able to see how straightforward it is to deploy your Next.js applications online regardless of how basic or complex the codebase is.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the upcoming sections, we will go through these topics related to building modern Next.js applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using Next.js for web app development&lt;/li&gt;
&lt;li&gt;Adding authentication with Auth.js&lt;/li&gt;
&lt;li&gt;Databases for persisting state and storing data&lt;/li&gt;
&lt;li&gt;GraphQL the modern alternative to REST APIs&lt;/li&gt;
&lt;li&gt;Having a Docker development environment&lt;/li&gt;
&lt;li&gt;Setting up Preevy to provision preview environments&lt;/li&gt;
&lt;li&gt;Building and deploying our application&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using Next.js for web app development
&lt;/h2&gt;

&lt;p&gt;Next.js is a framework for building server-side rendered React apps, making it suitable for generating quick and dynamic web applications. It's significant for web app development because it helps with things like page routing, server-side rendering, and quick loading times, which are critical for generating a great user experience. Additionally, it is simple to use and has a growing community of developers who are always striving to improve it. It has already replaced Create React App as the number one React build tool.&lt;/p&gt;

&lt;p&gt;Building a web application is just one stage of the development process we also have to think about making our applications secure using authentication. Let's now learn about Auth.js, a new modern way to add an authentication layer to our applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding authentication with Auth.js
&lt;/h2&gt;

&lt;p&gt;Auth.js is created by Vercel and is an open-source community project. It was originally called NextAuth.js until they rebranded and it is designed to be an authentication layer for the web. Auth.js helps developers to configure an authentication flow for their online projects. It is compatible with an extensive list of authentication providers along with additional choices. With Auth.js we can integrate many different providers into our applications, giving us the power to use them to log in and out. Some of the most well-known provider options include Google, GitHub, Facebook, Instagram and many more.&lt;/p&gt;

&lt;p&gt;It currently supports frameworks like Next.js, Svelte.js and Solid.js with many more on the way. Let's now dive into databases and see why they are a good storage option for our data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Databases for persisting state and storing data
&lt;/h2&gt;

&lt;p&gt;When it comes to storing information, many people choose databases. Databases have become a crucial aspect of most applications, whether you want to store user data or keep track of the state. They assist you in organising your data and ensuring that it is secure and accessible when needed. Databases can be used for a variety of purposes, ranging from analytics to powering websites and apps. As a result, they have become an indispensable tool for developers and businesses.&lt;/p&gt;

&lt;p&gt;Several databases are available, each with unique features that can either be or might not prove suitable for our needs. The most common is RDBMS (relational database management systems), which stores data in tables with various columns that can be connected together. NoSQL databases, on the other hand, provide more scalability and flexibility and additional possibilities for customising how your data is stored.&lt;/p&gt;

&lt;p&gt;Whatever choice you use, databases are an essential resource for preserving state and storing data. Their ability to simplify and automate activities makes them worthwhile to consider when developing apps or services. And their dependability assures that your data will be protected and accessible for a long time.&lt;/p&gt;

&lt;p&gt;Now that we have an introduction to databases, let's move on to learning about GraphQL and why it's the perfect modern alternative to REST APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL the modern alternative to REST APIs
&lt;/h2&gt;

&lt;p&gt;GraphQL is increasingly replacing conventional REST APIs as the preferred protocol. Instead of dealing with a vast and often burdensome payload of data, this powerful tool allows developers to request only what they need from an API. GraphQL also allows developers to query several resources at the same time via nesting, which can result in quicker and more efficient development. It also offers good documentation support, making it simple to understand and use, which makes GraphQL an appealing alternative for modern development.&lt;/p&gt;

&lt;p&gt;Utilising GraphQL ensures that your technical stack is robust and up to date with current trends. With GraphQL, it is possible for it to be used on both the client and server sides. This means that you can choose to create a backend which will fetch the data from the API or you could have it running on the frontend so that you can skip creating a backend altogether. In this tutorial, we will use it on the front so there will be no need to create an Express.js backend server.&lt;/p&gt;

&lt;p&gt;Another essential part of modern developer technical stacks is Docker. Let's keep reading and see how Docker can help us with our projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Having a Docker development environment
&lt;/h2&gt;

&lt;p&gt;Docker development involves more than just setting up a single development environment. It is about ensuring that your whole development process can be efficiently replicated, reused, and automated. With the proper configuration, you'll be able to swiftly and consistently build various settings, eventually saving time and money in the long run.&lt;/p&gt;

&lt;p&gt;Docker allows developers to bundle their apps into "containers" that contain all of the essential code and dependencies for running them in production. You no longer need to wonder whether it works locally and will also work when it goes live. These containers are lightweight and easy to move across servers, allowing you to test new features without affecting old ones. Everything is carefully wrapped up together.&lt;/p&gt;

&lt;p&gt;The last section we will cover before we start building our app will be Preevy. Let's learn how this new tool can help us to provision our preview environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Preevy to provision preview environments
&lt;/h2&gt;

&lt;p&gt;Preevy is created by LiveCycle and is used to assist development teams in improving their code-review operations by offering a simple and affordable approach to building temporary environments for each branch. These are also referred to as &lt;strong&gt;Preview Environments&lt;/strong&gt;. Before merging changes on a branch, we can use preview environments to test, check, and see changes.&lt;/p&gt;

&lt;p&gt;With Preevy, the difficulty of installing preview environments is decreased considerably, allowing all developers with a basic understanding of Docker to use it. We can create a development version via a URL which is typically appended to each pull/merge request. With this setup, we will have a version which is only for development and not production to play around with.&lt;/p&gt;

&lt;p&gt;We will need to create an account with Amazon AWS so that we can use AWS Lightsail for the deployment. When using the aws-lightsail driver, Preevy can deploy virtual machines on AWS Lightsail. AWS Lightsail is Amazon's low-cost option for cloud-based virtual machines. AWS lightsail deployment time for a VM is typically under 2 minutes, and its monthly cost can be as cheap as $3.50, making them perfect for large-scale preview settings.&lt;/p&gt;

&lt;p&gt;We now have a much greater understanding of what makes up a modern JavaScript full-stack application. It's time for us to start building our app so let's get to it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Building and deploying our application
&lt;/h2&gt;

&lt;p&gt;The app that we are going to build is an e-commerce website like Amazon. It will be a basic example with a few page routes, two of which will require GitHub or Google authenticated sign-in before you can see the data on the pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8htbw0acnnjb2gsf4jr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8htbw0acnnjb2gsf4jr.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687372351/next-auth-store-app_ik1wq4.jpg" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;We will be using hard code data in place of a database layer just to make things easier in this project. If this was a production-level application then we would set up a real database layer. There is no CRUD functionality this app has page routing and the logic for logging in and out of authenticated routes. It is easy enough to create your own more advanced applications once you understand these fundamentals.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In addition, we are also going to be using the most up-to-date and latest &lt;a href="https://nextjs.org/docs/app" rel="noopener noreferrer"&gt;App Router&lt;/a&gt; feature in Next.js which replaces the older &lt;a href="https://nextjs.org/docs/pages/building-your-application" rel="noopener noreferrer"&gt;Pages Router&lt;/a&gt; setup. So we get a feel for using the latest syntax and codebase Next.js has available to us. Vercel will get priority in the code because they are the creators of Auth.js although we will cover Netlify deployments later.&lt;/p&gt;

&lt;p&gt;Firstly ensure that you are aware of the prerequisites and that you have your developer environment set up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://authjs.dev/" rel="noopener noreferrer"&gt;Auth.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.apollographql.com/" rel="noopener noreferrer"&gt;Apollo GraphQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/?nc2=h_lg" rel="noopener noreferrer"&gt;Amazon Web Services (AWS)&lt;/a&gt; for AWS Lightsail deployments with Preevy&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/cli/" rel="noopener noreferrer"&gt;AWS CLI &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://preevy.dev/" rel="noopener noreferrer"&gt;Preevy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and &lt;a href="https://www.google.com/" rel="noopener noreferrer"&gt;Google&lt;/a&gt; account for setting up authentication&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the prerequisites out of the way let us now start building our app in the upcoming section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the app
&lt;/h3&gt;

&lt;p&gt;Firstly navigate to a directory on your computer like on the desktop so that we have a location to use for creating our project. Now run these commands to set up our project using Next.js.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;store-project
&lt;span class="nb"&gt;cd &lt;/span&gt;store-project
npx create-next-app my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the settings I used:&lt;/p&gt;

&lt;p&gt;✔ Would you like to use TypeScript with this project? … &lt;strong&gt;No&lt;/strong&gt; / Yes&lt;br&gt;
✔ Would you like to use ESLint with this project? … &lt;strong&gt;No&lt;/strong&gt; / Yes&lt;br&gt;
✔ Would you like to use Tailwind CSS with this project? … &lt;strong&gt;No&lt;/strong&gt; / Yes&lt;br&gt;
✔ Would you like to use &lt;code&gt;src/&lt;/code&gt; directory with this project? … No / &lt;strong&gt;Yes&lt;/strong&gt;&lt;br&gt;
✔ Use App Router (recommended)? … No / &lt;strong&gt;Yes&lt;/strong&gt;&lt;br&gt;
✔ Would you like to customize the default import alias? … &lt;strong&gt;No&lt;/strong&gt; / Yes&lt;/p&gt;

&lt;p&gt;Now we are going to create the files and folders that we will be using for this project run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; .dockerignore .env .gitignore docker-compose.yml
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
&lt;span class="nb"&gt;touch&lt;/span&gt; .env.local Dockerfile
&lt;span class="nb"&gt;cd &lt;/span&gt;src/app
&lt;span class="nb"&gt;mkdir &lt;/span&gt;account account/account account/rewards
&lt;span class="nb"&gt;mkdir &lt;/span&gt;api api/auth api/auth/&lt;span class="s2"&gt;"[...nextauth]"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;components delivery graphql queries utils
&lt;span class="nb"&gt;touch &lt;/span&gt;account/account/page.js account/account/page.module.css
&lt;span class="nb"&gt;touch &lt;/span&gt;account/rewards/page.js account/rewards/page.module.css
&lt;span class="nb"&gt;touch &lt;/span&gt;api/auth/&lt;span class="s2"&gt;"[...nextauth]"&lt;/span&gt;/route.js
&lt;span class="nb"&gt;touch &lt;/span&gt;components/MainMenu.js components/mainmenu.module.css components/Provider.js
&lt;span class="nb"&gt;touch &lt;/span&gt;delivery/page.js delivery/page.module.css
&lt;span class="nb"&gt;touch &lt;/span&gt;graphql/route.js
&lt;span class="nb"&gt;touch &lt;/span&gt;queries/clientQueries.js
&lt;span class="nb"&gt;touch &lt;/span&gt;utils/cors.js utils/withApollo.js
&lt;span class="nb"&gt;touch &lt;/span&gt;not-found.js page.module.css
&lt;span class="nb"&gt;cd&lt;/span&gt; ../../
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should now be in the root folder for &lt;code&gt;my-app&lt;/code&gt; so now we will install some packages for the project so run these commands here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @apollo/client @apollo/server @as-integrations/next graphql graphql-tag next-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With our basic setup done for our project, we can now focus on adding the code to our files which we will do now. This step can be tedious but we will be almost done afterwards this is the longest step. We will save the &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;.env.local&lt;/code&gt; files until last because they require some extra steps to be done first.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;store-project&lt;/code&gt; folder in your code editor and add this code to the &lt;code&gt;.dockerignore&lt;/code&gt; file and the &lt;code&gt;.gitignore&lt;/code&gt; file in the root folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.&lt;/span&gt;



&lt;span class="c"&gt;# dependencies&lt;/span&gt;

/node_modules

/.pnp

.pnp.js



&lt;span class="c"&gt;# testing&lt;/span&gt;

/coverage



&lt;span class="c"&gt;# next.js&lt;/span&gt;

/.next/

/out/



&lt;span class="c"&gt;# production&lt;/span&gt;

/build



&lt;span class="c"&gt;# misc&lt;/span&gt;

.DS_Store

&lt;span class="k"&gt;*&lt;/span&gt;.pem



&lt;span class="c"&gt;# debug&lt;/span&gt;

npm-debug.log&lt;span class="k"&gt;*&lt;/span&gt;

yarn-debug.log&lt;span class="k"&gt;*&lt;/span&gt;

yarn-error.log&lt;span class="k"&gt;*&lt;/span&gt;



&lt;span class="c"&gt;# local env files&lt;/span&gt;

.env&lt;span class="k"&gt;*&lt;/span&gt;.local



&lt;span class="c"&gt;# vercel&lt;/span&gt;

.vercel



&lt;span class="c"&gt;# typescript&lt;/span&gt;

&lt;span class="k"&gt;*&lt;/span&gt;.tsbuildinfo

next-env.d.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, add this code to the &lt;code&gt;docker-compose.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;my-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./my-app&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;NEXTAUTH_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${NEXTAUTH_URL}&lt;/span&gt;
      &lt;span class="na"&gt;NEXTAUTH_SECRET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${NEXTAUTH_SECRET}&lt;/span&gt;
      &lt;span class="na"&gt;GITHUB_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${GITHUB_ID}&lt;/span&gt;
      &lt;span class="na"&gt;GITHUB_SECRET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${GITHUB_SECRET}&lt;/span&gt;
      &lt;span class="na"&gt;GOOGLE_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${GOOGLE_ID}&lt;/span&gt;
      &lt;span class="na"&gt;GOOGLE_SECRET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${GOOGLE_SECRET}&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./my-app/src:/app/src&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./my-app/public:/app/public&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;3000:3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put this code in the &lt;code&gt;Dockerfile&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;FROM node:18-alpine

WORKDIR /app

&lt;span class="c"&gt;# Install dependencies based on the preferred package manager&lt;/span&gt;
COPY package.json yarn.lock&lt;span class="k"&gt;*&lt;/span&gt; package-lock.json&lt;span class="k"&gt;*&lt;/span&gt; pnpm-lock.yaml&lt;span class="k"&gt;*&lt;/span&gt; ./
RUN &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; yarn.lock &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;yarn &lt;span class="nt"&gt;--frozen-lockfile&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; package-lock.json &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;npm ci&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; pnpm-lock.yaml &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;yarn global add pnpm &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pnpm i&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="c"&gt;# Allow install without lockfile, so example works even without Node.js installed locally&lt;/span&gt;
  &lt;span class="k"&gt;else &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Warning: Lockfile not found. It is recommended to commit lockfiles to version control."&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn &lt;span class="nb"&gt;install&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;fi

&lt;/span&gt;COPY src ./src
COPY public ./public
COPY next.config.js &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Next.js collects completely anonymous telemetry data about general usage. Learn more here: https://nextjs.org/telemetry&lt;/span&gt;
&lt;span class="c"&gt;# Uncomment the following line to disable telemetry at run time&lt;/span&gt;
&lt;span class="c"&gt;# ENV NEXT_TELEMETRY_DISABLED 1&lt;/span&gt;

&lt;span class="c"&gt;# Note: Don't expose ports here, Compose will handle that for us&lt;/span&gt;

&lt;span class="c"&gt;# Start Next.js in development mode based on the preferred package manager&lt;/span&gt;
CMD &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; yarn.lock &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;yarn dev&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; package-lock.json &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;npm run dev&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; pnpm-lock.yaml &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;pnpm dev&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;else &lt;/span&gt;yarn dev&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will replace the code inside of &lt;code&gt;next.config.js&lt;/code&gt; with this so the app router feature is configured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @type {import('next').NextConfig} */&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;standalone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;experimental&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;appDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moving on let's do the files inside of the &lt;code&gt;src/app&lt;/code&gt; directory now. Add this to &lt;code&gt;account/account/page.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signOut&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-auth/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@apollo/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GET_ACCOUNT&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../queries/clientQueries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;withApollo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../utils/withApollo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MainMenu&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../components/MainMenu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./page.module.css&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;Account&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;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GET_ACCOUNT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSession&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;userEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;user&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;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;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Oh&lt;/span&gt; &lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;there&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt; &lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="nx"&gt;Please&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authenticated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signinflow&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;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Signed&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userEmail&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signinflowbtn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;Sign&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;
            &lt;span class="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;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;error&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;div&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&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;account&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;account&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;account&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;/h1&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="na"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;account&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;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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;country&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Giftcard&lt;/span&gt; &lt;span class="na"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;giftCardId&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&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="p"&gt;))}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;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;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signinflow&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signinflowbtn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;Sign&lt;/span&gt; &lt;span class="k"&gt;in&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="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;currently&lt;/span&gt; &lt;span class="nx"&gt;signed&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Sign&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
          &lt;span class="o"&gt;&amp;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="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;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;withApollo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put this in &lt;code&gt;account/account/page.module.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.signinflow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#131921&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.signinflowbtn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#febd69&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&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;For the rewards page add this to &lt;code&gt;account/rewards/page.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signOut&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-auth/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@apollo/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GET_REWARDS&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../queries/clientQueries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;withApollo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../utils/withApollo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MainMenu&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../components/MainMenu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./page.module.css&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;Rewards&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;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GET_REWARDS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSession&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;userEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;user&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;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;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Oh&lt;/span&gt; &lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;there&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt; &lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="nx"&gt;Please&lt;/span&gt; &lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authenticated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signinflow&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;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Signed&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userEmail&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signinflowbtn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;Sign&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;
            &lt;span class="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;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;error&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;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vouchercontainer&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rewards&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;vouchers&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;vouchers&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;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;voucher&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;vouchers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savingType&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="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;voucherdescription&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;vouchers&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="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;div&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;vouchers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&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;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Expiration&lt;/span&gt; &lt;span class="na"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&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="o"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="na"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                            &lt;span class="o"&gt;&amp;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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vouchercode&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                            &lt;span class="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;/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="p"&gt;))}&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                  &lt;span class="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;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="p"&gt;))}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="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;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signinflow&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signinflowbtn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;Sign&lt;/span&gt; &lt;span class="k"&gt;in&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="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;currently&lt;/span&gt; &lt;span class="nx"&gt;signed&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Sign&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;rewards&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="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;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;withApollo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Rewards&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This goes in &lt;code&gt;account/rewards/page.module.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.signinflow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#131921&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.signinflowbtn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#febd69&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.vouchercontainer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;flex-flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.voucher&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.voucherdescription&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;59&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;191&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;26&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.vouchercode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;191&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;26&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1500px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.vouchercontainer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="n"&gt;wrap&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 will add this code to &lt;code&gt;api/auth/[...nextauth]/route.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;GithubProvider&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-auth/providers/github&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;GoogleProvider&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-auth/providers/google&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NextAuth&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nc"&gt;GithubProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GITHUB_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GITHUB_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;

    &lt;span class="nc"&gt;GoogleProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GOOGLE_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GOOGLE_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;POST&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The components folder is next. Put this code in &lt;code&gt;components/MainMenu.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./mainmenu.module.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MainMenu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;nav&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mainmenu&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;Link&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&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;e&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&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;Link&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/delivery&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="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&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;Delivery&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&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;Link&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/account/rewards&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="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&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;Rewards&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&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;Link&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/account/account&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="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&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;Account&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&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;/nav&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;Remaining in the same folder this is for &lt;code&gt;components/mainmenu.module.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.mainmenu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#232f3e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;flex-flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;space-around&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.link&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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 this is going into &lt;code&gt;components/Provider.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SessionProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-auth/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;Provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SessionProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/SessionProvider&amp;gt;&lt;/span&gt;&lt;span class="err"&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;Provider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file inside of &lt;code&gt;delivery/page.js&lt;/code&gt; gets this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MainMenu&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/MainMenu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./page.module.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Nutrition&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Frequently&lt;/span&gt; &lt;span class="nx"&gt;Asked&lt;/span&gt; &lt;span class="nx"&gt;Questions&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;faqcontent&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;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;Is&lt;/span&gt; &lt;span class="nx"&gt;free&lt;/span&gt; &lt;span class="nx"&gt;shipping&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;purchases&lt;/span&gt; &lt;span class="nx"&gt;over&lt;/span&gt; &lt;span class="nx"&gt;$25&lt;/span&gt; &lt;span class="nx"&gt;available&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;products&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;/h2&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="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;Things&lt;/span&gt; &lt;span class="nx"&gt;sold&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;delivered&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;eligible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;things&lt;/span&gt;
            &lt;span class="nx"&gt;sold&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;marketplace&lt;/span&gt; &lt;span class="nx"&gt;sellers&lt;/span&gt; &lt;span class="nx"&gt;when&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;dispatcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt;
            &lt;span class="nx"&gt;combine&lt;/span&gt; &lt;span class="nx"&gt;qualifying&lt;/span&gt; &lt;span class="nx"&gt;goods&lt;/span&gt; &lt;span class="nx"&gt;worth&lt;/span&gt; &lt;span class="nx"&gt;less&lt;/span&gt; &lt;span class="nx"&gt;than&lt;/span&gt; &lt;span class="nx"&gt;$25&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;produce&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;
            &lt;span class="nx"&gt;worth&lt;/span&gt; &lt;span class="nx"&gt;more&lt;/span&gt; &lt;span class="nx"&gt;than&lt;/span&gt; &lt;span class="nx"&gt;$25&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;qualify&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;free&lt;/span&gt; &lt;span class="nx"&gt;delivery&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;faqcontent&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;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;How&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;I&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;pick&lt;/span&gt; &lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="nx"&gt;Hub&lt;/span&gt; &lt;span class="nx"&gt;Locker&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;Gateway&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;/h2&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="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;When&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;re all set to place your order, choose e-store Hub as your
            delivery address. We will send you an acknowledgement message with a
            barcode once your delivery arrives. Simply go to your chosen Locker
            or Gateway to pick up your package. Have your pickup message of
            confirmation with the barcode available when you arrive. You will
            scan the barcode yourself at the Locker; at the Gateway, the store
            clerk will check it before handing you your product. There is no
            need to provide identification while picking up.
          &amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/&amp;gt;
  );
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the CSS for &lt;code&gt;delivery/page.module.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.faqcontent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&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;Let's do our GraphQL route file with our data. Put this in &lt;code&gt;graphql/route.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApolloServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@apollo/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;startServerAndCreateNextHandler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@as-integrations/next&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;gql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;graphql-tag&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;allowCors&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../utils/cors&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;account&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="s1"&gt;r89fdjk23r89yew234fg89h23&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mark Thomas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;United States&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;giftCardId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;89dfviuhbbwerdfv897hwedfqdfqwf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`456 Maple Avenue, Austin, TX 78701`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rewards&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="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;savingType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Voucher&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="s1"&gt;Save $2 at checkout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;info&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;valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;89wdfeqwh89fewh98fh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;savingType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Voucher&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="s1"&gt;Save 20% at checkout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;info&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;valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;erfgerwgergewgewg345&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;savingType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Voucher&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="s1"&gt;Save 25% at checkout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;info&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;valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;34fg67werf45y45ytg0a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;savingType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Voucher&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="s1"&gt;Save 5% at checkout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;info&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;valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;er234dfrgdfsgerwerwge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;savingType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Voucher&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="s1"&gt;Save 50% at checkout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;info&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;valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gerwff4576jhey6233343&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Define the GraphQL schema and resolvers&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typeDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  type Rewards {
    id: String

    savingType: String

    description: String

    info: [Rewards]
  }

  type Rewards {
    valid: String

    code: String
  }

  type Account {
    id: String

    name: String

    country: String

    giftCardId: String

    address: String
  }

  type Query {
    rewards: [Rewards]

    account: [Account]
  }
`&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;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rewards&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;rewards&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Create the Apollo Server&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApolloServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;typeDefs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nx"&gt;resolvers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;startServerAndCreateNextHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;context&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;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;allowCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following that file we have this code with our GraphQL queries which goes in &lt;code&gt;queries/clientQueries.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@apollo/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GET_ACCOUNT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query {
    account {
      id
      name
      country
      giftCardId
      address
    }
  }
`&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;GET_REWARDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query {
    rewards {
      id
      savingType
      description
      info {
        valid
        code
      }
    }
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GET_ACCOUNT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GET_REWARDS&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Almost done just a few files remain. Now onto the utility files. Add this code to &lt;code&gt;utils/cors.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allowCors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Access-Control-Allow-Credentials&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Access-Control-Allow-Methods&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET,OPTIONS,PATCH,DELETE,POST,PUT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Access-Control-Allow-Headers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPTIONS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Now this code will go inside of &lt;code&gt;utils/withApollo.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApolloClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InMemoryCache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ApolloProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@apollo/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SessionProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-auth/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initializeApollo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_apolloClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApolloClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// Local GraphQL Endpoint&lt;/span&gt;

    &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// Add your Preevy GraphQL Endpoint&lt;/span&gt;

    &lt;span class="c1"&gt;// uri: 'https://yourapp.livecycle.run/graphql',&lt;/span&gt;

    &lt;span class="c1"&gt;// Add your Vercel GraphQL Endpoint&lt;/span&gt;

    &lt;span class="c1"&gt;// uri: 'https://yourapp.vercel.app/graphql',&lt;/span&gt;

    &lt;span class="c1"&gt;// Add your Netlify GraphQL Endpoint&lt;/span&gt;

    &lt;span class="c1"&gt;// uri: 'https://yourapp.netlify.app/graphql',&lt;/span&gt;

    &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InMemoryCache&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;restore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_apolloClient&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;function&lt;/span&gt; &lt;span class="nf"&gt;useApollo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;initializeApollo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;initialState&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;store&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;withApollo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PageComponent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WithApollo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;apolloClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;apolloState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useApollo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apolloState&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;SessionProvider&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ApolloProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;client&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;PageComponent&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&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;/ApolloProvider&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;/SessionProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// On the server&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;WithApollo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInitialProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&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;apolloClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initializeApollo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PageComponent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInitialProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;pageProps&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;PageComponent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInitialProps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;finished&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// When redirecting, the response is finished.&lt;/span&gt;

        &lt;span class="c1"&gt;// No point in continuing to render&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apolloState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;apolloClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="nx"&gt;apolloState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;WithApollo&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;Let's finish the last few files now. Replace all the CSS in &lt;code&gt;globals.css&lt;/code&gt; with this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;*,&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e3e6e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Istok Web'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;120rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&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;Replace the code in &lt;code&gt;layout.js&lt;/code&gt; with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./globals.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Istok_Web&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/font/google&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;istok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Istok_Web&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;subsets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;latin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;400&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;e-store App&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="s1"&gt;Generated by create next app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&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;body&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;istok&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/body&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/html&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This goes into &lt;code&gt;not-found.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MainMenu&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/MainMenu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="nx"&gt;Not&lt;/span&gt; &lt;span class="nx"&gt;Found&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;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;/&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;We will put this code in our homepage file which is the &lt;code&gt;page.js&lt;/code&gt; file in the &lt;code&gt;app&lt;/code&gt; folder so replace it with this code you see here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./page.module.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MainMenu&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/MainMenu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainMenu&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="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;container&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;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maincontent&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="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentbox&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Sony&lt;/span&gt; &lt;span class="nx"&gt;WH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="nx"&gt;XM5&lt;/span&gt; &lt;span class="nx"&gt;Noise&lt;/span&gt; &lt;span class="nx"&gt;Cancelling&lt;/span&gt; &lt;span class="nx"&gt;Wireless&lt;/span&gt; &lt;span class="nx"&gt;Headphones&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;For&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="nx"&gt;convenience&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;these&lt;/span&gt; &lt;span class="nx"&gt;Bluetooth&lt;/span&gt; &lt;span class="nx"&gt;headphones&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;paired&lt;/span&gt;
              &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;two&lt;/span&gt; &lt;span class="nx"&gt;devices&lt;/span&gt; &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;same&lt;/span&gt; &lt;span class="nx"&gt;time&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentbox&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;PlayStation&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="nx"&gt;Console&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;PS5&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt; &lt;span class="nx"&gt;unleashes&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;gaming&lt;/span&gt; &lt;span class="nx"&gt;possibilities&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;
              &lt;span class="nx"&gt;anticipated&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentbox&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Xbox&lt;/span&gt; &lt;span class="nx"&gt;Series&lt;/span&gt; &lt;span class="nx"&gt;X&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;Introducing&lt;/span&gt; &lt;span class="nx"&gt;Xbox&lt;/span&gt; &lt;span class="nx"&gt;Series&lt;/span&gt; &lt;span class="nx"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;fastest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;most&lt;/span&gt; &lt;span class="nx"&gt;powerful&lt;/span&gt; &lt;span class="nx"&gt;Xbox&lt;/span&gt; &lt;span class="nx"&gt;ever&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentbox&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;SanDisk&lt;/span&gt; &lt;span class="nx"&gt;Extreme&lt;/span&gt; &lt;span class="nx"&gt;Pro&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;TB&lt;/span&gt; &lt;span class="nx"&gt;Portable&lt;/span&gt; &lt;span class="nx"&gt;NVMe&lt;/span&gt; &lt;span class="nx"&gt;SSD&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;forged&lt;/span&gt; &lt;span class="nx"&gt;aluminum&lt;/span&gt; &lt;span class="nx"&gt;chassis&lt;/span&gt; &lt;span class="nx"&gt;acts&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;heat&lt;/span&gt; &lt;span class="nx"&gt;sink&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;deliver&lt;/span&gt; &lt;span class="nx"&gt;higher&lt;/span&gt;
              &lt;span class="nx"&gt;sustained&lt;/span&gt; &lt;span class="nx"&gt;speeds&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;portable&lt;/span&gt; &lt;span class="nx"&gt;drive&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="nx"&gt;tough&lt;/span&gt; &lt;span class="nx"&gt;enough&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;take&lt;/span&gt;
              &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="nx"&gt;adventure&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentbox&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Apple&lt;/span&gt; &lt;span class="mi"&gt;2023&lt;/span&gt; &lt;span class="nx"&gt;MacBook&lt;/span&gt; &lt;span class="nx"&gt;Pro&lt;/span&gt; &lt;span class="nx"&gt;laptop&lt;/span&gt; &lt;span class="nx"&gt;M2&lt;/span&gt; &lt;span class="nx"&gt;Pro&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Take&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;demanding&lt;/span&gt; &lt;span class="nx"&gt;projects&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;M2&lt;/span&gt; &lt;span class="nx"&gt;Pro&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;M2&lt;/span&gt; &lt;span class="nx"&gt;Max&lt;/span&gt; &lt;span class="nx"&gt;chip&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentbox&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Samsung&lt;/span&gt; &lt;span class="mi"&gt;43&lt;/span&gt; &lt;span class="nx"&gt;Inch&lt;/span&gt; &lt;span class="nx"&gt;BU8000&lt;/span&gt; &lt;span class="nx"&gt;UHD&lt;/span&gt; &lt;span class="nx"&gt;Crystal&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="nx"&gt;Smart&lt;/span&gt; &lt;span class="nx"&gt;TV&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;Immerse&lt;/span&gt; &lt;span class="nx"&gt;Yourself&lt;/span&gt; &lt;span class="nx"&gt;In&lt;/span&gt; &lt;span class="nx"&gt;Exceptional&lt;/span&gt; &lt;span class="nx"&gt;Colour&lt;/span&gt; &lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="nx"&gt;In&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Dynamic&lt;/span&gt; &lt;span class="nx"&gt;Crystal&lt;/span&gt;
              &lt;span class="nx"&gt;Colour&lt;/span&gt; &lt;span class="nx"&gt;delivers&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;UHD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;allowing&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;experience&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;
              &lt;span class="nx"&gt;billion&lt;/span&gt; &lt;span class="nx"&gt;shades&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;colour&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;lifelike&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;vivid&lt;/span&gt; &lt;span class="nx"&gt;picture&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="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/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;/&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;And lastly, this goes into the &lt;code&gt;page.module.css&lt;/code&gt; file in the &lt;code&gt;app&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.contentbox&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.maincontent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;flex-flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1500px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.maincontent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="n"&gt;wrap&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;Thats it! The main files are completed! It's time to deal with those ENV files now this is where we will set our environment variables so that we can get the authentication working on restricted routes. The account and rewards page will have an authentication layer on them.&lt;/p&gt;

&lt;h4&gt;
  
  
  Authentication setup
&lt;/h4&gt;

&lt;p&gt;Our application uses Auth.js for authentication. It's possible to have many different sign-in providers for your application. This app is set up to use GitHub and Google logins. You need an ID and secret key from GitHub and Google which we will then put in our ENV files. Read the documentation and find your ID and secrets. In my opinion, it is much easier to do it with GitHub and you only need one of them to work so that you can see the authentication working in the app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://authjs.dev/getting-started/oauth-tutorial" rel="noopener noreferrer"&gt;GitHub Auth setup&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developers.google.com/identity/protocols/oauth2" rel="noopener noreferrer"&gt;Google Auth setup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure that you pay attention to the Authorization callback URL. It will look different depending on where your app is running and you will need to update or change it on GitHub and Google otherwise the authenticated pages won't get access. See the examples below for GitHub:&lt;/p&gt;

&lt;p&gt;Localhost URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;http://localhost:3000/api/auth/callback/github
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Preevy URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://yourapp.livecycle.run/api/auth/callback/github
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vercel URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://yourapp.vercel.app/api/auth/callback/github
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you have your ID and secrets add them to both ENV files so &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;.env.local&lt;/code&gt;. We need two because one is for local development and the other is for production. Just copy the same code into both. See the example below and modify it with your ID and secrets.&lt;/p&gt;

&lt;p&gt;Just two more things to mention, we need a secret for our &lt;code&gt;NEXTAUTH_SECRET&lt;/code&gt; variable it can be anything you want. Just randomly generate a string of characters like you would for a secure password. The &lt;code&gt;NEXTAUTH_URL&lt;/code&gt; is required for Preevy deployments without it the authentication will go to localhost when it's deployed online which is incorrect and will stop the page loading.&lt;/p&gt;

&lt;p&gt;In some cases, we can get the authentication to work without having the &lt;code&gt;NEXTAUTH_URL&lt;/code&gt; variable in the ENV file altogether. But it will only work on localhost, Docker and Vercel so it's safer to just keep it in there. We have set &lt;code&gt;NEXTAUTH_URL&lt;/code&gt; to &lt;code&gt;http://localhost:3000/&lt;/code&gt; because that is where we will run our app first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;NEXTAUTH_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"yoursecret"&lt;/span&gt;

&lt;span class="nv"&gt;NEXTAUTH_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000/"&lt;/span&gt;

&lt;span class="nv"&gt;GITHUB_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"yourid"&lt;/span&gt;

&lt;span class="nv"&gt;GITHUB_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"yoursecret"&lt;/span&gt;

&lt;span class="nv"&gt;GOOGLE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"yourid"&lt;/span&gt;

&lt;span class="nv"&gt;GOOGLE_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"yoursecret"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;NEXTAUTH_URL&lt;/code&gt; variable will need to be changed depending on where our app is hosted and running.&lt;/p&gt;

&lt;p&gt;See the examples here:&lt;/p&gt;

&lt;p&gt;Localhost URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;NEXTAUTH_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Preevy URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;NEXTAUTH_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://yourapp.livecycle.run/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vercel URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;NEXTAUTH_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://yourapp.vercel.app/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything should be complete now so let's run our app.&lt;/p&gt;

&lt;h4&gt;
  
  
  Running our app locally
&lt;/h4&gt;

&lt;p&gt;To run our app locally go inside the &lt;code&gt;my-app&lt;/code&gt; folder and run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The GraphQL Apollo Server endpoint is here &lt;a href="http://localhost:3000/graphql" rel="noopener noreferrer"&gt;http://localhost:3000/graphql&lt;/a&gt; so we can test our GraphQL queries in development. We can also change this endpoint inside of the file in the directory &lt;code&gt;utils/withApollo.js&lt;/code&gt;. This becomes important when our app is online on Preevy and Vercel.&lt;/p&gt;

&lt;p&gt;To run our app inside of Docker first make sure Docker is running on your computer. Stop the other local development server from running first because you can't have two applications using port 3000. Then run this command inside of the &lt;code&gt;store-project&lt;/code&gt; root folder with the &lt;code&gt;docker-compose.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's see how to get it to work as a preview environment on Preevy.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating a preview build on Preevy
&lt;/h4&gt;

&lt;p&gt;You can follow the Preevy set-up in the &lt;a href="https://preevy.dev/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; and take a look at the &lt;a href="https://github.com/livecycle/preevy" rel="noopener noreferrer"&gt;Preevy GitHub&lt;/a&gt; for more setup instructions. In this tutorial, we are using AWS Lightsail as our cloud host. The main Preevy commands are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;preevy init

&lt;span class="c"&gt;## Add a flag and an id like 123&lt;/span&gt;
preevy up &lt;span class="nt"&gt;--id&lt;/span&gt; 123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure that you add an &lt;code&gt;id&lt;/code&gt; flag and a number afterwards otherwise, it could throw an error. Update the Authorization callback URL on GitHub and Google so it matches the Preevy URL that was generated and don't forget to change the &lt;code&gt;NEXTAUTH_URL&lt;/code&gt; variable in the ENV file to the generated Preevy URL like this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;NEXTAUTH_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://yourapp.livecycle.run/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also can change the GraphQL endpoint inside of the file in the directory &lt;code&gt;utils/withApollo.js&lt;/code&gt; to the URL endpoint for Preevy.&lt;/p&gt;

&lt;p&gt;Run the command &lt;code&gt;preevy up --id 123&lt;/code&gt; to push the latest changes again.&lt;/p&gt;

&lt;p&gt;We have done so much already it's now time to finish it off with deployment so let's work on that in the final section.&lt;/p&gt;

&lt;h4&gt;
  
  
  Deploying our app on Vercel
&lt;/h4&gt;

&lt;p&gt;The Vercel setup is pretty straightforward. Firstly create a repository on GitHub. I named mine &lt;strong&gt;store-project&lt;/strong&gt; and then run the GIT commands inside of the &lt;code&gt;my-app&lt;/code&gt; folder to push it to GitHub.&lt;/p&gt;

&lt;p&gt;See this GIT code example here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"first commit"&lt;/span&gt;
git branch &lt;span class="nt"&gt;-M&lt;/span&gt; main
git remote add origin https://github.com/replacewithyourname/store-project.git
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then sign into Vercel and Add a new project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46hexc0oocy3bettsi94.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46hexc0oocy3bettsi94.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687374709/vercel-add-new-project_ekykhm.jpg" width="800" height="686"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next import the repository you just created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkjqmosio8nfjysveiuu7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkjqmosio8nfjysveiuu7.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687374911/vercel-import-project_qjze5r.jpg" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next screen configure your project and there is an option for environment variables so add all the environment variables in the ENV file to Vercel and then hit the deploy button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdfgbpsurwy9x38clz7l.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdfgbpsurwy9x38clz7l.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687376186/vercel-env_hvseta.jpg" width="800" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our app should be live on Vercel! However, the authenticated routes won't work yet we have to make some updates to the code like before.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzvoqoz7bb91frda69z8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzvoqoz7bb91frda69z8.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687376380/vercel-congrats_gyoj90.jpg" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Update the Authorization callback URL on GitHub and Google so it matches the Vercel URL that was generated this is the first step to get the authenticated pages working.&lt;/p&gt;

&lt;p&gt;See the example here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Homepage URL&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://store-project-qwerty.vercel.app/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Authorization callback URL&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://store-project-qwerty.vercel.app/api/auth/callback/github
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, update the &lt;code&gt;NEXTAUTH_URL&lt;/code&gt; variable on Vercel to the URL that Vercel generated for your app. You will find it under Settings &amp;gt; Environment Variables see the image for reference.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1rjhuikf8hxrxd1wuk6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1rjhuikf8hxrxd1wuk6.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687377198/vercel-env-update_fauzx6.jpg" width="800" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And finally like before don't forget to also change the GraphQL endpoint inside of the file in the directory &lt;code&gt;utils/withApollo.js&lt;/code&gt; to the URL endpoint for Vercel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initializeApollo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_apolloClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApolloClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// Local GraphQL Endpoint&lt;/span&gt;

    &lt;span class="c1"&gt;// uri: 'http://localhost:3000/graphql',&lt;/span&gt;

    &lt;span class="c1"&gt;// Add your Preevy GraphQL Endpoint&lt;/span&gt;

    &lt;span class="c1"&gt;// uri: 'https://yourapp.livecycle.run/graphql',&lt;/span&gt;

    &lt;span class="c1"&gt;// Add your Vercel GraphQL Endpoint&lt;/span&gt;

    &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yourapp.vercel.app/graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// Add your Netlify GraphQL Endpoint&lt;/span&gt;

    &lt;span class="c1"&gt;// uri: 'https://yourapp.netlify.app/graphql',&lt;/span&gt;

    &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InMemoryCache&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;restore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_apolloClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now push the latest changes back to GitHub so that Vercel can rebuild your codebase with the new Vercel URL. Assuming you did everything correctly you should now see working authenticated routes for your app deployed on Vercel!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8riejz9ujqtvq5gferju.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8riejz9ujqtvq5gferju.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687377802/vercel-auth-route_uisj0x.jpg" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So with Vercel deployment complete let's do Netlify now.&lt;/p&gt;

&lt;h4&gt;
  
  
  Deploying our app on Netlify
&lt;/h4&gt;

&lt;p&gt;Sign into Netlify and then import an existing project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn81sxliaj8r37w9vp7sy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn81sxliaj8r37w9vp7sy.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687378959/netlify-project_w8xodt.jpg" width="678" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, connect to your GitHub and import the project you created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqtobrys7pq3tqene5yf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqtobrys7pq3tqene5yf.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687381475/netlify-import-project-git_v6mi56.jpg" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgs7x5hdky1838i14obzh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgs7x5hdky1838i14obzh.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687381524/netlify-pick-git_fgcqag.jpg" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once again add in those ENV variables and hit deploy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsr0f9dgknkm5lmqeefly.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsr0f9dgknkm5lmqeefly.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687382128/netlify-env_mid7ls.jpg" width="800" height="790"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And just like before our app should be live on Netlify! We have the same problem as before though, the authenticated routes won't work yet we have to make some updates to the code like the previous section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmlsez51hipoft36i9aqz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmlsez51hipoft36i9aqz.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687382469/netlify-online_vqbx1h.jpg" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Firstly like in the Vercel example update the Authorization callback URL on GitHub and Google so it matches the Netlify URL that was generated for your app. Next, update the &lt;code&gt;NEXTAUTH_URL&lt;/code&gt; variable on Netlify to the URL that Netlify generated for your app. You will find it under Site settings &amp;gt; Environment Variables see the image for reference.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpomcahc8ats6kb1w9mzo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpomcahc8ats6kb1w9mzo.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687382904/netlify-auth_irtvcf.jpg" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And just like we did before don't forget to also change the GraphQL endpoint inside of the file in the directory &lt;code&gt;utils/withApollo.js&lt;/code&gt; to the URL endpoint for Netlify.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initializeApollo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_apolloClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApolloClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// Local GraphQL Endpoint&lt;/span&gt;

    &lt;span class="c1"&gt;// uri: 'http://localhost:3000/graphql',&lt;/span&gt;

    &lt;span class="c1"&gt;// Add your Preevy GraphQL Endpoint&lt;/span&gt;

    &lt;span class="c1"&gt;// uri: 'https://yourapp.livecycle.run/graphql',&lt;/span&gt;

    &lt;span class="c1"&gt;// Add your Vercel GraphQL Endpoint&lt;/span&gt;

    &lt;span class="c1"&gt;// uri: 'https://yourapp.vercel.app/graphql',&lt;/span&gt;

    &lt;span class="c1"&gt;// Add your Netlify GraphQL Endpoint&lt;/span&gt;

    &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yourapp.netlify.app/graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InMemoryCache&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;restore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_apolloClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, push the latest changes back to GitHub so that Netlify can rebuild your codebase with the new Netlify URL.&lt;/p&gt;

&lt;p&gt;Assuming you did everything correctly you should now see working authenticated routes for your app deployed on Netlify!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the authenticated route goes to &lt;a href="http://localhost:3000/api/auth/callback/github" rel="noopener noreferrer"&gt;http://localhost:3000/api/auth/callback/github&lt;/a&gt; or &lt;a href="http://localhost:3000/api/auth/callback/google" rel="noopener noreferrer"&gt;http://localhost:3000/api/auth/callback/google&lt;/a&gt; then in the Deploys section on Netlify press the Trigger deploy button and select &lt;strong&gt;Clear cache and deploy site&lt;/strong&gt; and that should fix the error.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6btyw1oaacq9cv3s92b5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6btyw1oaacq9cv3s92b5.jpg" alt="https://res.cloudinary.com/d74fh3kw/image/upload/v1687385557/netlify-trigger-deploy_wgpyjc.jpg" width="742" height="348"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We are done! Our application is complete and we have a version deployed online on Vercel and Netlify good job! It might not be obvious but it's worth noting that the authentication part of our app will only work on Vercel or Netlify not both at the same time. We would have to duplicate the codebase and create a unique app for them on GitHub and Google to get them to work at the same time.&lt;/p&gt;

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

&lt;p&gt;To summarise, current web development is an ever-changing profession that necessitates a grasp and command of a variety of tools and technologies. The ones we've looked at in this article Next.js, Auth.js, databases, GraphQL, Docker, and Preevy aren't exhaustive, but they're nonetheless important in modern web development settings. Vercel and Netlify are some of the many serverless deployment platforms that make it easy for us to deploy our production applications online so that the world can access them.&lt;/p&gt;

&lt;p&gt;With its hybrid static and server rendering, Next.js provides a solid platform for developing scalable, high-performance apps. Auth.js simplifies the difficult work of user authentication, allowing developers to quickly add secure login features. Our database study revealed the need for organised data storage and retrieval, and GraphQL shone as an alternative to REST for developing flexible and efficient APIs. Docker, an essential technology for building isolated environments, is at the heart of today's software development and deployment cycle. Finally, Preevy, an emerging player in the pre-provisioning preview environment for static sites, can accelerate development build testing considerably.&lt;/p&gt;

&lt;p&gt;Each of these technologies has distinct advantages and applications. The true value of these tools, however, is in their combination, when utilised successfully together, these tools can allow developers to design extremely efficient, performant, secure, and scalable online applications. Mastering these technologies is no easy task it takes time, effort, and a lot of practice. However, the payoff is well worth the effort. By becoming proficient in these tools, you are not only providing yourself with the abilities required to flourish in the present web development scene, but you are also preparing yourself for the future as these technologies advance and influence the world of web development.&lt;/p&gt;

&lt;p&gt;So, keep researching, keep learning, and bear in mind that mastery in web development is a path of ongoing learning and adaptability.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
