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, 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:
To practice building a PWA from scratch, and
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.
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.
<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/
📂 Source code: https://github.com/Skyz03/Vite-Weather-App






