Weather App Tutorial: Easy Steps to Follow
Introduction🤖
This is a blog on a weather application that covers all of the current data for any area in the world, assisting users in making decisions based on the weather conditions displayed on this app. as it nearly includes major weather aspects such as current weather, current day weather, AQI, humidity, wind speed, dawn and sunset.
In this blog, I'll explain how I made this fantastic application, from design to code.
Technology Used💻
Client: Html, Css, Javascript
Server: Node.js, Express.js
API: Open Weather Api
Figma Design🖌️
I first designed this weather application on Figma, a collaborative web platform for interface design with additional offline features provided by desktop apps. I used this for various reasons, one of which was free.
Below is my Design👇
Step 1: Structure of Project🏖️
The structure of any application is critical because it allows any other person who wants to contribute to the application to easily understand what the app is saying, or any new developer joining their team to learn how things work. While creating an architecture, we make our application more understandable. This allows developers in a company to separate their tasks to work on specific files and contribute to one app.
Check the Structure of the application👇
As you can see from the image above, I believe you understand what this is expressing. If not, carry on to the next line.
There are 3 dots in the image, one is green which refers to the main directory project, another is purple which refers to specific usage folders and the last one is orange which refers to files see below their descriptions.
Green is the application project's primary directory (folder), which contains all of the files, subfolders, images, package files, and so on.
Ex-
Weather-App folder in the imagePurple one's folders are used for certain functions of the application, and they also contain sub-folders and files within them.
Ex-
Assets, WeatherImg, Client, and Server in the above structureOrange files include a readme, HTML, JS, CSS, images, gitignore, env, and package files.
Step 2: Initiating the Project👍
Follow the steps outlined below:-
Firstly open your git bash terminal, PowerShell or whatever you use and then type the command
mkdir Weather-App
this will create the folder for your app. If you do not know the commands go to the Cheatsheet📄 that covers all terminal commands.Now change the directory in your terminal to the weather app by command
cd Weather-App
Create 3 more folders one for Assets (usually contains the images for the application), another for Client(contains the frontend files that we display too show to users) and last for a server (contains the backend files that users don't see) by typing in the terminal -
mkdir Assets Client Server
Again change the directory in the terminal to
Weather-App/Assets/
by the commandcd Assests
it will go to the Assets folder, you can also check if there is anything in that Assets folder by typing a commanddir
Now I have another
weatherImg
folder in Assets so create it the same as above bymkdir weatherImg
Now change the directory to Client and make three files i.e.
index.html
,style.css
andclient.js
by simply changing the directory to the Client folder and typing the commandtouch index.html style.css client.js
Now, let's shift to VsCode, which will help us do our tasks faster and easier. will look like the below figure
Open your folder in VsCode and initialize your project to Git(version control system) and Node(javascript framework) by opening a new terminal & then 1'st type command
git init
after that typenpm init
for node.js it will add automatically thepackage.json
file & othernode_modules
let's install some dependencies required in our application type the command -
npm install express axios dotenv
Now create a
.env
and.gitignore
file through the GUI in the VsCodeIn
.env
file you have to add the secret key of your weather API which you have to get by simply creating the free account on WeatherAPI & getting the secret key from your profile, see below the exampleExample -
API_KEY = d8htgh5cb9b66hjy94bba5c5oi542308 // dummy api key
.gitignore file is used to not push the secret code and bulky node files to the GitHub, so add the below file name in that file
# Ignore .env file .env node_modules/
Now everything is ready only the code and some modules are required, so follow the next Backend Part.
Step 3: Backend🔥
Server.js Code - Explanation is given with comments in the code
// server/server.js
const express = require('express'); // import the express framework
const path = require('path'); // import the path module ,provide utilities working with file & directory path
require('dotenv').config(); // import & configure dotenv, loads environment variables from a .env file
const app = express(); //initializes a new express application
const PORT = process.env.PORT || 3000;
// Serve static files from the client directory
app.use(express.static(path.join(__dirname, '../client')));
// Serve static files from the assets directory
app.use('/assets', express.static(path.join(__dirname, '../Assets')));
// API endpoint to fetch weather data
const weatherRouter = require('./weather');
app.use('/weather', weatherRouter);
// Start the server
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Weather.js Code - Explanation is given with comments in the code
// server/weather.js
const express = require('express');
const axios = require('axios');
const router = express.Router();
require('dotenv').config();
const apiKey = process.env.API_KEY;
const apiUrl = 'https://api.weatherapi.com/v1/current.json';
// Modify the route to fetch both current weather and forecast data
router.get('/:location', async (req, res) => {
try {
const {location} = req.params;
// Prepare URLs for both current weather and forecast
const currentWeatherUrl = `${apiUrl}?key=${apiKey}&q=${location}&aqi=yes`;
const forecastUrl = `https://api.weatherapi.com/v1/forecast.json?key=${apiKey}&q=${location}&days=3&aqi=yes&alerts=no`; // Adjust 'days' as needed
// Make both API calls concurrently
const [currentResponse, forecastResponse] = await Promise.all([
axios.get(currentWeatherUrl),
axios.get(forecastUrl)
]);
// Combine both responses into one object
const combinedData = {
current: currentResponse.data,
forecast: forecastResponse.data
};
res.json(combinedData);
} catch (error) {
console.error('Error fetching weather data:', error);
res.status(500).json({ error: 'Error fetching weather data' });
}
});
module.exports = router;
Now let us build the client side part as the frontend code.
Step 4: Frontend❄️
Index.html- Explanation is given with comments in the code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Kanit:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet">
<title>Weather's Ok</title>
</head>
<body>
<div class="src-div">
<input type="text" placeholder="Enter city name" id="inpBar">
<button class="src-icon"><img src="/Assets/Search-btn.png" alt="Search button"></button>
</div>
<div>
<div class="weather-div">
<div class="div1">
<div>
<p class="cityName">New York</p>
<p class="cityTemp">25°C</p>
</div>
<div>
<p class="cityCond">Thunderstorm</p>
<p class="date">Monday,28 April</p>
</div>
</div>
<div class="div2">
<img src="/Assets/WeatherImg/sunny.png" class="weatherImg" alt="weather Images">
</div>
</div>
<div class="hourlyDiv">
<div class="hour">
<img src="/Assets/WeatherImg/partly-cloudy.png" alt="">
<p class="morn" >32°C</p>
<p id="time1" >07:00 am</p>
</div>
<div class="hour">
<img src="/Assets/WeatherImg/cloudy.png" alt="">
<p class="even" >32°C</p>
<p id="time2">06:00 pm</p>
</div>
<div class="hour">
<img src="/Assets/WeatherImg/hail.png" alt="">
<p class="night" >32°C</p>
<p id="time3">11:00 pm</p>
</div>
</div>
<div>
<img class="vecImg" src="/Assets/Vector 4.png" alt="AppDesign">
</div>
<div class="weatherMore">
<div>
<p>Wind</p>
<p id="wind">20km/h</p>
</div>
<div>
<p>Air Quality</p>
<p class="aqi">104 AQI</p>
</div>
<div>
<p>Humidity</p>
<p class="humid">18%</p>
</div>
</div>
<div class="weatherMore">
<div>
<img src="/Assets/WeatherImg/1.png" alt="">
<p id="rise">Sunrise</p>
<p class="Rise">05:14 am</p>
</div>
<div>
<img src="/Assets/WeatherImg/4.png" alt="">
<p id="set">Sunset</p>
<p class="Set">07:15 am</p>
</div>
</div>
</div>
<script src="client.js"></script>
</body>
</html>
Style.css - Explanation is given with comments in the code
/*Added few code because of length refer my github repo for code*/
body {
background-color: #ff9d54;
margin: 0;
padding: 0;
height: 100%;
}
.src-div {
height: 50px;
display: flex;
flex-direction: row;
margin: 10px 5px 5px 5px;
justify-content: center;
gap: 5px;
}
.src-icon {
background-color: #ffffff;
border-radius: 50%;
width: 55px;
display: flex;
justify-content: center;
align-items: center;
border-color: transparent;
cursor: pointer;
}
#inpBar {
width: 100%;
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 1rem;
background: #344A53;
color: #ff9d54;
text-align: center;
text-decoration: none;
border-radius: 30px;
border-color: transparent;
}
client.js- Explanation is given with comments in the code
// client/client.js
const searchBtn = document.querySelector('.src-icon')
searchBtn.addEventListener('click', async () => {
//retreives the value from the input element with the ID
const location = document.getElementById('inpBar').value;
try {
const response = await fetch(`/weather/${location}`);
const weatherData = await response.json();
console.log(weatherData); // helps to check output in inspect view
// Call your function to update the DOM with weatherData
updateWeatherInfo(weatherData);
} catch (error) {
console.error('Error fetching weather:', error);
}
});
function updateWeatherInfo(data) {
try {
const current = data.current;
const forecast = data.forecast;
const weatherIcon = document.querySelector('.weatherImg');
document.querySelector('.cityName').innerText = current.location.name;
document.querySelector('.cityTemp').innerText = `${current.current.temp_c}°C`;
document.querySelector('.cityCond').innerText = current.current.condition.text;
document.querySelector('.date').innerText = new Date(current.current.last_updated).toLocaleDateString();
document.querySelector('.aqi').innerText = `${current.current.air_quality.pm10} AQI`;
document.querySelector('.humid').innerText = `${current.current.humidity}%`;
document.getElementById('wind').innerText = `${current.current.wind_kph} km/h`;
document.querySelector('.Rise').innerText = forecast.forecast.forecastday[0].astro.sunrise;
document.querySelector('.Set').innerText = forecast.forecast.forecastday[0].astro.sunset;
document.querySelector('.morn').innerText = `${forecast.forecast.forecastday[0].hour[7].temp_c}°C`;
document.querySelector('.even').innerText = `${forecast.forecast.forecastday[0].hour[18].temp_c}°C`;
document.querySelector('.night').innerText = `${forecast.forecast.forecastday[0].hour[23].temp_c}°C`;
if(current.current.condition.text === 'Sunny'){
weatherIcon.src = 'Assets/WeatherImg/sunny.png';
}
else if(current.current.condition.text === 'Partly cloudy'){
weatherIcon.src = 'Assets/WeatherImg/partlycloudy.png';
}
else if(current.current.condition.text === 'Cloudy'){
weatherIcon.src = 'Assets/WeatherImg/cloudy.png';
}
else if(current.current.condition.text === 'Mist'){
weatherIcon.src = 'Assets/WeatherImg/drizzle.png';
}
else if(current.current.condition.text === 'Patchy rain possible'){
weatherIcon.src = 'Assets/WeatherImg/showers.png';
}
else if(current.current.condition.text === 'Light rain shower'){
weatherIcon.src = 'Assets/WeatherImg/showers.png';
}
else if(current.current.condition.text === 'Fog'){
weatherIcon.src = 'Assets/WeatherImg/partlycloudy.png';
}
else if(current.current.condition.text === 'Light drizzle'){
weatherIcon.src = 'Assets/WeatherImg/drizzle.png';
}
else if(current.current.condition.text === 'Heavy rain'){
weatherIcon.src = 'Assets/WeatherImg/showers.png';
}
else if(current.current.condition.text === 'Partly cloudy'){
weatherIcon.src = 'Assets/WeatherImg/hail.png';
}
else if(current.current.condition.text === 'Heavy snow'){
weatherIcon.src = 'Assets/WeatherImg/snow.png';
}
else if(current.current.condition.text === 'Patchy light rain with thunder'){
weatherIcon.src = 'Assets/WeatherImg/thunderstorms.png';
}
else if(current.current.condition.text === 'Moderate or heavy rain with thunder'){
weatherIcon.src = 'Assets/WeatherImg/thunderstorms.png';
}
else{
weatherIcon.src = 'Assets/WeatherImg/sunny.png';
}
} catch (error) {
console.error('Error updating weather info:', error);
}
}
Step 5: Run the Application🏃➡️
To run the application simply go to your terminal and type the command -
node server/server.js
and hit enter you will see the link of the localhost after clicking the link you will be redirected to your default browser.
Conclusion
Follow Me On Socials :
Like👍| Share📲| Comment💭
Subscribe to my newsletter
Read articles from MOHD NEHAL KHAN directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
MOHD NEHAL KHAN
MOHD NEHAL KHAN
I am a student at Manipal University Jaipur and a web developer, learning and exploring tech stack in web development and implementing in my projects