Weather Forecast App using MERN Stack
Last Updated :
22 Mar, 2024
This project is a simple weather application built using React.js for the frontend and Node.js with Express.js for the backend. It allows users to check the current weather and forecast for a specific city. The backend retrieves weather data from the OpenWeatherMap API and stores it in a MongoDB database. The frontend displays the weather information and forecast in a user-friendly interface.
Output Preview: Let us have a look at how the final output will look like.

Prerequisites
Approach to Create Weather Forecast App
Backend:
- Uses Express.js to set up RESTful API endpoints.
- Utilizes mongoose to connect to a MongoDB database and store weather data.
- Retrieves weather data from the OpenWeatherMap API based on user requests.
Frontend:
- Uses React.js to create a user-friendly interface.
- Provides an input field for users to enter the city name.
- Retrieves weather data from the backend API and displays it to the user.
- Shows both current weather and forecast information.
Steps to Create the Project
Steps to Create the Backend
Project Structure:

Step 1: Create a directory for project
mkdir server
cd server
Step 2: Initialize npm:
npm init -y
Step 3: Install Dependencies:
npm install express mongoose cors axios
Step 4: Create a file named index.js & write the following code.
JavaScript
//server/index.js
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const axios = require('axios');
const app = express();
const PORT = process.env.PORT || 5000;
// Replace 'YOUR_MONGODB_URI' with your actual MongoDB connection URI
const MONGODB_URI = 'YOUR_MONGODB_URI/weatherforecast';
mongoose.connect(MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true });
app.use(cors());
app.use(express.json());
// Create a Mongoose model for weather data
const WeatherData = mongoose.model('WeatherData', {
city: String,
country: String,
temperature: Number,
description: String,
icon: String,
});
// Route to handle storing weather data
app.post('/api/weather', async (req, res) => {
try {
// Extract weather data from request body
const { city, country, temperature, description, icon } = req.body;
// Create a new document using the WeatherData model
const weatherData = new WeatherData({
city,
country,
temperature,
description,
icon,
});
// Save the weather data to the database
await weatherData.save();
// Respond with success message
res.json({ message: 'Weather data saved successfully' });
} catch (error) {
console.error('Error saving weather data:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
});
// Start the server
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Run Backend Server:
node index.js
DATABASE OUTPUT:

Steps to Create the Frontend:
Project Structure:

Step 1: Set up React frontend using the command.
npx create-react-app client
cd client
Step 2: Install the required dependencies.
npm install axios
Step 3: Create Frontend Components:
- Modify or replace the src/App.js and src/App.css and other files with code given as below
- In app.js if that API key is not working generate from openweathermap.org and replace it.
CSS
/*App.css*/
@import url('https://fonts.googleapis.com/css2?family=Concert+One:wght@300&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@700&display=swap');
html {
height: 100%;
}
body {
background: whitesmoke;
padding: 1rem 5rem;
font-family: 'Roboto', sans-serif;
text-transform: capitalize;
background: linear-gradient(45deg, rgba(183, 204, 248, 0.717), rgba(7, 43, 127, 0.679)), url('https://img.freepik.com/free-photo/blue-sky-with-cloud-closeup_150588-124.jpg?t=st=1710145731~exp=1710149331~hmac=312231e34af28df68a64a9b006a4a627d0f623f0ba6e19eb23e5aceae935e41e&w=360');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
.header h1 {
color: rgb(214, 147, 45);
text-decoration: underline;
font-family: 'Orbitron', sans-serif;
}
#input {
font-size: 18px;
padding: 5px 10px;
outline: none;
border: none;
border-radius: 15px;
background: aliceblue;
}
#search {
background: none;
padding: 5px 20px;
color: aliceblue;
outline: none;
background: cadetblue;
font-size: 17px;
border-radius: 15px;
cursor: pointer;
border: none;
}
.weather {
text-align: center;
color: aliceblue;
}
#city {
font-size: 30px;
}
.weather img {
width: 120px;
height: 120px;
border-radius: 50%;
background: rgba(240, 248, 255, 0.408);
}
#temperature {
font-size: 50px;
margin: 0;
margin-left: 30px;
margin-bottom: 10px;
}
.temp-box {
display: flex;
align-items: center;
justify-content: center;
margin: 30px 0;
}
#clouds {
font-size: 20px;
background: rgba(153, 205, 50, 0.778);
padding: 2px 20px;
border-radius: 15px;
}
main {
display: grid;
grid-column-gap: 25px;
grid-template-columns: 1fr 5px 1fr;
align-items: center;
margin: 0 50px;
color: white;
}
.next {
display: flex;
justify-content: space-between;
align-items: center;
margin: 10px 0;
}
.next p,
.next h3 {
margin: 3px 0;
}
.forecstD {
margin: 20px 50px;
color: aliceblue;
}
.weekF {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.cast-header {
color: aliceblue;
background: rgba(254, 189, 132, 0.539);
width: max-content;
padding: 5px 15px;
border-radius: 20px;
font-size: 18px;
margin-bottom: 5px;
}
.divider1,
.divider2 {
background: rgba(254, 189, 132, 0.539);
height: 200px;
border-radius: 5px;
}
.divider2 {
height: 5px;
width: 30%;
margin: 0 auto;
}
.time,
.date {
color: rgb(254, 189, 132);
}
.desc {
color: rgb(196, 255, 77);
}
JavaScript
//src/App.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './App.css';
const apikey = "feff206daa60b539abe8fae8f2ab7f29";
function App() {
const [city, setCity] = useState('');
const [weatherData, setWeatherData] = useState(null);
useEffect(() => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
const { latitude, longitude } = position.coords;
const url = `http://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${apikey}`;
fetchWeatherData(url);
});
}
}, []);
const fetchWeatherData = async (url) => {
try {
const response = await axios.get(url);
const data = response.data;
console.log(data);
weatherReport(data);
setWeatherData(data);
// Send data to backend for storage
saveWeatherData(data);
} catch (error) {
console.error('Error fetching weather data:', error);
}
};
const searchByCity = async () => {
try {
const urlsearch = `http://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apikey}`;
const response = await axios.get(urlsearch);
const data = response.data;
console.log(data);
weatherReport(data);
setWeatherData(data);
// Send data to backend for storage
saveWeatherData(data);
} catch (error) {
console.error('Error fetching weather data:', error);
}
setCity('');
};
const saveWeatherData = async (data) => {
try {
const response = await axios.post('http://localhost:5000/api/weather', {
city: data.name,
country: data.sys.country,
temperature: Math.floor(data.main.temp - 273),
description: data.weather[0].description,
icon: data.weather[0].icon,
});
console.log('Weather data saved to database:', response.data);
} catch (error) {
console.error('Error saving weather data to database:', error);
}
};
const weatherReport = async (data) => {
const urlcast = `http://api.openweathermap.org/data/2.5/forecast?q=${data.name}&appid=${apikey}`;
try {
const response = await axios.get(urlcast);
const forecast = response.data;
console.log(forecast.city);
hourForecast(forecast);
dayForecast(forecast);
console.log(data);
document.getElementById('city').innerText = data.name + ', ' + data.sys.country;
console.log(data.name, data.sys.country);
console.log(Math.floor(data.main.temp - 273));
document.getElementById('temperature').innerText = Math.floor(data.main.temp - 273) + ' °C';
document.getElementById('clouds').innerText = data.weather[0].description;
console.log(data.weather[0].description);
let icon1 = data.weather[0].icon;
let iconurl = "http://api.openweathermap.org/img/w/" + icon1 + ".png";
document.getElementById('img').src = iconurl;
} catch (error) {
console.error('Error fetching forecast data:', error);
}
};
const hourForecast = (forecast) => {
document.querySelector('.templist').innerHTML = '';
for (let i = 0; i < 5; i++) {
var date = new Date(forecast.list[i].dt * 1000);
console.log((date.toLocaleTimeString(undefined, 'Asia/Kolkata')).replace(':00', ''));
let hourR = document.createElement('div');
hourR.setAttribute('class', 'next');
let div = document.createElement('div');
let time = document.createElement('p');
time.setAttribute('class', 'time');
time.innerText = (date.toLocaleTimeString(undefined, 'Asia/Kolkata')).replace(':00', '');
let temp = document.createElement('p');
temp.innerText = Math.floor((forecast.list[i].main.temp_max - 273)) + ' °C' + ' / ' + Math.floor((forecast.list[i].main.temp_min - 273)) + ' °C';
div.appendChild(time);
div.appendChild(temp);
let desc = document.createElement('p');
desc.setAttribute('class', 'desc');
desc.innerText = forecast.list[i].weather[0].description;
hourR.appendChild(div);
hourR.appendChild(desc);
document.querySelector('.templist').appendChild(hourR);
}
};
const dayForecast = (forecast) => {
document.querySelector('.weekF').innerHTML = '';
for (let i = 8; i < forecast.list.length; i += 8) {
console.log(forecast.list[i]);
let div = document.createElement('div');
div.setAttribute('class', 'dayF');
let day = document.createElement('p');
day.setAttribute('class', 'date');
day.innerText = new Date(forecast.list[i].dt * 1000).toDateString(undefined, 'Asia/Kolkata');
div.appendChild(day);
let temp = document.createElement('p');
temp.innerText = Math.floor((forecast.list[i].main.temp_max - 273)) + ' °C' + ' / ' + Math.floor((forecast.list[i].main.temp_min - 273)) + ' °C';
div.appendChild(temp);
let description = document.createElement('p');
description.setAttribute('class', 'desc');
description.innerText = forecast.list[i].weather[0].description;
div.appendChild(description);
document.querySelector('.weekF').appendChild(div);
}
};
return (
<div>
<div className="header">
<h1>WEATHER APP</h1>
<div>
<input
type="text"
name=""
id="input"
placeholder="Enter city name"
value={city}
onChange={(e) => setCity(e.target.value)}
/>
<button id="search" onClick={searchByCity}>
Search
</button>
</div>
</div>
<main>
<div className="weather">
<h2 id="city">Delhi,IN</h2>
<div className="temp-box">
<img src="/weathericon.png" alt="" id="img" />
<p id="temperature">26 °C</p>
</div>
<span id="clouds">Broken Clouds</span>
</div>
<div className="divider1"></div>
<div className="forecstH">
<p className="cast-header">Upcoming forecast</p>
<div className="templist">
{/* Hourly forecast will be rendered here */}
</div>
</div>
</main>
<div className="forecstD">
<div className="divider2"></div>
<p className="cast-header"> Next 4 days forecast</p>
<div className="weekF">
{/* Daily forecast will be rendered here */}
</div>
</div>
</div>
);
}
export default App;
To start frontend code:
npm start
Output:
Weather Forecast final output
Similar Reads
Chat Website using MERN Stack The "Chat Website" project is a dynamic web application that is used for real-time communication. The MERN stack, comprised of MongoDB, Express.js, React.js, and Node.js, is a powerful combination of technologies for developing robust and scalable web applications. In this article, we'll explore the
4 min read
Create a Weather App with Forecast using React-Native React-Native is an open-source framework used to develop cross-platform applications i.e., you can write code in React-Native and publish it as an Android or IOS app. In this article, we will build a weather app using React-Native. The app contains two features:Getting the current weather of a given
5 min read
Weather Application using ReactJS In this article, we will develop an Interactive Weather Application using ReactJS Framework. The developed application will provide real-time weather information to the user for the city they have searched. If the user searches, for the wrong city, an Error message is also displayed to the user, sta
5 min read
Create a Weather app using Flask | Python Prerequisite : Flask installation Flask is a lightweight framework written in Python. It is lightweight because it does not require particular tools or libraries and allow rapid web development. today we will create a weather app using flask as a web framework. this weather web app will provide curr
2 min read
Social Fitness App using MERN Stack Creating a Social Fitness App is a great opportunity for anyone who wants to understand full-stack development. In this article, we'll make a Social Fitness App from scratch using the MERN(MongoDB, Express.js, React, Node.js) stack. This project will help navigate backend development, and teach you
9 min read
Fantasy Sports App using MERN Stack In today's digital world, sports enthusiasts are always on the lookout for new and engaging ways to immerse themselves in their favorite games. Fantasy sports apps provide the perfect platform for fans to experience the thrill of team management, player selection, and match prediction. In this artic
12 min read