A modern, responsive weather application built with Next.js 16, React 19, TypeScript, and Tailwind CSS.
- Real-time weather data from OpenWeather API
- 5-day forecast with hourly breakdowns
- Search by city name or use geolocation
- Responsive design (mobile-first)
- Dark mode support
- Type-safe API responses
- Server-side data fetching with caching
npm installCreate a .env.local file in the project root:
OPENWEATHER_API_KEY=your_api_key_hereGetting an API Key:
- Sign up at OpenWeatherMap
- Navigate to API Keys
- Generate a new API key (free tier: 1000 calls/day)
npm run devOpen http://localhost:3000 in your browser.
npm run build
npm start├── app/
│ ├── globals.css # Global styles
│ ├── layout.tsx # Root layout with fonts
│ └── page.tsx # Main weather page
├── components/
│ ├── empty-state.tsx # Empty state UI
│ ├── error-message.tsx # Error display
│ ├── forecast-grid.tsx # 5-day forecast cards
│ ├── search-bar.tsx # Search with geolocation
│ ├── weather-card.tsx # Current weather display
│ └── weather-icon.tsx # Weather icon component
├── lib/
│ ├── api.ts # OpenWeather API functions
│ ├── utils.ts # Utility functions
│ └── weather-service.ts # Data processing layer
├── types/
│ └── weather.ts # TypeScript interfaces
├── env.example # Environment variable template
├── next.config.ts # Next.js configuration
├── tailwind.config.ts # Tailwind configuration
└── package.json # Dependencies
- Server Components: Data fetching (
lib/api.ts,lib/weather-service.ts), main page content - Client Components: Search bar (uses browser geolocation, React state), error messages (no data needed)
- All API calls use server-side fetching with Next.js 15
fetchcaching - Cache duration: 5 minutes for weather data, 24 hours for geocoding
- Proper error handling with typed error responses
- Tailwind CSS v4 with utility-first approach
- Responsive breakpoints:
sm:640px,md:768px,lg:1024px,xl:1280px - Dark mode support via
dark:modifiers - Consistent spacing with
p-4,gap-4,max-w-screen-xl
- All API responses defined in
types/weather.ts - No
anytypes used - Strict TypeScript configuration
// Get weather by city name
getWeatherByCity(city: string): Promise<CurrentWeatherResponse>
// Get weather by coordinates
getWeatherByCoords(lat: number, lon: number): Promise<CurrentWeatherResponse>
// Get 5-day forecast by city
getForecastByCity(city: string): Promise<ForecastResponse>
// Get 5-day forecast by coordinates
getForecastByCoords(lat: number, lon: number): Promise<ForecastResponse>
// Geocode city name to coordinates
geocodeCity(city: string): Promise<GeocodingResult[]>// Fetch and process weather data
fetchWeatherByCity(city: string): Promise<{ current, forecast }>
fetchWeatherByCoords(lat: number, lon: number): Promise<{ current, forecast }>| Variable | Description | Required |
|---|---|---|
OPENWEATHER_API_KEY |
OpenWeatherMap API key | Yes |
MIT License - feel free to use for personal or commercial projects.