The weather app is the classic "I can consume APIs" project โ async code, real data, error states, all in one afternoon.
The core (free OpenWeather key)
async function getWeather(city) {
const KEY = "your_api_key";
const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${KEY}`;
const res = await fetch(url);
if (res.status === 404) throw new Error("City not found");
if (!res.ok) throw new Error("Weather service unavailable");
return res.json();
}
form.addEventListener("submit", async (e) => {
e.preventDefault();
card.innerHTML = `<div class="spinner"></div>`;
try {
const d = await getWeather(input.value.trim());
card.innerHTML = `
<h2>${d.name}, ${d.sys.country}</h2>
<div class="temp">${Math.round(d.main.temp)}ยฐC</div>
<p>${d.weather[0].description} ยท feels like ${Math.round(d.main.feels_like)}ยฐ</p>
<p>๐ง ${d.main.humidity}% ๐ฌ ${d.wind.speed} m/s</p>`;
} catch (err) {
card.innerHTML = `<p class="error">${err.message}</p>`;
}
});Level it up for the portfolio
- 5-day forecast (the /forecast endpoint) rendered as cards
- "Use my location" via the Geolocation API
- Background gradient that changes with conditions
- Remember the last city in localStorage
Note: the free key is client-visible โ fine for portfolios; real apps proxy it through a backend. Saying that sentence in an interview earns points.