# Crafting a Cutting-Edge Weather App: 
A Journey with React, Tailwind, Vite, and GSAP

Weather apps are one of the most common beginner-friendly projects, but turning them into something **production-grade** is another story. When I took on the [Frontend Mentor Weather App Challenge](https://www.frontendmentor.io/challenges/weather-app-K1FhddVm49), I decided not just to build a simple app that shows the temperature, but to go deeper:

* Add **progressive web app (PWA)** features
    
* Make it **responsive** across devices
    
* Enhance the **user experience with animations**
    
* Provide **unit switching & custom dropdowns**
    
* Include **favorites, compare lists, and toast notifications**
    
* And even a **unique 5-second GSAP intro animation** to make it stand out.
    

In this article, I’ll take you through the process of building this project, the tools and techniques I used, the challenges I faced, and the lessons I learned along the way.

---

## Why Build Another Weather App?

It’s fair to ask: why a weather app?

The truth is, weather apps are the perfect sandbox for practicing **API integration, state management, UI design, and accessibility**. Almost every feature you might need in a larger app—searching, persisting data, handling errors, toggling views—can be prototyped in a weather app.

For me, the motivation was twofold:

1. To practice building a **PWA** from scratch, and
    
2. To polish a project to **portfolio-ready quality** instead of just a quick demo.
    

---

## Tech Stack & Tools

Here’s what I used to build the app:

* **React** – The backbone of the UI
    
* **Vite** – Lightning-fast dev/build tool
    
* **Tailwind CSS** – Utility-first styling
    
* **React Hot Toast** – For in-app notifications
    
* **GSAP** – For animated text intro and transitions
    
* **Vite PWA plugin** – To make the app installable and offline-friendly
    
* **Open-Meteo API** – Free weather API with hourly/daily forecasts
    

---

## Core Features

### 🔎 City Search with Debouncing

One of the first features was a search bar to look up cities. A common mistake is making API calls on every keystroke. Instead, I implemented **debouncing**, so the API only gets called once the user pauses typing.

```js
const [query, setQuery] = useState("");
const debouncedQuery = useDebounce(query, 500);

useEffect(() => {
  if (debouncedQuery) {
    fetchWeather(debouncedQuery);
  }
}, [debouncedQuery]);
```

This not only reduces API calls but also improves responsiveness.

---

### 🌤 Current Weather Display

The main card shows:

* Current temperature
    
* Weather icon
    
* Location details (city, country)
    
* Extra metrics: “feels like”, humidity, wind speed, precipitation
    

This gave users **at-a-glance clarity** while still letting them drill down into more data.

---

### 📅 7-Day Forecast

The daily forecast section shows each day’s:

* High/low temperatures
    
* Weather icons
    

I structured it with a **horizontal scrollable card layout** so users on mobile could swipe through comfortably.

---

### 🕒 Hourly Forecast with Scrollable Cards

This was one of the trickiest parts. The hourly forecast for a selected day is displayed in a scrollable container. To make it professional:

* I hid default browser scrollbars with **custom Tailwind classes**.
    
* Each hourly card shows the weather icon, time, and temperature.
    
* The user can switch days via a dropdown, which filters the hourly list dynamically.
    

```jsx
<div className="scrollbar-hide mt-4 flex h-[620px] flex-col gap-4 overflow-y-auto">
  {filteredHourlyForecast?.map((hour, index) => (
    <HourlyCard key={hour.time} hour={hour} i={index} />
  ))}
</div>
```

This created a **clean, card-based UI** while keeping it functional.

---

### ⚙️ Units Dropdown

I wanted to go beyond the typical “Celsius ↔ Fahrenheit” toggle. The dropdown allows:

* Switching the **entire system** (metric ↔ imperial)
    
* Individually changing:
    
    * Temperature (°C / °F)
        
    * Wind speed (km/h / mph)
        
    * Precipitation (mm / in)
        

To achieve this, I built a **dropdown** inspired by professional Shadn UI.

---

### ⭐ Favorites & Compare

Two features that added polish were:

* **Favorites** – Save cities to localStorage for quick access later
    
* **Compare** – Add cities to a “compare list” at the bottom of the screen
    

When a city is added to compare, a **toast notification** appears:

> “Added to compare list at the bottom, select another city too”

This subtle feedback improves UX tremendously.

---

### 📱 PWA Support

A huge goal was making this installable. Using `vite-plugin-pwa`, I:

* Added a manifest with icons of all required sizes
    
* Ensured rich install banners show up
    

This means users can **add it to their home screen** and even use it with no network.

---

### ✨ GSAP Intro Animation

Here’s where the app really stands out. I wanted the first 5 seconds to **feel cinematic**. Using **GSAP’s** , I animated the app title.

* Fades in smoothly
    
* After 5 seconds, the intro transitions into the main weather dashboard.
    

This animation is **subtle but memorable**. It sets the app apart from most weather apps that just jump into content.

---

## Challenges & Solutions

### 1\. **Scrollbar Styling**

Browsers handle scrollbars differently, and Tailwind doesn’t support this natively. I used the `scrollbar-hide` custom class to remove them and applied **custom classes** for consistent styling.

### 2\. **Dropdown UX**

The default dropdown looked from Shadncn UI, ensuring it was responsive and accessible.

### 3\. **PWA Manifest Icons**

Initially, the install banner looked broken because I hadn’t provided icons in all required sizes. Tools like **RealFaviconGenerator** helped fix that.

### 4\. **API Rate Limits**

The Open-Meteo API is free but can fail if spammed. Debouncing search input was crucial to avoid hitting rate limits.

---

## What I Learned

This project reinforced several concepts:

* **API integration best practices** (debouncing, error handling)
    
* **PWA setup** (manifest, service workers, caching)
    
* **Animations for UX** (GSAP intro, smooth dropdowns, hover states)
    
* **State management & persistence** with localStorage
    
* **UI polish** (toasts, icons, scrollbars, responsive layout)
    

The biggest lesson was: **little details make a big difference**. A toast here, a smooth intro animation there, custom icons—these elevate a simple weather app into something that feels professional.

---

## Future Improvements

Some areas I’d like to improve:

* Pre-caching API responses for offline usage
    
* Adding **historical weather charts** with Recharts or Chart.js
    
* More advanced **comparison view** (graphs comparing two cities side by side)
    
* Better **accessibility support** for screen readers
    
* Optimizing animations for performance on low-end devices
    

---

## Conclusion

Building this weather app was more than just an exercise—it was a chance to bring together **frontend best practices, PWA technology, and UI polish** into one cohesive project.

From **GSAP-powered intro animations** to **scroll handling, and toast notifications**, every feature was an opportunity to push myself closer to production-quality work.

If you’re learning frontend development, I highly recommend trying something similar. Don’t just stop at “fetch and display weather.” Add persistence, add interactivity, add polish. That’s where the learning truly happens.

---

✅ **Live demo:** [https://vite-weather-app-sigma.vercel.app/](https://vite-weather-app-sigma.vercel.app/)  
📂 **Source code:** [https://github.com/Skyz03/Vite-Weather-App](https://github.com/Skyz03/Vite-Weather-App)
