Project: Weather App
Table of Contents + −
In the previous lesson, we built a calculator that worked entirely with values already on the page. Now let’s build something that reaches out to the internet for live data: a weather app that fetches the current weather for any city you type in.
🎯 What We’ll Build
We are building a small app with a text box, a search button, and a result area. You type a city name, press the button, and the app asks a public weather service for that city’s current conditions. It then shows the temperature and a short description like “clear sky” or “light rain”.
This project ties together everything you have learned about asynchronous code. It uses fetch to make the request, async and await to handle the waiting, try and catch to deal with problems, and the DOM to put the answer on screen.
🧱 The HTML
The page needs three things: an input where the user types a city, a button to start the search, and an empty element where the result will appear.
<input id="city" type="text" placeholder="Enter a city" /><button id="search">Search</button><div id="result"></div>Let’s walk through what each line gives us:
- The
<input id="city">is the text box where the user types a city name. Theplaceholdershows faint hint text until they start typing. - The
<button id="search">is the button that kicks off the search when clicked. - The
<div id="result">starts empty because there is nothing to show until the user searches; we will fill it with the weather later. - The
idon each element is what lets the JavaScript find it.
⚙️ The JavaScript
Here is the full script that powers the app. Read it once, and then we will walk through each part.
const apiKey = "YOUR_API_KEY";
const cityInput = document.getElementById("city");const searchButton = document.getElementById("search");const result = document.getElementById("result");
async function getWeather(city) { const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${apiKey}`;
try { const response = await fetch(url);
if (!response.ok) { throw new Error("City not found"); }
const data = await response.json();
const temperature = data.main.temp; const description = data.weather[0].description;
result.textContent = `${city}: ${temperature}°C, ${description}`; } catch (error) { result.textContent = `Sorry, something went wrong: ${error.message}`; }}
searchButton.addEventListener("click", () => { const city = cityInput.value.trim();
if (city === "") { result.textContent = "Please enter a city name."; return; }
getWeather(city);});Let’s step through the script section by section:
- The first line stores the API key, and the next three lines grab the input, button, and result area so we can use them later.
- The
getWeatherfunction is markedasync, which lets us useawaitinside it. We build the requesturlfrom the city name and the key. await fetch(url)sends the request and pauses until the server answers.- We check
response.okbefore trusting the data. If the server returns an error, such as a city that does not exist,response.okisfalse, so wethrowan error to jump straight into thecatchblock. - When the response is good,
await response.json()reads the body and turns it into a JavaScript object. - We pull the temperature out of
data.main.tempand the text description out ofdata.weather[0].description, then write a friendly sentence into the result area withtextContent. - The
catchblock runs whenever anything insidetryfails, whether the network is down or the city is wrong. Instead of leaving the user staring at a blank page, it shows a clear message. - Finally, the click listener reads the input, trims off extra spaces, refuses to search on an empty box, and otherwise calls
getWeather.
You need a free API key
This app talks to OpenWeatherMap, which
requires a free account and an API key. Sign up, copy your key, and paste it
in place of "YOUR_API_KEY". Keep keys out of public code in real projects.
In production, hide the key behind your own server so visitors cannot read it
from the browser.
🚀 Try It Yourself!
Once the basic version works, try these enhancements one at a time.
- Add a loading message by setting
result.textContent = "Loading..."right before thefetchcall. - Show more details from the response, such as humidity (
data.main.humidity) or the “feels like” temperature (data.main.feels_like). - Let the user press Enter to search by listening for the
keydownevent on the input. - Add a button to switch between Celsius and Fahrenheit by changing the
unitsvalue in the URL. - Display a weather icon using the
data.weather[0].iconcode from the response.
🧩 What You’ve Learned
- ✅ How to send a request to a public API with
fetch - ✅ How
asyncandawaitkeep asynchronous code readable - ✅ How to turn a JSON response into a usable object with
response.json() - ✅ How to handle failures gracefully with
tryandcatch - ✅ How to display live data by updating the DOM
🚀 What’s Next?
You can now fetch real data and show it on a page. Next, we will build an app that manages a series of questions and tracks a score. Let’s continue to the Quiz App.