<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Stormkit</title>
    <description>The latest articles on Forem by Stormkit (@stormkit).</description>
    <link>https://forem.com/stormkit</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%2F4373%2Ffee834b9-db55-4e79-85b2-55bdc71f4ad3.png</url>
      <title>Forem: Stormkit</title>
      <link>https://forem.com/stormkit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/stormkit"/>
    <language>en</language>
    <item>
      <title>Node.js Hosting: DIY Flexibility vs. Stormkit’s Streamlined Power</title>
      <dc:creator>Savas Vedova</dc:creator>
      <pubDate>Thu, 24 Jul 2025 13:51:54 +0000</pubDate>
      <link>https://forem.com/stormkit/nodejs-hosting-diy-flexibility-vs-stormkits-streamlined-power-5bkj</link>
      <guid>https://forem.com/stormkit/nodejs-hosting-diy-flexibility-vs-stormkits-streamlined-power-5bkj</guid>
      <description>&lt;p&gt;When it comes to hosting Node.js applications, you’re faced with a choice: build and manage your own infrastructure or use an orchestrator like &lt;a href="https://www.stormkit.io" rel="noopener noreferrer"&gt;Stormkit&lt;/a&gt;, purpose-built to scale and simplify, especially for managing multiple apps or hundreds of long-lived processes. While DIY hosting offers control, Stormkit’s feature set makes it a compelling choice for developers looking to optimize resources and streamline workflows. &lt;/p&gt;

&lt;p&gt;Let’s break down the trade-offs, highlighting Stormkit’s unique strengths and acknowledging the realities of self-hosting.&lt;/p&gt;

&lt;h2&gt;
  
  
  DIY Hosting: Control at a Cost
&lt;/h2&gt;

&lt;p&gt;Running your own Node.js setup, with a process manager like PM2, or systemd, gives you full control over your environment. For small projects or developers who enjoy fine-tuning servers, this can be a great fit. But as you scale to multiple apps or hundreds of processes, the DIY approach shows its limits.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scaling Complexity:&lt;/strong&gt; Managing traffic spikes across multiple apps means manually provisioning servers, setting up load balancers, and ensuring uptime. This can lead to over-provisioning, where you’re paying for idle servers, or under-provisioning, risking crashes during surges.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maintenance Burden:&lt;/strong&gt; You’re responsible for server updates, Node version upgrades, and monitoring resource usage. Juggling multiple apps amplifies this, as each may have different runtime or dependency needs, leading to configuration sprawl.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security Overhead:&lt;/strong&gt; Securing multiple apps requires configuring firewalls, SSL certificates, and staying vigilant about vulnerabilities. A single misstep can expose your apps, and keeping everything patched is a time sink.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deployment Friction:&lt;/strong&gt; Rolling out updates across multiple apps often involves manual restarts, risking downtime. Testing new versions or rolling back failed deployments can be clunky without a streamlined system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cost Inefficiency:&lt;/strong&gt; A small VPS is cheap, but scaling multiple apps across servers, plus adding redundancy and monitoring, drives up costs. Your time spent managing servers is another hidden expense.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DIY hosting is ideal for small, single-app projects or when you need highly specific configurations. If you’ve got the skills and time, it’s a hands-on way to learn and save on small-scale costs. But for managing multiple Node.js apps at scale, the overhead can pull you away from coding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stormkit: Optimized for Scale and Simplicity
&lt;/h2&gt;

&lt;p&gt;Stormkit is designed to handle Node.js applications at scale, especially when you’re managing multiple apps or long-lived processes. Its feature set addresses the pain points of DIY hosting, though self-hosting Stormkit means you still manage the underlying servers. Here’s why Stormkit stands out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource-Efficient Orchestration:&lt;/strong&gt; Stormkit’s on-demand spin-up and spin-down mechanism optimizes server usage. Instead of running multiple machines for each app, Stormkit orchestrates processes across fewer instances, dynamically allocating resources. What might take many servers in a traditional setup can often be handled with just a few, saving costs and reducing waste.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Insightful Analytics:&lt;/strong&gt; Stormkit provides a dashboard with stats on your most-visited and most-deployed apps. This quick overview helps you prioritize optimization and understand usage patterns, something DIY setups require custom tooling to achieve.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexible Runtime Management:&lt;/strong&gt; With Stormkit, you can manage Node runtimes via a .node-version file, supporting multiple versions across apps. This eliminates the hassle of manually installing and switching runtimes on servers, a common DIY headache.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seamless Deployments:&lt;/strong&gt; Deploying with Stormkit is as simple as a git push, with zero-downtime updates and instant rollbacks if something goes wrong. Each deployment gets a unique URL for testing, and you can add an auth wall to secure preview environments—features that require significant DIY effort to replicate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-Hosting Maintenance:&lt;/strong&gt; Since Stormkit is self-hosted, you’re responsible for maintaining the servers it runs on—patching the OS, monitoring hardware, and ensuring uptime. While Stormkit handles app-level orchestration, the server-level maintenance remains your responsibility.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Takeaway: Match Your Needs
&lt;/h2&gt;

&lt;p&gt;DIY hosting offers unparalleled control and is great for small projects or developers who love hands-on server work. It’s cost-effective for single apps and lets you tailor every detail, but scaling multiple apps or processes can lead to complexity, inefficiency, and maintenance overload.&lt;/p&gt;

&lt;p&gt;Stormkit flips this by streamlining orchestration, deployments, and runtime management, letting you achieve more with fewer servers. Its analytics, unique deployment URLs, and auth walls make managing multiple apps a breeze, though you’ll still need to handle server maintenance for self-hosting. If you’re focused on coding and scaling efficiently, Stormkit’s purpose-built features are a game-changer. If you have unique server needs or like to be hands-on, DIY might still be your path. &lt;/p&gt;

&lt;p&gt;Either way, keep your focus on building great apps 🚀&lt;/p&gt;

</description>
      <category>node</category>
      <category>devops</category>
      <category>cicd</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Hosting 300+ Websites - A Technical Deep Dive</title>
      <dc:creator>Savas Vedova</dc:creator>
      <pubDate>Wed, 21 May 2025 16:18:29 +0000</pubDate>
      <link>https://forem.com/stormkit/hosting-300-websites-a-technical-deep-dive-5248</link>
      <guid>https://forem.com/stormkit/hosting-300-websites-a-technical-deep-dive-5248</guid>
      <description>&lt;p&gt;It’s entirely feasible to host over 300 websites on a lean setup of just a few machines, and Stormkit makes it happen with a smart, scalable configuration. This post walks through the technical details how the infrastructure is set up, what it costs, how reliable it is, and what it takes to manage. Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure Setup
&lt;/h2&gt;

&lt;p&gt;The foundation is a compact yet powerful hardware and software stack designed to handle hundreds of sites efficiently. These websites generate millions of requests per month, so reliability is a core concern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardware
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Machines&lt;/strong&gt;: The production setup runs on 3 servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specs&lt;/strong&gt;: 2 vCPUs, 4 GiB RAM, SSD storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Provider&lt;/strong&gt;: Alibaba Cloud, chosen for its compliance with local regulations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;p&gt;To support the hosting environment, we’ve added a few key components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Network Load Balancer (NLB):&lt;/strong&gt; A Layer 4 load balancer ensures TLS termination happens at the source, enabling automatic TLS certificate issuance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis Instance:&lt;/strong&gt; A Tair Redis OSS-compatible instance handles caching, keeps TLS certificates and acts as a message queue for storing logs and analytics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL Database:&lt;/strong&gt; Apsara DB RDS provides a reliable and managed database solution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Staging Machine:&lt;/strong&gt; A single server mirrors the production environment for testing and experimentation, keeping costs minimal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Deployments
&lt;/h2&gt;

&lt;p&gt;Frequent deployments are a hallmark of modern development workflows. Here’s how we’ve streamlined the process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions Integration:&lt;/strong&gt; Instead of scaling up worker servers, we offload CI/CD pipelines to GitHub Actions, which integrates seamlessly with Stormkit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File Storage:&lt;/strong&gt; All static files are stored and served from Alibaba OSS (S3-compatible object storage), ensuring fast and reliable delivery.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Software Configuration
&lt;/h2&gt;

&lt;p&gt;Managing 300+ websites might sound daunting, but with the right tools, it’s surprisingly straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Monorepo Architecture:&lt;/strong&gt; All websites are managed in a single monorepo, simplifying code management and updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stormkit Snippets:&lt;/strong&gt; Each website is customized using Stormkit’s Snippets feature. Conditional rules based on &lt;code&gt;domain&lt;/code&gt; and &lt;code&gt;path&lt;/code&gt; allow for unique configurations, ensuring every site has its own look and functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Application, One Environment:&lt;/strong&gt; All domains are assigned to a single Stormkit environment, reducing complexity and overhead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Networking
&lt;/h2&gt;

&lt;p&gt;Since the client primarily serves regional customers, global distribution wasn’t a priority. All resources are hosted in a single region, optimizing for simplicity and cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Breakdown
&lt;/h2&gt;

&lt;p&gt;Here’s how the numbers stack up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Alibaba Cloud Resources:&lt;/strong&gt; 4 servers, 1 database, 1 Redis instance, 1 NLB and around 300GB file storage cost approximately &lt;strong&gt;$1000/month&lt;/strong&gt; with subscriptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployments:&lt;/strong&gt; GitHub Actions is included in the client’s paid tier, so there’s no additional cost for CI/CD.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stormkit Services:&lt;/strong&gt; $500/month for infrastructure setup, service updates, monitoring, feature development, enterprise features and direct Slack support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Total Monthly Cost:&lt;/strong&gt; Around &lt;strong&gt;$1500&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cost Per Website:&lt;/strong&gt; Roughly &lt;strong&gt;$5 per site&lt;/strong&gt;—a fraction of traditional hosting costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reliability and Downtime
&lt;/h2&gt;

&lt;p&gt;When hosting hundreds of websites, uptime is non-negotiable. Here’s how this setup performs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Downtime:&lt;/strong&gt; Virtually zero downtime over the last six months.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Usage:&lt;/strong&gt; Hosting machines maintain a CPU load of 0.8–1.9 and average memory consumption of 24%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency:&lt;/strong&gt; With Stormkit’s monorepo and API automation, updates roll out to all sites quickly, minimizing manual effort.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;This setup demonstrates that hosting 300+ websites doesn’t require a sprawling infrastructure or a massive budget. With the right tools, a lean team can manage a large-scale operation efficiently.&lt;/p&gt;

&lt;p&gt;Whether you’re managing a handful of sites or hundreds, this approach proves that scalability and cost-efficiency can go hand in hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Need Help with Your Infrastructure?
&lt;/h2&gt;

&lt;p&gt;If you’re looking to optimize your infrastructure or streamline your deployment process, Stormkit can help. Our platform supports deployments for JavaScript (frontend and backend), Go, and Rust applications, offering unparalleled flexibility and control.&lt;/p&gt;

&lt;p&gt;Contact us today to learn how Stormkit can transform your hosting and deployment workflows. &lt;a href="https://www.stormkit.io/enterprise" rel="noopener noreferrer"&gt;Get in touch with us&lt;/a&gt; for more details.&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>Migrating your app from Webpack to Vite</title>
      <dc:creator>Savas Vedova</dc:creator>
      <pubDate>Mon, 29 Aug 2022 09:49:00 +0000</pubDate>
      <link>https://forem.com/stormkit/migrating-stormkit-from-webpack-to-vite-5429</link>
      <guid>https://forem.com/stormkit/migrating-stormkit-from-webpack-to-vite-5429</guid>
      <description>&lt;p&gt;Hey all 👋&lt;/p&gt;

&lt;p&gt;I recently migrated &lt;a href="https://stormkit.io" rel="noopener noreferrer"&gt;Stormkit&lt;/a&gt; from Webpack to Vite and I wanted to share the changes because I had to follow a trial and error methodology to migrate it due to lack of documentation. &lt;/p&gt;

&lt;p&gt;For those who'd like to see directly the code, &lt;a href="https://github.com/stormkit-io/app-stormkit-io/pull/406/files#diff-6a3b01ba97829c9566ef2d8dc466ffcffb4bdac08706d3d6319e42e0aa6890dd" rel="noopener noreferrer"&gt;here are the changes&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;First thing you should know is that Vite uses &lt;code&gt;esbuild&lt;/code&gt; for development and &lt;code&gt;rollup&lt;/code&gt; for production. So while your development environment is working, your production build may fail. That was indeed the case for me and I'll explain in a moment why it happened. &lt;/p&gt;

&lt;p&gt;Let's take a look to the configuration options used in vite:&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;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite&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="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Although this is called root, &lt;/span&gt;
    &lt;span class="c1"&gt;// in our case this is "src", &lt;/span&gt;
    &lt;span class="c1"&gt;// where our application logic is located. &lt;/span&gt;
    &lt;span class="c1"&gt;// All configuration options defined &lt;/span&gt;
    &lt;span class="c1"&gt;// afterwards will be relative to this endpoint.&lt;/span&gt;
    &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// This is where our assets are served from. &lt;/span&gt;
    &lt;span class="c1"&gt;// In webpack, this was "output.publicPath".&lt;/span&gt;
    &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&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="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// This is similar to Webpack's DefinePlugin. &lt;/span&gt;
    &lt;span class="c1"&gt;// It is used to inject constants in your application.&lt;/span&gt;
    &lt;span class="na"&gt;define&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="c1"&gt;// Using the following configuration made our build fail as &lt;/span&gt;
        &lt;span class="c1"&gt;// mentioned above. I had to change a couple of `global` usages &lt;/span&gt;
        &lt;span class="c1"&gt;// and remove this configuration to make them work.&lt;/span&gt;
        &lt;span class="c1"&gt;// global: { }&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nl"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// We need https for various 3rd party tools used &lt;/span&gt;
      &lt;span class="c1"&gt;// in local environment. It is similar to &lt;/span&gt;
      &lt;span class="c1"&gt;// Webpack Dev Server's 'server: "https"' config.&lt;/span&gt;
      &lt;span class="c1"&gt;// We require a certificate for this to work and that is &lt;/span&gt;
      &lt;span class="c1"&gt;// achieved through the 'basicSsl' plugin.&lt;/span&gt;
      &lt;span class="c1"&gt;// You can check the actual code to see which package is that.&lt;/span&gt;
      &lt;span class="na"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="c1"&gt;// We are proxying all requests from `/api` to our api server. &lt;/span&gt;
      &lt;span class="c1"&gt;// This config is very similar to Webpack Dev Server's proxy config. &lt;/span&gt;
      &lt;span class="na"&gt;proxy&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;// This is almost equivalent to Webpack's "resolve" config. &lt;/span&gt;
  &lt;span class="c1"&gt;// It is used to import files using aliases.&lt;/span&gt;
  &lt;span class="na"&gt;resolve&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;// Assets under this folder will be copied to the dist folder. &lt;/span&gt;
  &lt;span class="c1"&gt;// We used to achieve the same functionality using &lt;/span&gt;
  &lt;span class="c1"&gt;// the "copy-webpack-plugin" package.&lt;/span&gt;
  &lt;span class="c1"&gt;// Do not forget that this is relative to the "root" path configured above.&lt;/span&gt;
  &lt;span class="na"&gt;publicDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./public&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// List of plugins used to make various technologies work.&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="c1"&gt;// used to add https to local environment&lt;/span&gt;
     &lt;span class="nf"&gt;basicSsl&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
     &lt;span class="c1"&gt;// used to include our bundles inside the html file&lt;/span&gt;
     &lt;span class="nf"&gt;createHtmlPlugin&lt;/span&gt;&lt;span class="p"&gt;({}),&lt;/span&gt;
     &lt;span class="c1"&gt;// used to import svgs&lt;/span&gt;
     &lt;span class="nf"&gt;svgr&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
     &lt;span class="c1"&gt;// used to make react work with vite&lt;/span&gt;
     &lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Specify the dist folder&lt;/span&gt;
    &lt;span class="na"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// Loading a file was failing and adding this configuration&lt;/span&gt;
  &lt;span class="c1"&gt;// fixed it. It basically replaces top-level "this" usage&lt;/span&gt;
  &lt;span class="c1"&gt;// with the "window" object.&lt;/span&gt;
  &lt;span class="na"&gt;esbuild&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;define&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;this&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;window&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We do use Tailwind and Material UI in our project. A simple &lt;code&gt;postcss.config.js&lt;/code&gt; was all that I needed to make Tailwind work properly:&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tailwindcss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;autoprefixer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The rationale behind the migration
&lt;/h2&gt;

&lt;p&gt;This definitely adds no direct value for the end user. So why did we migrate? &lt;/p&gt;

&lt;p&gt;The main reason is because we'll make a lot of changes to the frontend soon as we're releasing a V2 for Stormkit. When I realised that the HMR was broken and I heard that Vite is extremely fast for development I decided to give it a try. Turns out, this was a pretty good decision and it will also add value to the end user because it'll increase our development speed. &lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The build time seems to be a bit slower than our previous configuration. This is mainly because we used to use &lt;code&gt;esbuild&lt;/code&gt;, which is extremely fast, for production builds but &lt;code&gt;vite&lt;/code&gt; uses &lt;code&gt;rollup&lt;/code&gt;. However, to be honest, given the increase in the HMR, we're willing to sacrifice a few seconds during production builds. &lt;/li&gt;
&lt;li&gt;Whereas the HMR is extremely fast. When I make a change in the UI and switch to the browser to visualize it, I used to wait a few seconds till those changes were propagated. Now, by the time I switch the Browser tab, the changes are already there. This is fantastic! &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hope this mini tutorial was helpful to understand what is needed to migrate from Webpack to Vite. Stormkit is can be considered as a large application and the migration was possible through 1 PR with almost no breaking changes. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; This article is also published on our &lt;a href="https://www.stormkit.io/blog/migrating-your-app-from-webpack-to-vite" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to build an ECommerce App with React</title>
      <dc:creator>Ashutosh Kumar Singh</dc:creator>
      <pubDate>Thu, 01 Jul 2021 17:05:16 +0000</pubDate>
      <link>https://forem.com/stormkit/how-to-build-an-ecommerce-app-with-react-27fe</link>
      <guid>https://forem.com/stormkit/how-to-build-an-ecommerce-app-with-react-27fe</guid>
      <description>&lt;p&gt;In this tutorial, we will build an E-commerce App with &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; using &lt;a href="https://buttercms.com/" rel="noopener noreferrer"&gt;ButterCMS&lt;/a&gt; and &lt;a href="https://snipcart.com/" rel="noopener noreferrer"&gt;Snipcart&lt;/a&gt;. We will use &lt;a href="https://chakra-ui.com/" rel="noopener noreferrer"&gt;Chakra UI&lt;/a&gt;, a modular and accessible component library, to style the app. &lt;br&gt;
Finally, we will deploy our ecommerce app with &lt;a href="https://www.stormkit.io/" rel="noopener noreferrer"&gt;Stormkit&lt;/a&gt;, a serverless deployment service for JavaScript apps similar to Vercel or Netlify.&lt;/p&gt;

&lt;p&gt;If you want to jump right into the code, check out the &lt;a href="https://github.com/lelouchB/react-ecommerce-butter" rel="noopener noreferrer"&gt;GitHub Repo here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And here's a link to the deployed version: &lt;a href="https://yakscythe-49dgnn.stormkit.dev/" rel="noopener noreferrer"&gt;https://yakscythe-49dgnn.stormkit.dev/&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Knowledge of HTML, CSS &amp;amp; JavaScript&lt;/li&gt;
&lt;li&gt;Basic knowledge of &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Node &amp;amp; NPM installed on the local development machine.&lt;/li&gt;
&lt;li&gt;Any code editor of your choice.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en" rel="noopener noreferrer"&gt;React Dev Tools&lt;/a&gt; (optional)&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://buttercms.com/" rel="noopener noreferrer"&gt;Butter CMS Account&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://app.snipcart.com/register" rel="noopener noreferrer"&gt;Snipcart Account&lt;/a&gt; (free forever in test mode)&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://www.stormkit.io/" rel="noopener noreferrer"&gt;Stormkit Account&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What is ButterCMS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://buttercms.com/" rel="noopener noreferrer"&gt;ButterCMS&lt;/a&gt; is a SaaS start-up that delivers value to Developers and Marketers through a &lt;a href="https://buttercms.com/blog/what-is-headless-cms" rel="noopener noreferrer"&gt;headless, API-based CMS (Content Management System)&lt;/a&gt; and blogging platform. Butter is a developer-friendly CMS that enables developers to build modern apps while also providing their marketing teams with the tools needed to make website content updates. &lt;/p&gt;
&lt;h2&gt;
  
  
  What is Snipcart
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://snipcart.com/" rel="noopener noreferrer"&gt;Snipcart&lt;/a&gt; is HTML based fully customizable shopping cart that you can integrate with any web stack in few simple steps and start accepting international payments in minutes. With Snipcart's management dashboard, you can track abandoned carts, sales, orders, customers, and more.&lt;/p&gt;

&lt;p&gt;Snipcart works perfectly with Headless CMS like Butter and speeds up your development process, provides better security, and functionality to your ecommerce app.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Stormkit
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.stormkit.io/" rel="noopener noreferrer"&gt;Stormkit&lt;/a&gt; is a serverless hosting and deployment service for JavaScript applications. It enables you to focus on developing your application instead of wasting time by automating deployments, logs, hosting, scaling, TLS certificates and much more with state of the art best practices and features like &lt;a href="https://www.stormkit.io/docs/features/multiple-environments" rel="noopener noreferrer"&gt;multiple environments&lt;/a&gt;, &lt;a href="https://www.stormkit.io/docs/features/staged-rollouts" rel="noopener noreferrer"&gt;staged rollouts&lt;/a&gt;, &lt;a href="https://www.stormkit.io/docs/features/remote-config" rel="noopener noreferrer"&gt;remote Config&lt;/a&gt; and &lt;a href="https://www.stormkit.io/docs/features/snippets" rel="noopener noreferrer"&gt;snippets&lt;/a&gt;. This makes Stormkit something like a low-code frontend infrastructure service for developers.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to Setup and Install React
&lt;/h2&gt;

&lt;p&gt;In this tutorial, you will use Create React App template to quickly create the initial React app. Run the following command in the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-react-app react-ecommerce-butter
&lt;span class="nb"&gt;cd &lt;/span&gt;react-ecommerce-butter
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last command, &lt;code&gt;npm start&lt;/code&gt;, will start the React development server on your system's port 3000.  Head over to &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt; in your browser to view your React app.&lt;/p&gt;

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

&lt;p&gt;You can stop the development server by hitting &lt;strong&gt;CTRL+C&lt;/strong&gt; in the terminal. &lt;/p&gt;

&lt;p&gt;In this tutorial, you will use Chakra UI to style your ecommerce app. Run the following command to install Chakra UI.&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 @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4 react-icons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update &lt;code&gt;src/index.js&lt;/code&gt; to wrap your react app with the &lt;code&gt;ChakraProvider&lt;/code&gt; component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.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;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App&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;reportWebVitals&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./reportWebVitals&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;ChakraProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@chakra-ui/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChakraProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ChakraProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;reportWebVitals&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file to store ButterCMS and Snipcart API keys securely as environment variables. Run the following command to create the &lt;code&gt;.env&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;&lt;span class="nb"&gt;touch&lt;/span&gt; .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to create a &lt;a href="https://buttercms.com/" rel="noopener noreferrer"&gt;free ButterCMS account&lt;/a&gt;. After creating an account, head over to &lt;a href="https://buttercms.com/settings/" rel="noopener noreferrer"&gt;https://buttercms.com/settings/&lt;/a&gt; and copy the &lt;strong&gt;Read API Token&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;Navigate to &lt;a href="https://app.snipcart.com/register" rel="noopener noreferrer"&gt;https://app.snipcart.com/register&lt;/a&gt; in your browser and create a free Snipcart account if you haven't already.&lt;/p&gt;

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

&lt;p&gt;After creating the Snipcart account, head over to &lt;a href="https://app.snipcart.com/?ReturnUrl=%2fdashboard%2faccount%2fcredentials" rel="noopener noreferrer"&gt;account settings&lt;/a&gt; and copy the &lt;strong&gt;PUBLIC TEST API KEY&lt;/strong&gt; under Credentials.&lt;/p&gt;

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

&lt;p&gt;Paste both Butter CMS API Key and Snipcart Public Test API Key in the &lt;code&gt;.env&lt;/code&gt; file as shown below.&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;REACT_APP_BUTTER_ECOMMERCE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="nv"&gt;REACT_APP_SNIPCART_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How To Create Products on Butter
&lt;/h2&gt;

&lt;p&gt;In this section, you will create the products for your ecommerce app on Butter. In this tutorial, you will create an ecommerce platform named &lt;strong&gt;Cookie Jar&lt;/strong&gt;, where customers can buy different varieties of cookies. Hence, the products for this ecommerce platform will be &lt;strong&gt;cookies&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Navigate to your &lt;a href="https://buttercms.com/content/collections/" rel="noopener noreferrer"&gt;Butter Dashboard&lt;/a&gt; and then create a new collection named &lt;strong&gt;cookies&lt;/strong&gt; with the following fields. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt; - Type: &lt;code&gt;Number&lt;/code&gt; - &lt;code&gt;isRequired&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; - Type: &lt;code&gt;Short Text&lt;/code&gt; - &lt;code&gt;isRequired&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt; - Type: &lt;code&gt;Long Text&lt;/code&gt; - &lt;code&gt;isRequired&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;price&lt;/code&gt; - Type: &lt;code&gt;Number&lt;/code&gt; - &lt;code&gt;isRequired&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;image&lt;/code&gt; - Type: &lt;code&gt;Media&lt;/code&gt; - &lt;code&gt;isRequired&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can create an ecommerce app on any product like shoes, sports stuff, craft, etc. You can add additional fields like ratings, reviews, stock, etc., to your ecommerce app, but these are the bare minimum required for any ecommerce app.&lt;/p&gt;

&lt;p&gt;You can add the fields by dragging and dropping the corresponding field types.&lt;/p&gt;

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

&lt;p&gt;After adding the fields, click on the &lt;strong&gt;Create Collection&lt;/strong&gt; button, name the collection &lt;code&gt;cookies&lt;/code&gt;, and hit &lt;strong&gt;Save as a Collection&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;You will also need to add some dummy data to the &lt;code&gt;cookies&lt;/code&gt; collection. You can either copy the dummy data from &lt;a href="https://yakscythe-49dgnn.stormkit.dev/" rel="noopener noreferrer"&gt;https://yakscythe-49dgnn.stormkit.dev/&lt;/a&gt; or add your favorite cookies.&lt;/p&gt;

&lt;p&gt;Make sure to hit &lt;strong&gt;Publish&lt;/strong&gt; after adding the cookies, aka products. You can come back and add more products or edit them whenever you want.&lt;/p&gt;

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

&lt;p&gt;Here is how your &lt;code&gt;cookies&lt;/code&gt; collection will look after adding products to it.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  How To Fetch and Display Products
&lt;/h2&gt;

&lt;p&gt;In this section, you will fetch the data  from Butter CMS and display them as products on your ecommerce app. &lt;/p&gt;

&lt;p&gt;You will use the &lt;code&gt;buttercms&lt;/code&gt; library to fetch data from ButterCMS. Run the following command in your project's root directory to install &lt;code&gt;buttercms&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Update &lt;code&gt;App.js&lt;/code&gt; file with the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Butter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buttercms&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;butter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Butter&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;REACT_APP_BUTTER_ECOMMERCE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchData&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;res&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;butter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cookies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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="kd"&gt;const&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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;allProducts&lt;/span&gt; &lt;span class="o"&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;cookies&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allProducts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;fetchData&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;products&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;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="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;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, you start by creating an instance of &lt;code&gt;Butter&lt;/code&gt; using your ButterCMS API key stored in &lt;code&gt;.env&lt;/code&gt; file and accessed using &lt;code&gt;process.env.REACT_APP_BUTTER_ECOMMERCE&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Then you create a state named &lt;code&gt;products&lt;/code&gt; to store the data fetched from ButterCMS using the &lt;code&gt;useState()&lt;/code&gt; hook. Hooks are functions that use React features like defining a state without writing a class.&lt;/p&gt;

&lt;p&gt;You fetch the collection named &lt;code&gt;cookies&lt;/code&gt; using butter's &lt;code&gt;.retrieve()&lt;/code&gt; method inside the React's &lt;code&gt;useEffect()&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;You then access the response from ButterCMS and store it inside the &lt;code&gt;products&lt;/code&gt; state using the &lt;code&gt;setProducts()&lt;/code&gt; method. Here is how the state &lt;code&gt;products&lt;/code&gt; look like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;125151&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Biscotti Cookies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Biscotti actually means “twice baked” and the cookie is indeed baked twice, resulting in its hard and crunchy texture."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://cdn.buttercms.com/UqbFGAJLTGqtYqF2UajV"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;113778&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Chocolate Chip Cookies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Chocolate chip cookies are the perennial classic and longtime fan favorite. "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://cdn.buttercms.com/Xe1zfNvRCiOOI4LPuoVb"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To display the product's data, you iterate over the &lt;code&gt;products&lt;/code&gt; state using the &lt;code&gt;.map()&lt;/code&gt; method and display the data on the page using curly brackets &lt;code&gt;{}&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;products&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;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Head over to &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;. Here is how your ecommerce app will look like.&lt;/p&gt;

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

&lt;p&gt;Though your app needs styling, but you are getting all the required data from ButterCMS successfully. Now, you will use Chakra UI to style the app. Update &lt;code&gt;App.js&lt;/code&gt; with Chakra UI components to style your ecommerce app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Divider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SimpleGrid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Flex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@chakra-ui/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;FiShoppingCart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FiShoppingBag&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-icons/fi&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;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Butter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buttercms&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;butter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Butter&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;REACT_APP_BUTTER_ECOMMERCE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchData&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;res&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;butter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cookies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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="kd"&gt;const&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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;allProducts&lt;/span&gt; &lt;span class="o"&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;cookies&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allProducts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;fetchData&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt; &lt;span class="na"&gt;maxW&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container.xl"&lt;/span&gt; &lt;span class="na"&gt;h&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"100vh"&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Flex&lt;/span&gt; &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"space-between"&lt;/span&gt; &lt;span class="na"&gt;alignContent&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;
          &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;
          &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;
          &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2rem"&lt;/span&gt;
          &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"gray.900"&lt;/span&gt;
          &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Robo"&lt;/span&gt;
          &lt;span class="na"&gt;my&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"5px"&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Cookie Jar
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
          &lt;span class="na"&gt;my&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"5px"&lt;/span&gt;
          &lt;span class="na"&gt;colorScheme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"green"&lt;/span&gt;
          &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ghost"&lt;/span&gt;
          &lt;span class="na"&gt;leftIcon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FiShoppingBag&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"24px"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lg"&lt;/span&gt;
          &lt;span class="na"&gt;p&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          View Cart
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Flex&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Divider&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt; &lt;span class="na"&gt;mt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SimpleGrid&lt;/span&gt;
          &lt;span class="na"&gt;minChildWidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"300px"&lt;/span&gt;
          &lt;span class="na"&gt;align&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;
          &lt;span class="na"&gt;justify&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;
          &lt;span class="na"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"40px"&lt;/span&gt;
          &lt;span class="na"&gt;mb&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;products&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;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;
              &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt;
              &lt;span class="na"&gt;maxW&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"sm"&lt;/span&gt;
              &lt;span class="na"&gt;borderWidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1px"&lt;/span&gt;
              &lt;span class="na"&gt;rounded&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lg"&lt;/span&gt;
              &lt;span class="na"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lg"&lt;/span&gt;
              &lt;span class="na"&gt;_hover&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark-lg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt;
                &lt;span class="na"&gt;h&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"350px"&lt;/span&gt;
                &lt;span class="na"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"cover"&lt;/span&gt;
                &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`Picture of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;roundedTop&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lg"&lt;/span&gt;
              &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt; &lt;span class="na"&gt;p&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"6"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Flex&lt;/span&gt;
                  &lt;span class="na"&gt;mt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
                  &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"space-between"&lt;/span&gt;
                  &lt;span class="na"&gt;alignContent&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;
                &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;
                    &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2xl"&lt;/span&gt;
                    &lt;span class="na"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"semibold"&lt;/span&gt;
                    &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h4"&lt;/span&gt;
                    &lt;span class="na"&gt;textTransform&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"uppercase"&lt;/span&gt;
                    &lt;span class="na"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"tight"&lt;/span&gt;
                    &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Roboto"&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;
                    &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h4"&lt;/span&gt;
                    &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2xl"&lt;/span&gt;
                    &lt;span class="na"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bold"&lt;/span&gt;
                    &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"teal.600"&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    $&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Flex&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;
                  &lt;span class="na"&gt;mt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"gray.500"&lt;/span&gt;
                  &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
                  &lt;span class="na"&gt;leftIcon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FiShoppingCart&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"24px"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lg"&lt;/span&gt;
                  &lt;span class="na"&gt;mt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                  &lt;span class="na"&gt;isFullWidth&lt;/span&gt;
                  &lt;span class="na"&gt;colorScheme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt;
                  &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"outline"&lt;/span&gt;
                  &lt;span class="na"&gt;alignSelf&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

                &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  Add to Cart
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SimpleGrid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the above code, you import different Chakra UI components like &lt;code&gt;Container&lt;/code&gt;, &lt;code&gt;Flex&lt;/code&gt;, etc., and use them to style your app. Except for styling, the code used to fetch and display the data on the app remains the same.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will not discuss how these components are used in-depth; you can refer to &lt;a href="https://chakra-ui.com/docs/getting-started" rel="noopener noreferrer"&gt;official Chakra UI docs&lt;/a&gt; to learn more about these components.&lt;/p&gt;

&lt;p&gt;Here is how your app will look.&lt;/p&gt;

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

&lt;p&gt;You have created two buttons in the above code, &lt;code&gt;View Cart&lt;/code&gt;, which shows users their cart, and &lt;code&gt;Add to Cart&lt;/code&gt;, which adds the product to the cart. These buttons don't work yet; you will integrate them with Snipcart in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  How To Integrate Snipcart With React App
&lt;/h2&gt;

&lt;p&gt;In this section, you will configure and integrate Snipcart with your ecommerce app. &lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;public/index.html&lt;/code&gt; file and add the following code inside the &lt;code&gt;&amp;lt;Head&amp;gt;&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preconnect"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://app.snipcart.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preconnect"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.snipcart.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.snipcart.com/themes/v3.2.0/default/snipcart.css"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, add the following code in &lt;code&gt;public/index.html&lt;/code&gt; before closing &lt;code&gt;&amp;lt;Body&amp;gt;&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script
  &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.snipcart.com/themes/v3.2.0/default/snipcart.js"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
  &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"snipcart"&lt;/span&gt;
  &lt;span class="na"&gt;data-config-modal-style=&lt;/span&gt;&lt;span class="s"&gt;"side"&lt;/span&gt;
  &lt;span class="na"&gt;data-api-key=&lt;/span&gt;&lt;span class="s"&gt;"%REACT_APP_SNIPCART_KEY%"&lt;/span&gt;
  &lt;span class="na"&gt;hidden&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Snipcart API Key stored in &lt;code&gt;.env&lt;/code&gt; file is being accessed in the above code using &lt;code&gt;%REACT_APP_SNIPCART_KEY%&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;Add to Cart&lt;/code&gt; button in &lt;code&gt;src/App.js&lt;/code&gt; like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
  &lt;span class="na"&gt;leftIcon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FiShoppingCart&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"24px"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lg"&lt;/span&gt;
  &lt;span class="na"&gt;mt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;isFullWidth&lt;/span&gt;
  &lt;span class="na"&gt;colorScheme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt;
  &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"outline"&lt;/span&gt;
  &lt;span class="na"&gt;alignSelf&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"snipcart-add-item"&lt;/span&gt;
  &lt;span class="na"&gt;data-item-id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;data-item-image&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;data-item-name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;data-item-url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;
  &lt;span class="na"&gt;data-item-description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;data-item-price&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Add to Cart
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, you pass the data required by Snipcart, like the product's name, id, description, etc.&lt;/p&gt;

&lt;p&gt;Here is the &lt;code&gt;Add to Cart&lt;/code&gt; button in action.&lt;/p&gt;

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

&lt;p&gt;Finally, update the &lt;code&gt;View Cart&lt;/code&gt; button like with &lt;code&gt;className="snipcart-checkout"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
  &lt;span class="na"&gt;my&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"5px"&lt;/span&gt;
  &lt;span class="na"&gt;colorScheme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"green"&lt;/span&gt;
  &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ghost"&lt;/span&gt;
  &lt;span class="na"&gt;leftIcon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FiShoppingBag&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"24px"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lg"&lt;/span&gt;
  &lt;span class="na"&gt;p&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"snipcart-checkout"&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  View Cart
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This button will show the current items in the cart to the user.&lt;/p&gt;

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

&lt;p&gt;Run the following commands in the terminal to commit your code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;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;"Finished building the React Ecommerce app"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Deploy your Ecommerce App with Stormkit
&lt;/h2&gt;

&lt;p&gt;In this section, you will deploy the ecommerce app with the free tier of Stormkit. &lt;/p&gt;

&lt;p&gt;The first step is to push your code to a GitHub repository. Create an account on &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;https://github.com/&lt;/a&gt; if you haven't already.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feguo833m8dx9gm0ctp8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feguo833m8dx9gm0ctp8c.png" alt="Create an account on GitHub"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to &lt;a href="https://github.com/new" rel="noopener noreferrer"&gt;https://github.com/new&lt;/a&gt; and create a new GitHub repo with &lt;code&gt;react-ecommerce-butter&lt;/code&gt; as the repo name. You can skip other fields for now. Finally, click on the &lt;code&gt;Create repository&lt;/code&gt; button.&lt;/p&gt;

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

&lt;p&gt;On the next page, you will be provided with the code to push your code to GitHub. Copy the commands from the second section, i.e., &lt;code&gt;...or push an existing repository from the command line&lt;/code&gt; section.&lt;/p&gt;

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

&lt;p&gt;The commands will be similar to this but will contain your GitHub username.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add origin https://github.com/lelouchB/react-ecommerce-butter.git
git branch &lt;span class="nt"&gt;-M&lt;/span&gt; main
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;The last command will push your code to GitHub. Head over to &lt;a href="https://app.stormkit.io/auth" rel="noopener noreferrer"&gt;https://app.stormkit.io/auth&lt;/a&gt; and login using GitHub OAuth.&lt;/p&gt;

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

&lt;p&gt;Click on the GitHub icon under &lt;strong&gt;Where can we find your codebase?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4g8s8icwj47dne1ph45.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4g8s8icwj47dne1ph45.png" alt="Where can we find your codebase?"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be asked to connect your repositories with Stormkit. You can choose to connect all your repositories or select only the &lt;code&gt;react-ecommerce-butter&lt;/code&gt; repo. &lt;/p&gt;

&lt;p&gt;Select the &lt;code&gt;react-ecommerce-butter&lt;/code&gt; repository and proceed further.&lt;/p&gt;

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

&lt;p&gt;You will be redirected to your Stormkit dashboard, where your newly connected app would appear. Select the app you want to deploy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogjgpg4nz6q2fbonps22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogjgpg4nz6q2fbonps22.png" alt="Stormkit Dashboard with New App"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On your app dashboard, you will be provided with a default &lt;code&gt;production&lt;/code&gt; environment. You can create as many environments as you want. In this tutorial, we will deploy using the default &lt;code&gt;production&lt;/code&gt; environment.&lt;/p&gt;

&lt;p&gt;Before deploying, you will need to set the environment variables in your &lt;code&gt;production&lt;/code&gt; environment; else your deployment will fail. &lt;/p&gt;

&lt;p&gt;Click on the &lt;code&gt;production&lt;/code&gt; environment.&lt;/p&gt;

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

&lt;p&gt;Now, click on the &lt;code&gt;Edit&lt;/code&gt; button or the pencil icon to edit the environment configurations.&lt;/p&gt;

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

&lt;p&gt;A modal will appear with current environment configurations.&lt;/p&gt;

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

&lt;p&gt;Scroll to the bottom of the modal; you will see the &lt;strong&gt;Build configuration&lt;/strong&gt; and &lt;strong&gt;Environment variables&lt;/strong&gt; sections. &lt;/p&gt;

&lt;p&gt;Under &lt;strong&gt;Build configuration,&lt;/strong&gt; type &lt;code&gt;build&lt;/code&gt; under &lt;strong&gt;Public folder&lt;/strong&gt; field and add &lt;code&gt;npm run build&lt;/code&gt; command under &lt;strong&gt;Build command&lt;/strong&gt; field.&lt;/p&gt;

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

&lt;p&gt;Under &lt;strong&gt;Environment variables&lt;/strong&gt;, add &lt;code&gt;REACT_APP_BUTTER_ECOMMERCE&lt;/code&gt; and &lt;code&gt;REACT_APP_SNIPCART_KEY&lt;/code&gt; environment variables with their values and click on the &lt;strong&gt;Update environment&lt;/strong&gt; button.&lt;/p&gt;

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

&lt;p&gt;Finally, click on the &lt;strong&gt;Deploy now&lt;/strong&gt; button to deploy your app.&lt;/p&gt;

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

&lt;p&gt;A modal will appear to select the environment, select the &lt;strong&gt;production&lt;/strong&gt; environment and click on &lt;strong&gt;Deploy now&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;The &lt;strong&gt;Deploy now&lt;/strong&gt; will trigger the deployment process, which you can see live on your dashboard.&lt;/p&gt;

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

&lt;p&gt;After the deployment process completes, you will be provided with a preview URL of your deployed website. &lt;/p&gt;

&lt;p&gt;If the preview looks good, you can publish it to production by going to the &lt;strong&gt;Deployments&lt;/strong&gt; tab and clicking on the triple dots across the latest commit, i.e., &lt;code&gt;Finished building the React Ecommerce app&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;A modal will appear, deselect the sync sliders option and then scroll the bar to 100%, i.e., to the end. Finally, click on &lt;strong&gt;Publish to production&lt;/strong&gt; button to publish the app.&lt;/p&gt;

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

&lt;p&gt;Congratulations, your ecommerce app has been deployed. You can see the deployed version of this project &lt;a href="https://yakscythe-49dgnn.stormkit.dev/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

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

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

&lt;p&gt;In this tutorial, we learned how to build an Ecommerce App with React.js using ButterCMS and Snipcart. Finally, we deployed our ecommerce app with Stormkit. You can follow this tutorial and create your own version of this project. &lt;/p&gt;

&lt;p&gt;Here are a few ideas to get you started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Style the app using other UI libraries like &lt;a href="https://react-bootstrap.github.io/" rel="noopener noreferrer"&gt;React Bootstrap&lt;/a&gt;, &lt;a href="https://material-ui.com/" rel="noopener noreferrer"&gt;Material UI&lt;/a&gt;, etc.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://snipcart.com/blog/stripe-checkout-form-integration-vs-snipcart" rel="noopener noreferrer"&gt;Integrate a Payment Gateway like Stripe.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://auth0.com/docs/quickstart/spa/react/01-login" rel="noopener noreferrer"&gt;Add Authentication Portal with Auth0.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are some additional resources that can be helpful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://buttercms.com/" rel="noopener noreferrer"&gt;ButterCMS Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stormkit.io/docs" rel="noopener noreferrer"&gt;Stormkit Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://buttercms.com/" rel="noopener noreferrer"&gt;Snipcart Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chakra-ui.com/docs/getting-started" rel="noopener noreferrer"&gt;Chakra UI Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>react</category>
      <category>headlesscsms</category>
      <category>ecommerce</category>
      <category>snipcart</category>
    </item>
    <item>
      <title>Deploying a full blown React website with Stormkit and Storyblok</title>
      <dc:creator>Savas Vedova</dc:creator>
      <pubDate>Thu, 07 Nov 2019 06:13:10 +0000</pubDate>
      <link>https://forem.com/stormkit/deploying-a-full-blown-react-website-with-stormkit-and-storyblok-50cd</link>
      <guid>https://forem.com/stormkit/deploying-a-full-blown-react-website-with-stormkit-and-storyblok-50cd</guid>
      <description>&lt;p&gt;I’ve been using &lt;a href="https://vsk.me" rel="noopener noreferrer"&gt;my website&lt;/a&gt; as a place to share my CV so far. It's a &lt;a href="https://github.com/facebook/create-react-app" rel="noopener noreferrer"&gt;create-react-app&lt;/a&gt; bootstrap hosted on &lt;a href="https://www.stormkit.io" rel="noopener noreferrer"&gt;Stormkit&lt;/a&gt;. Lately, I’ve decided to add a blog section to it. A friend of mine was using &lt;a href="https://www.storyblok.com/" rel="noopener noreferrer"&gt;Storyblok&lt;/a&gt; and talking good about it so I wanted to give it a shot. In this tutorial I’ll share what it took for me to implement the blog section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow
&lt;/h2&gt;

&lt;p&gt;After updating the code, I simply push to Github. Stormkit receives an event and builds the website. Once the deployment is successful, it automatically publishes it. So all I have to do is to merge to master. To update the content, I use StoryBlok. Pretty cool and intuitive CMS. Using a combination of StoryBlok and Stormkit, I can preview the changes of the blog post directly on the website and then publish the content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's get started
&lt;/h2&gt;

&lt;p&gt;I'll assume you already have an application bootstrapped. I've used &lt;a href="https://github.com/facebook/create-react-app" rel="noopener noreferrer"&gt;create-react-app&lt;/a&gt; for this, but you can use whatever you feel comfortable with.&lt;/p&gt;

&lt;p&gt;First of all, let's install the requirements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add storyblok-js-client react-markdown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These packages will be used to make an API call to &lt;a href="https://www.storyblok.com/" rel="noopener noreferrer"&gt;Storyblok&lt;/a&gt; to fetch the content, and to transform the returned markdown into a react component. More on this will come later.&lt;/p&gt;

&lt;p&gt;Second, make sure to have either a &lt;a href="https://github.com" rel="noopener noreferrer"&gt;Github&lt;/a&gt; or &lt;a href="https://bitbucket.org" rel="noopener noreferrer"&gt;Bitbucket&lt;/a&gt; account and push the repository to one of these providers. We’ll use this to connect our repository to &lt;a href="https://www.stormkit.io" rel="noopener noreferrer"&gt;Stormkit&lt;/a&gt; and deploy our website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare the content
&lt;/h2&gt;

&lt;p&gt;First head to &lt;a href="https://www.storyblok.com/" rel="noopener noreferrer"&gt;Storyblok&lt;/a&gt;, create an account if you haven't and create a workspace.&lt;/p&gt;

&lt;p&gt;&lt;a href="//a.storyblok.com/f/68531/1024x431/f968b318c8/screenshot-2019-10-27-at-12-34-00.png" class="article-body-image-wrapper"&gt;&lt;img src="//a.storyblok.com/f/68531/1024x431/f968b318c8/screenshot-2019-10-27-at-12-34-00.png" alt="Img"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a new space and choose Headless as the type. Next, we’ll be adding a new folder. You can group your content using folders. Click on the &lt;strong&gt;+ Folder&lt;/strong&gt; button and name your folder. In my case I picked &lt;strong&gt;posts&lt;/strong&gt; as a name. Leave the other settings empty. Afterwards, click on &lt;strong&gt;+ Entry&lt;/strong&gt; button and create a new entry. Pick a title and a slug for the entry. You’ll be using the slug to read it from the URL and fetch the content, therefore pick something that is SEO compatible.&lt;/p&gt;

&lt;p&gt;&lt;a href="//a.storyblok.com/f/68531/1024x190/343678d4a2/screenshot-2019-10-27-at-12-32-44.png" class="article-body-image-wrapper"&gt;&lt;img src="//a.storyblok.com/f/68531/1024x190/343678d4a2/screenshot-2019-10-27-at-12-32-44.png" alt="Img"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you have created the folder and your first entry, you can define the schema for your posts. Click on &lt;strong&gt;Define schema&lt;/strong&gt; and specify the fields that you will need. By default, Storyblok creates a body field with a default field type. Change that to &lt;strong&gt;markdown&lt;/strong&gt;. After, you can add all the fields you will need. In my case, I have added a &lt;strong&gt;keywords&lt;/strong&gt;, &lt;strong&gt;title, short content&lt;/strong&gt; and &lt;strong&gt;description&lt;/strong&gt; field**.** The ‘keywords’ and ‘description’ fields are used for SEO meta tags and the ‘short content’ is used for displaying a short description to the user when listing the latest entries.&lt;/p&gt;

&lt;p&gt;&lt;a href="//a.storyblok.com/f/68531/1024x190/243ec3e321/screenshot-2019-10-27-at-12-36-05.png" class="article-body-image-wrapper"&gt;&lt;img src="//a.storyblok.com/f/68531/1024x190/243ec3e321/screenshot-2019-10-27-at-12-36-05.png" alt="Img"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To add new entries, you will be using the &lt;strong&gt;+ Entry&lt;/strong&gt; button again on the entries page. Make sure that the &lt;strong&gt;posts&lt;/strong&gt; is selected when adding new entries.&lt;/p&gt;

&lt;h2&gt;
  
  
  The code
&lt;/h2&gt;

&lt;p&gt;Storyblok comes with a JS library that helps us making requests and retrieve content. At the beginning of this blog post, we have installed its official package. We'll using that one to make requests. Since the same client will be used across the application, I decided to create a global context and pass the client around with this context. I’ve created a file that exports the provider and a helper function to inject the context values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.context.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;withConsumer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Consumer&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;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/context.Consumer&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;Now let's create the provider and pass down the client object that we’re going to create at application load. The code is commented for further information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.context&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;StoryblokClient&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;storyblok-js-client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="c1"&gt;// Create the Storyblok client. You can obtain the API-Key from &lt;/span&gt;
&lt;span class="c1"&gt;// the Storyblok dashboard, by clicking on Settings and then api keys tab.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Storyblok&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;StoryblokClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;your_api_key&amp;gt;&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;memory&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="c1"&gt;// Wrap the application with a global context, and pass down the Storyblok client.&lt;/span&gt;
  &lt;span class="c1"&gt;// If we decide to add server-side rendering, we can create a new instance per request &lt;/span&gt;
  &lt;span class="c1"&gt;// and pass it down the client without a race condition.&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;storyblok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Storyblok&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="cm"&gt;/* your app goes here */&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;/context.Provider&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to fetch the content. To do so, we need to connect the component that will display the latest blog entries to the context, retrieve the client and use the Storyblok API to fetch the items. Here is how:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Posts.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.context&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;Markdown&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reach-markdown&lt;/span&gt;&lt;span class="dl"&gt;"&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;unmounted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;storyblok&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;entries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEntries&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// After the first call entries will be an array. &lt;/span&gt;
    &lt;span class="c1"&gt;// Do not re-fetch after the first call.&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="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="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;Storyblok&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cdn/stories&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;starts_with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// If there is a race condition and the component is unmounted before&lt;/span&gt;
      &lt;span class="c1"&gt;// the api call is completed, do not update the state as React will &lt;/span&gt;
      &lt;span class="c1"&gt;// complain about memory leak.&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;unmounted&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;stories&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="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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;unmounted&lt;/span&gt; &lt;span class="o"&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;storyblok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEntries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nothing found.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;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;posts&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;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Latest&lt;/span&gt; &lt;span class="nx"&gt;entries&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="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;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/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;Markdown&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withConsumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Posts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploying the application (manually)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; Once you have configured the environment (manually or through stormkit.config.yml), you can deploy automatically on each commit. In this tutorial, I'll show how to deploy manually.&lt;/p&gt;

&lt;p&gt;In order to deploy our application, we’re going to use &lt;a href="https://www.stormkit.io" rel="noopener noreferrer"&gt;Stormkit&lt;/a&gt;. It makes deploying and managing web applications extremely easy. With Stormkit you can create isomorphic applications that have multiple environments, publish new versions to a percentage of users, implement remote configuration and conduct experiments with a/b testing. Autoscaling and TLS certificates are included and you don't have to worry about it.&lt;/p&gt;

&lt;p&gt;Let's move on an connect our application:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://app.stormkit.io" rel="noopener noreferrer"&gt;app.stormkit.io&lt;/a&gt; and select your provider&lt;/li&gt;
&lt;li&gt;Once logged in, Stormkit will ask you in which provider your codebase is located. Click on the provider once more.&lt;/li&gt;
&lt;li&gt;If Github, click on ‘Connect more repositories’ and grant access to Stormkit.&lt;/li&gt;
&lt;li&gt;Next select your repository and now it's connected.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you have followed the steps above, you’ll be presented a page where you see the &lt;strong&gt;production&lt;/strong&gt; environment:&lt;/p&gt;

&lt;p&gt;&lt;a href="//a.storyblok.com/f/68531/1024x535/e3d9af0ad6/screenshot-2019-10-27-at-23-02-16.png" class="article-body-image-wrapper"&gt;&lt;img src="//a.storyblok.com/f/68531/1024x535/e3d9af0ad6/screenshot-2019-10-27-at-23-02-16.png" alt="Img"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;strong&gt;Details&lt;/strong&gt; under the &lt;strong&gt;production&lt;/strong&gt; environment. You’ll be brought to a page where you can deploy your application. On top right of the screen you’ll see a &lt;strong&gt;Deploy now&lt;/strong&gt; button. Click on that. If you’ve bootstrapped your application using &lt;strong&gt;create-react-app&lt;/strong&gt; the default settings should be enough. Otherwise check &lt;a href="https://www.stormkit.io/docs/deployments" rel="noopener noreferrer"&gt;here&lt;/a&gt; for relevant documentation for configuring your environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="//a.storyblok.com/f/68531/1024x542/447db15efe/screenshot-2019-10-27-at-23-21-31.png" class="article-body-image-wrapper"&gt;&lt;img src="//a.storyblok.com/f/68531/1024x542/447db15efe/screenshot-2019-10-27-at-23-21-31.png" alt="Img"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have deployed your application, Stormkit will generate a URL for you. Preview your application using that link. Later, you can connect your domain and publish this deployment so that the users will start to see that version of your application. You can also do staged rollouts by publishing multiple versions at the same time.&lt;/p&gt;

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

&lt;p&gt;If you were able to follow until here, you should now have a serverless application that is hosted on Stormkit, and the backend is provided by Storyblok. All of this without touching a single line of server configuration. Pretty neat, huh?&lt;/p&gt;

&lt;p&gt;To sum up; in essence we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created a workspace with Storyblok&lt;/li&gt;
&lt;li&gt;Connected our repo to Stormkit for deployments&lt;/li&gt;
&lt;li&gt;Installed requirements&lt;/li&gt;
&lt;li&gt;Created a global context to pass down the Storyblok client and&lt;/li&gt;
&lt;li&gt;Fetched the latest entries using the Storyblok client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hope you enjoyed the tutorial. Follow me on &lt;a href="https://twitter.com/savasvedova" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; if you have any remarks, questions, or simply want to connect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;I'm the founder of &lt;a href="https://www.stormkit.io" rel="noopener noreferrer"&gt;Stormkit&lt;/a&gt; and I am strongly biased towards the tool. However, this doesn't mean what I say about the tool is exaggerated 😜&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Original Post:&lt;/strong&gt; &lt;a href="https://vsk.me/blog/deploying-a-full-blown-react-website-with-stormkit-and-storyblok" rel="noopener noreferrer"&gt;https://vsk.me/blog/deploying-a-full-blown-react-website-with-stormkit-and-storyblok&lt;/a&gt;&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>jamstack</category>
      <category>stormkit</category>
      <category>react</category>
    </item>
  </channel>
</rss>
