Build a Next.js Interactive Web-Based Cryptocurrency Price Alert

Written by

in

In the fast-paced world of cryptocurrency, staying informed about price fluctuations is crucial. Missing a sudden surge or a sharp drop can mean lost opportunities or unexpected losses. Wouldn’t it be great to have a system that automatically notifies you when the price of your favorite cryptocurrencies hits specific targets? This tutorial will guide you through building a dynamic, real-time cryptocurrency price alert application using Next.js, a powerful React framework, and CoinGecko’s API.

Why Build a Crypto Price Alert App?

Traditional methods of tracking cryptocurrency prices, such as manually checking exchanges or relying on basic price trackers, can be time-consuming and inefficient. A price alert app provides a proactive solution, allowing you to:

  • Stay ahead of the market: Receive instant notifications about price movements, enabling you to react quickly.
  • Automate monitoring: Eliminate the need to constantly monitor prices manually.
  • Customize alerts: Set alerts based on your specific investment strategies and risk tolerance.
  • Improve decision-making: Make informed decisions based on real-time data and personalized alerts.

This project is perfect for beginners and intermediate developers looking to deepen their understanding of Next.js, API integration, and real-time data handling. You’ll learn how to fetch data from an external API, manage state, create dynamic user interfaces, and implement notifications.

Prerequisites

Before we begin, make sure you have the following:

  • Node.js and npm (or yarn): Installed on your computer.
  • Basic knowledge of JavaScript and React: Familiarity with React components, state, and props is recommended.
  • A code editor: Such as Visual Studio Code, Sublime Text, or Atom.
  • A CoinGecko API Key: You will need to create a free account on CoinGecko to access their API. (Optional, but recommended for higher rate limits).

Step-by-Step Guide

1. Setting Up Your Next.js Project

Let’s start by creating a new Next.js project. Open your terminal and run the following command:

npx create-next-app crypto-alert-app

This command will create a new directory called crypto-alert-app with all the necessary files for your project. Navigate into the project directory:

cd crypto-alert-app

Next, install the necessary dependencies. We’ll need axios for making API requests and a notification library (e.g., react-toastify) to display alerts to the user. Install them using npm or yarn:

npm install axios react-toastify

or

yarn add axios react-toastify

2. Fetching Cryptocurrency Data

We’ll use the CoinGecko API to fetch real-time cryptocurrency price data. Create a new file named utils/api.js in your project directory. This file will contain functions to interact with the CoinGecko API. Add the following code to utils/api.js:

import axios from 'axios';

const API_BASE_URL = 'https://api.coingecko.com/api/v3';

export const getCryptoPrices = async (ids, vsCurrencies) => {
  try {
    const response = await axios.get(`${API_BASE_URL}/simple/price`, {
      params: {
        ids: ids.join(','),
        vs_currencies: vsCurrencies.join(','),
      },
    });
    return response.data;
  } catch (error) {
    console.error('Error fetching crypto prices:', error);
    throw error;
  }
};

This code defines a function getCryptoPrices that takes an array of cryptocurrency IDs (e.g., ‘bitcoin’, ‘ethereum’) and an array of currencies (e.g., ‘usd’, ‘eur’) as arguments. It then uses axios to make a GET request to the CoinGecko API to retrieve the current prices for the specified cryptocurrencies. The function handles potential errors and returns the fetched data. Remember to replace 'your_api_key' with your actual CoinGecko API key if you have one, although it’s not strictly required for the basic functionality.

3. Creating the Alert Component

Create a new component called components/AlertForm.js. This component will allow users to set up price alerts. Add the following code:

import React, { useState } from 'react';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

const AlertForm = ({ cryptoData, onAddAlert }) => {
  const [selectedCrypto, setSelectedCrypto] = useState('');
  const [targetPrice, setTargetPrice] = useState('');
  const [alertType, setAlertType] = useState('above');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!selectedCrypto || !targetPrice) {
      toast.error('Please fill in all fields.');
      return;
    }

    const parsedTargetPrice = parseFloat(targetPrice);
    if (isNaN(parsedTargetPrice)) {
      toast.error('Target price must be a number.');
      return;
    }

    onAddAlert({
      cryptoId: selectedCrypto,
      targetPrice: parsedTargetPrice,
      alertType,
    });

    setSelectedCrypto('');
    setTargetPrice('');
    toast.success('Alert added successfully!');
  };

  return (
    <div>
      <h2>Set Price Alert</h2>
      
        <div>
          <label>Cryptocurrency:</label>
           setSelectedCrypto(e.target.value)}
          >
            Select Cryptocurrency
            {cryptoData &&
              Object.keys(cryptoData).map((cryptoId) => (
                
                  {cryptoId}
                
              ))}
          
        </div>
        <div>
          <label>Target Price:</label>
           setTargetPrice(e.target.value)}
          />
        </div>
        <div>
          <label>Alert Type:</label>
           setAlertType(e.target.value)}
          >
            Above
            Below
          
        </div>
        <button type="submit">Add Alert</button>
      
    </div>
  );
};

export default AlertForm;

This component uses the useState hook to manage the form inputs. It takes cryptoData (the price data fetched from the API) and an onAddAlert function (to handle adding a new alert) as props. The form allows the user to select a cryptocurrency, enter a target price, and select the alert type (above or below). It includes basic validation to ensure that all fields are filled and that the target price is a number. It also uses react-toastify to display success and error messages to the user.

4. Creating the Alert List Component

Create a new component called components/AlertList.js. This component will display the active price alerts. Add the following code:

import React from 'react';

const AlertList = ({ alerts, cryptoData, onDeleteAlert }) => {
  return (
    <div>
      <h2>Active Alerts</h2>
      {alerts.length === 0 ? (
        <p>No alerts set.</p>
      ) : (
        <ul>
          {alerts.map((alert, index) => {
            const currentPrice = cryptoData && cryptoData[alert.cryptoId] ? cryptoData[alert.cryptoId].usd : 'Loading...';
            return (
              <li>
                {alert.cryptoId.toUpperCase()} {alert.alertType} ${alert.targetPrice} (Current Price: ${currentPrice})
                <button> onDeleteAlert(index)}>Delete</button>
              </li>
            );
          })}
        </ul>
      )}
    </div>
  );
};

export default AlertList;

This component takes two props: alerts (an array of alert objects) and cryptoData (the current price data). It displays a list of active alerts, including the cryptocurrency, alert type, target price, and current price. It also includes a delete button for each alert, which calls the onDeleteAlert function (passed as a prop) to remove the alert.

5. Integrating the Components in the Main Page

Now, let’s integrate these components into your main page (pages/index.js). Replace the existing code in pages/index.js with the following:

import React, { useState, useEffect } from 'react';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { getCryptoPrices } from '../utils/api';
import AlertForm from '../components/AlertForm';
import AlertList from '../components/AlertList';

const Home = () => {
  const [cryptoData, setCryptoData] = useState(null);
  const [alerts, setAlerts] = useState([]);

  useEffect(() => {
    const fetchCryptoData = async () => {
      try {
        const data = await getCryptoPrices(['bitcoin', 'ethereum', 'litecoin'], ['usd']);
        setCryptoData(data);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };
    fetchCryptoData();

    const intervalId = setInterval(fetchCryptoData, 5000); // Refresh data every 5 seconds

    return () => clearInterval(intervalId);
  }, []);

  const handleAddAlert = (newAlert) => {
    setAlerts([...alerts, newAlert]);
  };

  const handleDeleteAlert = (index) => {
    const newAlerts = [...alerts];
    newAlerts.splice(index, 1);
    setAlerts(newAlerts);
  };

  useEffect(() => {
    if (cryptoData && alerts.length > 0) {
      alerts.forEach((alert) => {
        const currentPrice = cryptoData[alert.cryptoId]?.usd;
        if (currentPrice) {
          if (
            alert.alertType === 'above' &&
            currentPrice > alert.targetPrice
          ) {
            toast.success(
              `${alert.cryptoId.toUpperCase()} price is above ${alert.targetPrice}!
              Current Price: ${currentPrice}`,
              { autoClose: 5000 }
            );
          } else if (
            alert.alertType === 'below' &&
            currentPrice < alert.targetPrice
          ) {
            toast.error(
              `${alert.cryptoId.toUpperCase()} price is below ${alert.targetPrice}!
              Current Price: ${currentPrice}`,
              { autoClose: 5000 }
            );
          }
        }
      });
    }
  }, [cryptoData, alerts]);

  return (
    <div>
      
      <h1>Cryptocurrency Price Alert App</h1>
      
      
      {/* Display current prices */}
      {cryptoData && (
        <div>
          <h2>Current Prices</h2>
          {Object.entries(cryptoData).map(([cryptoId, data]) => (
            <p>
              {cryptoId.toUpperCase()}: ${data.usd}
            </p>
          ))}
        </div>
      )}
    </div>
  );
};

export default Home;

This code imports the necessary components and functions. It uses the useState hook to manage the cryptoData (the fetched price data) and alerts (the array of active alerts). The useEffect hook is used to fetch the cryptocurrency prices from the API on component mount and then at regular intervals (every 5 seconds). The handleAddAlert function is used to add new alerts to the alerts state, and the handleDeleteAlert function is used to delete alerts. The main return statement renders the AlertForm and AlertList components and displays the current prices of the cryptocurrencies. Importantly, the code also includes the logic to trigger notifications using react-toastify when the price alerts are triggered. The useEffect hook now also includes the logic to check the alerts against the current prices and trigger notifications when necessary.

6. Styling the Application (Optional)

To improve the appearance of your application, you can add some basic styling. Create a file named styles/globals.css in your project directory (if it doesn’t already exist) and add the following CSS:

body {
  font-family: sans-serif;
  margin: 20px;
}

h1 {
  text-align: center;
}

form {
  margin-bottom: 20px;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 5px;
}

label {
  display: block;
  margin-bottom: 5px;
}

input[type="number"],
select {
  width: 100%;
  padding: 8px;
  margin-bottom: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  box-sizing: border-box;
}

button {
  background-color: #4CAF50;
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background-color: #3e8e41;
}

ul {
  list-style: none;
  padding: 0;
}

li {
  padding: 10px;
  margin-bottom: 5px;
  border: 1px solid #eee;
  border-radius: 4px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

Import this CSS file into your pages/_app.js file to apply the styles to your entire application. If you do not have a pages/_app.js file, create one with the following content:

import '../styles/globals.css';

function MyApp({ Component, pageProps }) {
  return ;
}

export default MyApp;

7. Running the Application

To run your application, open your terminal, navigate to your project directory, and run the following command:

npm run dev

or

yarn dev

This will start the development server. Open your web browser and go to http://localhost:3000 to see your application in action.

Common Mistakes and Troubleshooting

  • CORS Errors: If you encounter CORS (Cross-Origin Resource Sharing) errors, it means your browser is blocking requests to the CoinGecko API. This is usually because the API doesn’t allow requests from your local development environment. You may need to use a proxy server or configure CORS settings in your browser or server.
  • API Rate Limits: CoinGecko has rate limits for their API. If you exceed the rate limits, your requests will be blocked. Consider implementing error handling and retries or obtaining an API key to increase your rate limit.
  • Incorrect API Endpoint: Double-check the API endpoint URL to ensure it is correct. Typos can easily lead to errors.
  • Data Not Displaying: If the data is not displaying, check the browser’s console for any errors. Also, verify that the API is returning the data in the expected format.
  • Notification Issues: If notifications are not working, ensure that the react-toastify library is correctly installed and imported. Also, check your browser’s notification settings.

Key Takeaways

  • You learned how to fetch real-time cryptocurrency price data using the CoinGecko API.
  • You built a user interface to set and manage price alerts.
  • You implemented a notification system to alert users when their price targets are met.
  • You gained experience with Next.js, React, API integration, and state management.

FAQ

1. Can I add more cryptocurrencies to track?

Yes, you can easily extend the application to track more cryptocurrencies. Simply add the cryptocurrency IDs to the getCryptoPrices function in utils/api.js and update the options in the select input in the AlertForm component.

2. How often does the app refresh the prices?

The app refreshes the prices every 5 seconds, as defined by the setInterval function in the useEffect hook. You can adjust this interval to suit your needs.

3. Can I customize the notification messages?

Yes, you can customize the notification messages in the useEffect hook in pages/index.js. Modify the text within the toast.success and toast.error functions to display the information you want.

4. How can I deploy this app?

You can deploy this Next.js app to various platforms, such as Vercel (recommended, as it’s the easiest), Netlify, or AWS. You’ll need to create an account on your chosen platform, connect your GitHub repository (or other code repository), and configure the deployment settings. Vercel is specifically designed for Next.js and makes the deployment process very straightforward.

5. Is an API Key Required?

While the code will work without an API key for the CoinGecko API, it is highly recommended to obtain a free API key. This will help you avoid rate limiting and ensure the app functions reliably, especially if you plan to use it frequently or deploy it for others to use.

This tutorial provides a solid foundation for building a cryptocurrency price alert app. Remember that this is just a starting point. You can further enhance this application by adding more features, such as historical price charts, portfolio tracking, and more sophisticated alert conditions. The possibilities are endless, and with each feature you add, you’ll deepen your understanding of Next.js and web development. As you continue to experiment and refine your skills, you’ll be well-equipped to tackle more complex projects and create innovative solutions. The knowledge gained from this project will undoubtedly serve as a valuable asset in your journey as a developer, enabling you to build increasingly sophisticated and useful applications.