SkySnapping is a responsive weather application that shows current conditions, an hourly outlook, and a 7-day forecast for your location or any city in the world. It pairs live OpenWeather data with full-screen weather artwork, a glassmorphism interface, and a mobile-first layout.
- Live app: skysnapping.netlify.app
- Repository: github.com/Fcharki/react-weather-app
- Current conditions: temperature, feels-like, humidity, sunrise, sunset, and condition artwork
- Hourly forecast for the next 24 hours
- 7-day forecast with average daily temperature and the dominant weather condition
- Search any city with debounced autocomplete suggestions
- Recent search history stored locally
- "Use my location" support through the browser Geolocation API
- City-local time formatting (sunrise, sunset, hourly slots, and dates)
- Dynamic day/night backgrounds that follow the current weather condition and icon
- Clear nights use a starry moon scene; other conditions use darkened night variants
- Keyboard-accessible search combobox with arrow-key navigation and Escape support
- Responsive layouts for mobile portrait, mobile landscape, tablet, and desktop
- SPA routing with a dedicated About page
| Layer | Technology |
|---|---|
| UI | React 19, TypeScript |
| Build | Vite 6 |
| Styling | Tailwind CSS 4 |
| Routing | React Router 7 |
| Icons | lucide-react, Heroicons |
| Animations | Lottie (lottie-react) |
| Data | OpenWeather Current Weather, 5-day/3-hour Forecast, and Geocoding APIs |
| Quality | ESLint, TypeScript strict mode |
- Node.js 20 or newer
- npm 10 or newer
- A free OpenWeather API key
git clone https://github.com/Fcharki/react-weather-app.git
cd react-weather-app
npm installCreate a .env file in the project root. You can copy .env.example as a starting point.
VITE_WEATHER_API_KEY=your_openweather_api_key
VITE_BASE_URL=https://api.openweathermap.orgVITE_BASE_URL is optional and defaults to https://api.openweathermap.org.
Vite exposes variables prefixed with
VITE_in the browser bundle. Never commit a real API key. Use a dedicated key, restrict it in the OpenWeather dashboard when possible, and rotate it if it is ever exposed.
npm run devVite serves the app at http://localhost:5173 by default.
| Command | Description |
|---|---|
npm run dev |
Start the Vite development server with HMR |
npm run build |
Type-check the project and create a production build in dist/ |
npm run preview |
Preview the production build locally |
npm run lint |
Run ESLint across the repository |
src/
App.tsx App shell, routing, search and geolocation state
main.tsx React entry point
index.css Tailwind entry, global font and base styles
components/
NavBar.tsx Fixed responsive navigation and mobile drawer
SearchBar.tsx Accessible city search combobox
About.tsx Lazy-loaded About page
weather/
WeatherDashboard.tsx Data orchestration and responsive page layout
CurrentWeatherCard.tsx Current conditions summary
ForecastPanel.tsx Hourly/weekly tabs and forecast list
WeatherIcon.tsx OpenWeather icon renderer
hooks/
useWeather.ts Weather fetching, caching, retries and cancellation
useCitySearch.ts Debounced geocoding search and recent history
lib/
weatherApi.ts OpenWeather client, cache and API error handling
weather.ts Formatting and forecast aggregation helpers
weatherBackground.ts Condition normalization, day/night detection, background maps
types/
weather.ts Shared TypeScript models
Appkeeps the active search city, the default/current coordinates, and geolocation status.SearchBardebounces typing, requests city suggestions from the OpenWeather Geocoding API, and stores the five most recent searches inlocalStorage.useWeatherchooses a city query or coordinate query, cancels stale requests withAbortController, and keeps a five-minute in-memory cache.- Current weather and forecast requests run in parallel with
Promise.all, so the dashboard resolves with a single round trip. lib/weather.tsconverts raw API data into timezone-aware hourly and daily entries. The daily view groups three-hour forecast slots by city-local date, averages the temperature, and picks the most common condition.WeatherDashboardselects the matching background image and renders the same responsive card layout on all screen sizes.
- Mobile-first spacing with safe-area padding for notched devices.
- The weather page uses normal document flow instead of a fixed full-screen overlay, so mobile browser chrome and scrolling behave correctly.
- Forecast entries render as compact rows on small screens and as a 4- or 7-column grid from
smandmdupward. - The navigation search bar is available inline on desktop and below the header on mobile, with a slide-over menu for secondary links.
- Search supports touch selection, keyboard navigation, focus rings, and ARIA combobox semantics.
- Background artwork was converted from JPEG to WebP and resized to a maximum of 2048 px, reducing the asset payload from about 8.9 MB to about 2.1 MB, including generated night variants.
- The About page and its Lottie animations are code-split and loaded on demand.
- Weather requests are cached for five minutes and deduplicated by city or rounded coordinates.
- In-flight requests are aborted when the city or location changes, preventing race conditions and unnecessary updates.
- Forecast icons are lazy-loaded; the current-condition icon is prioritized.
- React state stores plain forecast data rather than JSX, which keeps memoized transformations cheap.
The app is a static SPA and deploys to any static host.
- Build command:
npm run build - Publish directory:
dist - Environment variable:
VITE_WEATHER_API_KEY public/_redirectsalready rewrites all routes toindex.htmlso React Router works on refresh:
/* /index.html 200
Weather data is provided by OpenWeather. This project uses the Current Weather, 5-day/3-hour Forecast, and Geocoding endpoints.
Built by Fadma Charki.