A lightweight, mobile-first weather dashboard built with Next.js 14 and Tailwind CSS.
It fetches real-time weather data from the OpenWeather API and delivers a clean, intuitive, and accessible interface β complete with smooth animations, dark/light themes, and geolocation support.
Perfect for developers looking for a production-ready starter or a quick weather app prototype.
π View Live Demo (Deployed on Vercel)
πΌοΈ (Replace with a GIF or screenshot β host via GitHub Assets, Imgur, or Giphy)
- π Live Weather Data: Real-time temperature, humidity, wind, pressure, visibility, and cloud cover.
- π Forecasts: 5-day forecast + 8-hour hourly view with precipitation probability (POP).
- π«οΈ Advanced Metrics: Air Quality Index (AQI) + pollutant breakdown (PM2.5/PM10) + UV Index.
- π Smart Location: Auto GPS detection with fallback to London; coordinates cached for 30 min.
- π± Responsive Design: Mobile-optimized layout with horizontal scroll and side navigation sheet.
- π Themes & Units: Toggle dark/light mode and Celsius/Fahrenheit (persisted via localStorage).
- π« Animations: Floating particle backgrounds for a modern, dynamic experience.
- βΏ Accessibility: ARIA-compliant UI; full keyboard and screen-reader support.
- ποΈ Voice Search: Browser-based speech recognition for hands-free city lookup.
β οΈ Error Handling: Graceful fallback for geolocation, API, and offline scenarios.
| Category | Technologies |
|---|---|
| Framework | Next.js 14 (App Router, Server Components) |
| Styling | Tailwind CSS 3.4, CSS-in-JS for animations |
| UI Components | Radix UI (Dialog/Sheet), Lucide React Icons, shadcn/ui (Card, Badge, Button, Progress) |
| API Integration | OpenWeatherMap API (Current, Forecast, Air Pollution, UV) |
| State & Utils | React Hooks (useState, useEffect, useRef), localStorage for caching |
| Build & Deploy | TypeScript 5.2, ESLint, Vercel (one-click deploy) |
- Node.js: v18+ (LTS recommended)
- Package Manager: npm 9+ or Yarn 1.22+
- API Key: Free OpenWeatherMap account
-
Duplicate the example environment file:
cp .env.example .env.local
-
Add your OpenWeather API key to
.env.local:NEXT_PUBLIC_OPENWEATHER_API_KEY=your_openweather_api_key_here
Note: The
NEXT_PUBLIC_prefix exposes it to the client-side for API calls. Keep it secure in production by using server-side proxies for sensitive keys.
git clone https://github.com/agudu50/weatherapp.git
cd weatherappnpm:
npm installYarn:
yarn installDevelopment (Hot reload on http://localhost:3000):
- npm:
npm run dev - Yarn:
yarn dev
Build & Start Production:
npm:
npm run build
npm startYarn:
yarn build
yarn startweatherapp/
βββ app/
β βββ dashboard/
β β βββ page.tsx # Main dashboard component (mobile-optimized UI)
β β βββ layout.tsx # Layout with Sheet trigger and mobile header
β βββ api/ # API routes (proxies for OpenWeather)
β βββ weather/route.ts # Current weather endpoint
β βββ forecast/route.ts # Forecast data
β βββ air-quality/route.ts # AQI data
β βββ uv/route.ts # UV Index
βββ components/
β βββ ui/ # shadcn/ui primitives
β β βββ sheet.tsx # Custom Radix Sheet with accessibility fixes
β β βββ card.tsx # Weather cards
β β βββ ... # Button, Badge, Progress, etc.
β βββ layout/ # Header, particles background
βββ lib/ # Utils (API helpers, utils.ts for temp conversions)
βββ public/ # Static assets (icons, etc.)
βββ tailwind.config.js # Tailwind setup with custom themes
βββ README.md # You're reading it!
The app prioritizes WCAG 2.1 AA compliance:
- Screen Reader Support: Hidden DialogTitle injected into SheetContent for Radix Dialog errors.
- Keyboard Navigation: Full tab-focus support in Sheet and controls.
- Contrast & Spacing: Tailwind's default ensures 4.5:1 ratios; touch targets β₯ 44px.
Fixed Issue: DialogContent requires a DialogTitle β Resolved by adding a visually hidden <Title> as a child of <DialogContent>. Custom props like showHeader enable mobile-optimized headers:
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
<Sheet>
<SheetTrigger>Open Menu</SheetTrigger>
<SheetContent side="left" showHeader title="Navigation" headerContent="App menu options">
<nav>
{/* Menu items */}
</nav>
</SheetContent>
</Sheet>- Adaptive Layout: Stacks controls vertically on small screens; horizontal scroll for hourly forecast.
- Geolocation Prompts: Non-intrusive alerts for permission; accuracy displayed in badges.
- Performance: Lazy-loaded forecasts; no-cache headers for live data.
- PWA Ready: Add manifest.json and service worker for offline use (future enhancement).
| Issue | Solution |
|---|---|
| Geolocation Denied | Grant browser permissions; app falls back to London (51.5074Β° N, -0.1278Β° W). Check console for errors. |
| API Key Error (401) | Verify NEXT_PUBLIC_OPENWEATHER_API_KEY in .env.local; restart dev server. |
| CORS/Proxy Issues | Ensure /api/* routes proxy OpenWeather correctly (no client-side CORS). |
| Sheet Not Closing | Update Radix UI to latest; confirm onOpenChange handlers. |
| Animations Lag | Reduce particle count in useEffect for low-end devices. |
Run npm run lint for code issues or check browser console for API logs.
- Vercel (Recommended): Connect GitHub repo; auto-deploys on push. Free tier supports API routes.
- Netlify: Drag-drop
out/folder afternpm run build. - Custom Server: Use
npm run buildand host on Node/Express.
Environment vars: Set NEXT_PUBLIC_OPENWEATHER_API_KEY in platform dashboard.
We welcome contributions!
- Fork the repo and create a feature branch (
git checkout -b feat/amazing-feature). - Commit changes (
git commit -m 'Add some amazing feature'). - Push to branch (
git push origin feat/amazing-feature). - Open a Pull Request.
Guidelines:
- Follow Conventional Commits.
- Ensure responsive design (test on mobile).
- Add unit tests for utils (e.g., temp conversions) with Vitest.
- Update README for new features.
This project is licensed under the MIT License - see the LICENSE file for details.
Built with β€οΈ by [Anthony Gudu/agudu50]. Star β the repo if it helps! Questions? Open an issue.