Project 2: Weather App

📖 Concept

Build a weather application using the Fetch API and async/await. This project practices API integration, async programming, error handling, and dynamic UI updates.

Features:

  • Search by city name or use geolocation
  • Display current weather (temperature, humidity, wind, conditions)
  • 5-day forecast
  • Weather icons and background changes
  • Recent searches history

API: OpenWeatherMap free tier (or similar) Concepts practiced: fetch, async/await, try/catch, JSON parsing, Geolocation API, localStorage, template literals

💻 Code Example

codeTap to expand ⛶
1// Weather App — API Integration
2
3class WeatherApp {
4 constructor(apiKey) {
5 this.apiKey = apiKey;
6 this.baseURL = "https://api.openweathermap.org/data/2.5";
7 this.recentSearches = JSON.parse(
8 localStorage.getItem("recentSearches") || "[]"
9 );
10 }
11
12 async getWeather(city) {
13 try {
14 const response = await fetch(
15 `${this.baseURL}/weather?q=${encodeURIComponent(city)}&appid=${this.apiKey}&units=metric`
16 );
17 if (!response.ok) {
18 if (response.status === 404) throw new Error("City not found");
19 throw new Error(`HTTP ${response.status}`);
20 }
21 const data = await response.json();
22 this.saveSearch(city);
23 return this.formatWeather(data);
24 } catch (error) {
25 console.error("Weather fetch failed:", error);
26 throw error;
27 }
28 }
29
30 async getForecast(city) {
31 const response = await fetch(
32 `${this.baseURL}/forecast?q=${encodeURIComponent(city)}&appid=${this.apiKey}&units=metric`
33 );
34 if (!response.ok) throw new Error("Forecast unavailable");
35 const data = await response.json();
36 return this.formatForecast(data);
37 }
38
39 async getByLocation() {
40 return new Promise((resolve, reject) => {
41 navigator.geolocation.getCurrentPosition(
42 async (pos) => {
43 const { latitude: lat, longitude: lon } = pos.coords;
44 const response = await fetch(
45 `${this.baseURL}/weather?lat=${lat}&lon=${lon}&appid=${this.apiKey}&units=metric`
46 );
47 resolve(this.formatWeather(await response.json()));
48 },
49 reject,
50 { timeout: 10000 }
51 );
52 });
53 }
54
55 formatWeather(data) {
56 return {
57 city: data.name,
58 country: data.sys.country,
59 temp: Math.round(data.main.temp),
60 feelsLike: Math.round(data.main.feels_like),
61 humidity: data.main.humidity,
62 wind: data.wind.speed,
63 description: data.weather[0].description,
64 icon: data.weather[0].icon,
65 iconURL: `https://openweathermap.org/img/wn/${data.weather[0].icon}@2x.png`
66 };
67 }
68
69 formatForecast(data) {
70 // Group by day, take noon readings
71 const daily = data.list
72 .filter(item => item.dt_txt.includes("12:00"))
73 .slice(0, 5)
74 .map(item => ({
75 date: new Date(item.dt * 1000).toLocaleDateString("en", {
76 weekday: "short"
77 }),
78 temp: Math.round(item.main.temp),
79 icon: item.weather[0].icon,
80 description: item.weather[0].description
81 }));
82 return daily;
83 }
84
85 saveSearch(city) {
86 this.recentSearches = [
87 city,
88 ...this.recentSearches.filter(c => c !== city)
89 ].slice(0, 5);
90 localStorage.setItem(
91 "recentSearches",
92 JSON.stringify(this.recentSearches)
93 );
94 }
95}
96
97// Usage
98const app = new WeatherApp("YOUR_API_KEY");
99
100async function handleSearch(city) {
101 const loadingEl = document.querySelector("#loading");
102 const errorEl = document.querySelector("#error");
103 const weatherEl = document.querySelector("#weather");
104
105 loadingEl.style.display = "block";
106 errorEl.style.display = "none";
107
108 try {
109 const [weather, forecast] = await Promise.all([
110 app.getWeather(city),
111 app.getForecast(city)
112 ]);
113 renderWeather(weather);
114 renderForecast(forecast);
115 } catch (error) {
116 errorEl.textContent = error.message;
117 errorEl.style.display = "block";
118 } finally {
119 loadingEl.style.display = "none";
120 }
121}

🏋️ Practice Exercise

Build It Yourself:

  1. Get a free API key from OpenWeatherMap
  2. Build the search UI with autocomplete for city names
  3. Display current weather with themed backgrounds/icons
  4. Add 5-day forecast with horizontal scrollable cards
  5. Implement geolocation-based weather detection
  6. Save recent searches to localStorage
  7. Bonus: Add unit toggle (Celsius/Fahrenheit)

⚠️ Common Mistakes

  • Exposing API keys in client-side code — use environment variables or a proxy server

  • Not handling the case when geolocation permission is denied

  • Not URL-encoding the city name — spaces and special characters break the URL

  • Forgetting to show loading state while fetching — app feels unresponsive

  • Not debouncing search input — too many API calls on every keystroke

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for Project 2: Weather App. Login to unlock this feature.