<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: CodingTechMan</title>
    <description>The latest articles on DEV Community by CodingTechMan (@codingtechman).</description>
    <link>https://dev.to/codingtechman</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1863976%2F667ac5ff-cfb2-4acd-975f-98b52eb505ce.png</url>
      <title>DEV Community: CodingTechMan</title>
      <link>https://dev.to/codingtechman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codingtechman"/>
    <language>en</language>
    <item>
      <title>Simple Tutorial: A Dockerized Node.js, React and Next.js Application</title>
      <dc:creator>CodingTechMan</dc:creator>
      <pubDate>Fri, 09 Aug 2024 05:06:52 +0000</pubDate>
      <link>https://dev.to/codingtechman/simple-tutorial-a-dockerized-nodejs-react-and-nextjs-application-gik</link>
      <guid>https://dev.to/codingtechman/simple-tutorial-a-dockerized-nodejs-react-and-nextjs-application-gik</guid>
      <description>&lt;h2&gt;
  
  
  Simple Tutorial: A Dockerized Node.js, React and Next.js Application
&lt;/h2&gt;

&lt;p&gt;This is a simple tutorial aimed at showing you how to get a simple Node.js, Next.js and React App up and running with Docker on your local machine. It is aimed at beginner web developers looking to start a web project.&lt;/p&gt;

&lt;p&gt;After following this tutorial, we should have a React + Next.js frontend application and it pulls data from a Node.js backend application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nIx0Df7t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3840/1%2A1UjDwNW0vsujRjgFLJCOig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nIx0Df7t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3840/1%2A1UjDwNW0vsujRjgFLJCOig.png" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt; Install Git, Docker, and Docker-Compose&lt;/p&gt;

&lt;p&gt;The prerequisites to complete this tutorial are git, Docker and Docker-Compose. These links should take you to the installation page for each software.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git" rel="noopener noreferrer"&gt;Git&lt;/a&gt;: Allows you to download the provided repository in Step 1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;: Allows us to run code in containers, regardless of environment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/compose/install/" rel="noopener noreferrer"&gt;Docker-Compose&lt;/a&gt;: Allows us to run multiple containers easily, we have both a frontend and a backend container in this project.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Copy the Sample Application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’ve provided a simple application for you to clone at the link below. Simply use git clone &lt;a href="https://github.com/EMChamp/simple-nodejs-react-docker-app" rel="noopener noreferrer"&gt;https://github.com/EMChamp/simple-nodejs-react-docker-app&lt;/a&gt; to clone the repo to your local machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/EMChamp/simple-nodejs-react-docker-app" rel="noopener noreferrer"&gt;Repo Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is what the directory layout should look like. It isn’t important to understand every file, just check that you have a &lt;strong&gt;client directory&lt;/strong&gt;, &lt;strong&gt;server directory&lt;/strong&gt;, and &lt;strong&gt;docker-compose.yml&lt;/strong&gt; in your directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JzXhdPWK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Arh6eP5I7rkCd8TFvLjWwoA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JzXhdPWK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Arh6eP5I7rkCd8TFvLjWwoA.png" alt="Directory contents after git clone command" width="572" height="41"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Run on Docker&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the following command in the &lt;strong&gt;simple-nodejs-react-docker-app&lt;/strong&gt; directory docker-compose up&lt;/p&gt;

&lt;p&gt;If all goes well we should see this output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eO6dfJqc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2696/1%2AA13WUTOayUENo0HzouyxcA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eO6dfJqc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2696/1%2AA13WUTOayUENo0HzouyxcA.png" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Visit Website&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your web browser visit &lt;a href="http://localhost:5041/" rel="noopener noreferrer"&gt;http://localhost:5041/&lt;/a&gt;, you should see the following page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nIx0Df7t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3840/1%2A1UjDwNW0vsujRjgFLJCOig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nIx0Df7t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3840/1%2A1UjDwNW0vsujRjgFLJCOig.png" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The string “Data from Backend API” is pulled from the backend and displayed on the page.&lt;/p&gt;

&lt;p&gt;Now we have finished the tutorial and have a working Node.js, React and Next.js application running on Docker. As next steps you can choose to modify the code to suit an application that you would like to build.&lt;/p&gt;

&lt;p&gt;In the next optional section, we will walk through the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Code Walkthrough&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While it is not necessary to read this section to run the project, it may be useful as a reference to understand what the files do and what they affect if you plan to modify the code.&lt;/p&gt;

&lt;p&gt;Here is what the directory contents should look like. It isn’t important to understand every file (which is covered below), just check that you have a &lt;strong&gt;client **directory, **server **directory, and **docker-compose.yml&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;simple-nodejs-react-docker-app/
├── client/
│   ├── package.json
│   ├── package-lock.json
│   ├── public/
│   │   ├── favicon.ico
│   ├── styles/
│   │   ├── styles.css
│   ├── pages/
│   │   ├── _app.tsx
│   │   ├── index.tsx
│   ├── tsconfig.json
├── server/
│   ├── package.json
│   ├── package-lock.json
│   ├── server.js
│   ├── Dockerfile
└── docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Client&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This section will cover the important files in the client directory and their purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;package.json&lt;/strong&gt; will define the dependencies we need to run the application. It will also define our start and build commands.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "client",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "next dev -p $PORT",
    "build": "next build",
    "start": "next start -p $PORT"
  },
  "dependencies": {
    "axios": "^0.21.1",
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  },
  "devDependencies": {
    "@types/react": "^18.0.0",
    "@types/react-dom": "^18.0.0",
    "typescript": "^4.7.0"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;src/pages/index.tsx&lt;/strong&gt; will define the main page our application loads. It will display a simple page with a header saying “Simple Node.js and React App”. It will then load a string from &lt;a href="http://localhost:5040/endpoint" rel="noopener noreferrer"&gt;http://localhost:5040/endpoint&lt;/a&gt; which is an endpoint defined by the server that is running on our local machine. This string is then used to populate the page.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from 'react';
import axios from 'axios';

const Home: React.FC = () =&amp;gt; {
  const [data, setData] = useState&amp;lt;string&amp;gt;('');
  const [loading, setLoading] = useState&amp;lt;boolean&amp;gt;(true);
  const [error, setError] = useState&amp;lt;string&amp;gt;('');

  useEffect(() =&amp;gt; {
    axios.get('http://localhost:5040/endpoint')
      .then(response =&amp;gt; {
        setData(response.data);
        setLoading(false);
      })
      .catch(error =&amp;gt; {
        setError('Failed to fetch data');
        setLoading(false);
      });
  }, []);

  return (
    &amp;lt;div className="container"&amp;gt;
      &amp;lt;header className="header"&amp;gt;
        &amp;lt;h1&amp;gt;Simple Node.js and React App&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;The data below is populated by our Node.js Backend. This page is build with React.&amp;lt;/p&amp;gt;
      &amp;lt;/header&amp;gt;
      &amp;lt;main className="content"&amp;gt;
        {loading ? (
          &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;
        ) : error ? (
          &amp;lt;p&amp;gt;{error}&amp;lt;/p&amp;gt;
        ) : (
          &amp;lt;section&amp;gt;
            &amp;lt;h2&amp;gt;API Data&amp;lt;/h2&amp;gt;
            &amp;lt;p&amp;gt;{data}&amp;lt;/p&amp;gt;
          &amp;lt;/section&amp;gt;
        )}
      &amp;lt;/main&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Home;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;src/pages/_app.tsx&lt;/strong&gt; is the entry point for our application. It loads the global CSS stylesheet for all pages, including index.tsx and any future pages. The MyApp function wraps all our pages and ensures they have the necessary global styles and settings. Next.js handles Server-Side Rendering (SSR) by default, allowing pages to be rendered on the server before being sent to the client.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// _app.tsx
import '../styles/styles.css'; // Adjust path according to your structure

import type { AppProps } from 'next/app';

function MyApp({ Component, pageProps }: AppProps) {
  return (
      &amp;lt;Component {...pageProps} /&amp;gt;
  );
}

export default MyApp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;src/styles/styles.css&lt;/strong&gt; defines simple styling for our rendered web page.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body {
    margin: 0;
    font-family: Arial, sans-serif;
    background-color: #f4f4f4;
    color: #333;
  }

  .container {
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
    background-color: #fff;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  }

  .header {
    text-align: center;
    padding: 20px 0;
    border-bottom: 1px solid #ddd;
  }

  .header h1 {
    margin: 0;
    font-size: 2.5em;
    color: #0070f3;
  }

  .header p {
    margin: 0;
    font-size: 1.2em;
    color: #555;
  }

  .content {
    padding: 20px 0;
  }

  .content section {
    margin-bottom: 20px;
  }

  .content h2 {
    margin-top: 0;
    font-size: 1.8em;
    color: #0070f3;
  }

  .content p {
    font-size: 1em;
    line-height: 1.6;
    color: #555;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt; configures a Docker container for a Next.js application. It uses the Node.js version 21 image, sets the working directory, copies the necessary files, installs dependencies, copies the application code, builds the Next.js application, exposes port 5041, and defines the command to start the application using npm start.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:21

WORKDIR /app

COPY package.json ./
COPY package-lock.json ./
RUN npm install

COPY . .

# Build the Next.js application
RUN npm run build

EXPOSE 5041

CMD ["npm", "start"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Server Code&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The server code is very simple in that it contains a barebones application.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── server/
│   ├── package.json
│   ├── package-lock.json
│   ├── server.js
│   ├── Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;package.json&lt;/strong&gt; defines the command to start our server on node.js and also the dependencies cors and express needed on the server.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "name": "server",
    "version": "1.0.0",
    "main": "server.js",
    "scripts": {
      "start": "node server.js"
    },
    "dependencies": {
      "express": "^4.17.1",
      "cors": "^2.8.5"
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;server.js&lt;/strong&gt; defines our server code using Express.js. It sets up an endpoint /endpoint that returns a string when accessed. The client can call this endpoint by sending a GET request to &lt;a href="http://localhost:5040/endpoint" rel="noopener noreferrer"&gt;http://localhost:5040/endpoint&lt;/a&gt; to retrieve this data. CORS is configured to allow requests only from &lt;a href="http://localhost" rel="noopener noreferrer"&gt;http://localhost&lt;/a&gt;, ensuring that only our client application can access this endpoint.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// server.js
const express = require('express');
const cors = require('cors');
const app = express();

// Use the PORT environment variable if it is set, otherwise default to 5040
const port = process.env.PORT || 5040;

// Enable CORS for specific origins
const corsOptions = {
  origin: 'http://localhost:5041',
};
app.use(cors(corsOptions));

app.get('/endpoint', (req, res) =&amp;gt; {
  res.send('Data from Backend API');
});

app.listen(port, () =&amp;gt; {
  console.log(`Server is running on http://localhost:${port}`);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt; configures a Docker container for the server application. It uses the Node.js version 21 image as the base, sets the working directory to /app, copies the necessary files, installs dependencies, copies the application code, exposes port 5040, and defines the command to start the application using npm start.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Root Directory&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The root directory only has one file called docker-compose.yml that is relevant to the project (README.md is only used to for GitHub purposes).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docker-compose.yml&lt;/strong&gt; defines the frontend and backend containers that make up the application. It specifies the appropriate ports to be exposed on each container and binds them to the corresponding ports on the host machine. It also defines environment variables that set the port for the React and Node.js applications, and ensures that the frontend container depends on the backend container.version: '3.8'&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  backend_server:
    build: ./server
    ports:
      - "5040:5040"
    environment:
      - PORT=5040
  frontend_client:
    build: ./client
    ports:
      - "5041:5041"
    environment:
      - PORT=5041
    depends_on:
      - backend_server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This tutorial is hopefully helpful as a guide on how to dockerize your Node.js and React projects. Dockerization is helpful especially when you want to launch your application on different environments. Many popular tools like Kubernetes require the use of containers so this gives you a head start as well when deploying to production.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>docker</category>
      <category>react</category>
      <category>node</category>
    </item>
    <item>
      <title>Real-Time Crypto Tracker using Webhooks with React, Next.js and Node.js</title>
      <dc:creator>CodingTechMan</dc:creator>
      <pubDate>Fri, 09 Aug 2024 04:54:15 +0000</pubDate>
      <link>https://dev.to/codingtechman/real-time-crypto-tracker-using-webhooks-with-react-nextjs-and-nodejs-4cec</link>
      <guid>https://dev.to/codingtechman/real-time-crypto-tracker-using-webhooks-with-react-nextjs-and-nodejs-4cec</guid>
      <description>&lt;h2&gt;
  
  
  Real-Time Crypto Tracker using Webhooks with React, Next.js and Node.js
&lt;/h2&gt;

&lt;p&gt;In this article we explore building a crypto tracker using webhooks with a Frontend built with React, Next.js which is connected to a Backend. Now typically a frontend is the one pulling all the data, but with websockets we can push data from a backend to the frontend.&lt;/p&gt;

&lt;p&gt;Webhooks can be useful any time you need real-time updates on your frontend. Since Cryptocurrency prices change in real time this is a great use case for it. You can have a real-time dashboard that simply tracks crypto in real time without refreshing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xk91a-Lb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/3840/1%2AbYmkvNo7kiWOggD47bjjNQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xk91a-Lb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/3840/1%2AbYmkvNo7kiWOggD47bjjNQ.gif" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CoinMarketCap API Key (Free Version is OK) — Required as this is our data source for cryptocurrency prices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node.js installed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git for cloning&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Repo Link&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code overview below covers the main part of the code, however to run the entire project I recommend using git clone on the repo link below to follow along.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/EMChamp/cryptotracker-reactnode" rel="noopener noreferrer"&gt;https://github.com/EMChamp/cryptotracker-reactnode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Overview — Frontend&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This code overview will look at the major pieces of the code and give an idea of their responsibilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;frontend/App.js&lt;/strong&gt; is the main page of our Next.js/React App where it will actively track a set of cryptocurrency symbols. We also have a websocket connection setup to our backend where we actively listen for price updates.&lt;/p&gt;

&lt;p&gt;We also have a method for adding new cryptocurrency symbols to track. By default we are only tracking Bitcoin (BTC) and Ethereum Classic (ETC).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from 'react';
import axios from 'axios';
import './App.css';

function App() {
  // Track symbols and prices
  const [prices, setPrices] = useState({});
  const [newSymbol, setNewSymbol] = useState('');
  const [trackingSymbols, setTrackingSymbols] = useState(['BTC', 'ETC']);

  // Listen for new webhook events from backend and update prices accordingly.
  useEffect(() =&amp;gt; {
    const ws = new WebSocket('ws://localhost:5000');

    ws.onmessage = (event) =&amp;gt; {
      const data = JSON.parse(event.data);
      setPrices(data);
    };

    return () =&amp;gt; ws.close();
  }, []);

  // Handles adding new symbols to the tracking list
  const addSymbol = () =&amp;gt; {
    if (newSymbol &amp;amp;&amp;amp; !trackingSymbols.includes(newSymbol.toUpperCase())) {
      axios.post('http://localhost:5000/add-symbol', { symbol: newSymbol })
        .then(response =&amp;gt; {
          setTrackingSymbols(response.data.symbols);
          setNewSymbol('');
        })
        .catch(error =&amp;gt; {
          console.error('Error adding symbol:', error.response.data.message);
        });
    }
  };

  // UI/Frontend of the page
  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;header className="App-header"&amp;gt;
        &amp;lt;h1&amp;gt;CryptoTracker&amp;lt;/h1&amp;gt;
      &amp;lt;/header&amp;gt;
      &amp;lt;main&amp;gt;
        &amp;lt;div className="symbol-input"&amp;gt;
          &amp;lt;input
            type="text"
            placeholder="Enter crypto symbol (e.g., BTC)"
            value={newSymbol}
            onChange={(e) =&amp;gt; setNewSymbol(e.target.value)}
          /&amp;gt;
          &amp;lt;button onClick={addSymbol}&amp;gt;Add Symbol&amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="symbol-tracker"&amp;gt;
          {trackingSymbols.map((symbol) =&amp;gt; (
            &amp;lt;div key={symbol} className="symbol-card"&amp;gt;
              &amp;lt;h2&amp;gt;{symbol}&amp;lt;/h2&amp;gt;
              &amp;lt;p&amp;gt;{prices[symbol] ? `$${prices[symbol].toFixed(2)}` : 'Loading...'}&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
          ))}
        &amp;lt;/div&amp;gt;
      &amp;lt;/main&amp;gt;
      &amp;lt;footer className="App-footer"&amp;gt;
        &amp;lt;p&amp;gt;&amp;amp;copy; 2024 CryptoTracker. All rights reserved.&amp;lt;/p&amp;gt;
      &amp;lt;/footer&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;frontend/index.js&lt;/strong&gt; is responsible for rendering App.js’ App component onto the browser.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  &amp;lt;React.StrictMode&amp;gt;
    &amp;lt;App /&amp;gt;
  &amp;lt;/React.StrictMode&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;frontend/App.css&lt;/strong&gt; styles the HTML in the page above in a clean and modern look.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body {
  margin: 0;
  font-family: Arial, sans-serif;
  background-color: #f4f4f4;
}

.App {
  text-align: center;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.App-header {
  background-color: #1a1a1a;
  color: white;
  padding: 20px;
  text-align: center;
  font-size: 1.5em;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  position: sticky;
  top: 0;
  z-index: 1000;
}

.symbol-input {
  margin: 20px auto;
  display: flex;
  justify-content: center;
}

.symbol-input input {
  padding: 10px;
  font-size: 1em;
  width: 250px;
  margin-right: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.symbol-input button {
  padding: 10px 20px;
  font-size: 1em;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.symbol-input button:hover {
  background-color: #0056b3;
}

.symbol-tracker {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 20px;
  padding: 20px;
}

.symbol-card {
  background-color: white;
  border: 1px solid #ccc;
  border-radius: 8px;
  padding: 20px;
  width: 200px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s;
}

.symbol-card h2 {
  margin: 0;
  font-size: 1.2em;
}

.symbol-card p {
  margin: 10px 0 0;
  font-size: 1.1em;
  color: #333;
}

.symbol-card:hover {
  transform: translateY(-5px);
}

.App-footer {
  background-color: #1a1a1a;
  color: white;
  padding: 10px;
  text-align: center;
  margin-top: auto;
  box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.1);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Code Overview — Backend&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;backend/server.js&lt;/strong&gt; is our backend server code. It is setup to poll CoinMarketCap’s API every 10 seconds for price changes and then push those changes via websocket to any connected frontend clients.&lt;/p&gt;

&lt;p&gt;The endpoint &lt;strong&gt;/add-symbol&lt;/strong&gt; takes requests from the frontend for any new symbols to track and appends it to the list of currently tracked symbols when we make the next API call to CoinMarketCap’s API for price changes.&lt;/p&gt;

&lt;p&gt;We use the websocket library to handle the heavy lifting of managing websocket connections where it actively listens for any HTTPS connections that should be upgraded to websocket.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const axios = require('axios');
const WebSocket = require('ws');
const cors = require('cors');

const app = express();
app.use(cors());
const PORT = 5000;
const API_KEY = ''; // Replace with your CoinMarketCap API key
const INTERVAL = 10000; // Poll every 10 seconds

// List of cryptocurrencies to track
let symbols = ['BTC', 'ETC'];

// Create a WebSocket server
const wss = new WebSocket.Server({ noServer: true });

// Function to fetch cryptocurrency prices
const fetchPrices = async () =&amp;gt; {
    try {
        const response = await axios.get('https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest', {
            params: {
                symbol: symbols.join(','),
                convert: 'USD'
            },
            headers: {
                'X-CMC_PRO_API_KEY': API_KEY
            }
        });

        const prices = symbols.reduce((acc, symbol) =&amp;gt; {
            acc[symbol] = response.data.data[symbol].quote.USD.price;
            return acc;
        }, {});

        return prices;
    } catch (error) {
        console.error('Error fetching data from CoinMarketCap:', error);
        return null;
    }
};

// Broadcast prices to all clients
const broadcastPrices = (prices) =&amp;gt; {
    wss.clients.forEach(client =&amp;gt; {
        if (client.readyState === WebSocket.OPEN) {
            client.send(JSON.stringify(prices));
        }
    });
};

// Periodically poll CoinMarketCap API and broadcast prices
setInterval(async () =&amp;gt; {
    const prices = await fetchPrices();
    if (prices) {
        broadcastPrices(prices);
    }
}, INTERVAL);

// Handle HTTP and WebSocket connections
const server = app.listen(PORT, () =&amp;gt; {
    console.log(`Server running on http://localhost:${PORT}`);
});

server.on('upgrade', (request, socket, head) =&amp;gt; {
    wss.handleUpgrade(request, socket, head, (ws) =&amp;gt; {
        wss.emit('connection', ws, request);
    });
});

// Endpoint for tracking new symbols
app.post('/add-symbol', (req, res) =&amp;gt; {
    const { symbol } = req.body;
    if (!symbols.includes(symbol.toUpperCase())) {
        symbols.push(symbol.toUpperCase());
        res.status(200).send({ success: true, symbols });
    } else {
        res.status(400).send({ success: false, message: 'Symbol already being tracked' });
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Running the application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code overview goes over the main parts of the code however it is not complete, so we would still recommend to clone the code from our GitHub repository in order to run it locally.&lt;/p&gt;

&lt;p&gt;First you will have to replace &lt;strong&gt;API_KEY&lt;/strong&gt; with your CoinMarketCap API Key.&lt;/p&gt;

&lt;p&gt;Afterwards we can run the following commands which will go to each portion of the application, install their packages and then start the server.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd frontend
npm install
npm start

cd ../backend
npm install
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZNl430GE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2556/1%2ASJaJg4gdoT6HzOVf-YePNw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZNl430GE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2556/1%2ASJaJg4gdoT6HzOVf-YePNw.png" alt="Output of above commands" width="800" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we should have our frontend server running on &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; and backend server on &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Going to our frontend on &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; will let us access this page where you can add Cryptocurrency symbols and then watch the application update in real time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xk91a-Lb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/3840/1%2AbYmkvNo7kiWOggD47bjjNQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xk91a-Lb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/3840/1%2AbYmkvNo7kiWOggD47bjjNQ.gif" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cryptocurrency</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
