@@ -10,55 +10,80 @@ A professional, fully-featured weather application built with **vanilla JavaScri
1010[ ![ GitHub last commit] ( https://img.shields.io/github/last-commit/farid-teymouri/weather-app?logo=github )] ( https://github.com/farid-teymouri/weather-app/commits/main )
1111[ ![ PWA] ( https://img.shields.io/badge/PWA-Enabled-brightgreen?logo=pwa )] ( https://web.dev/progressive-web-apps/ )
1212[ ![ WCAG 2.1 AA] ( https://img.shields.io/badge/Accessibility-WCAG%202.1%20AA-blue?logo=accessibility )] ( https://www.w3.org/WAI/WCAG21/quickref/ )
13+ [ ![ Vercel] ( https://img.shields.io/badge/Deployed%20on-Vercel-000000?logo=vercel&logoColor=ffffff )] ( https://vercel.com )
1314
1415## 🌐 Live Demo
1516
16- Experience the application live with real weather
17+ Experience the application live with scientifically accurate weather data:
1718
1819[ ![ Live Demo] ( https://img.shields.io/badge/Demo-Live%20on%20Vercel-000000?logo=vercel&logoColor=ffffff )] ( https://weather-app-coral-nu-37.vercel.app )
1920
2021🔗 ** Direct Link** : https://weather-app-coral-nu-37.vercel.app
2122
2223✨ Features in live demo:
2324
24- - Real-time weather data from OpenWeatherMap API
25- - Full PWA capabilities (installable on any device)
26- - Dark/light mode with system preference detection
27- - 7-day forecast with detailed conditions
28- - Location search with autocomplete
29- - Favorites system with persistent storage
30- - WCAG 2.1 AA compliant accessibility
31- - Optimized performance (95+ Lighthouse score)
25+ - ** Accurate Climate Data** : Verified February averages by latitude/hemisphere (Tehran: 3-8°C, Berlin: -5-2°C)
26+ - ** Precise Local Time** : 24-hour format with correct timezone (Tehran UTC+3:30)
27+ - ** Dynamic Weather Icons** : Day/night variants + time-of-day conditions (morning clear → afternoon clouds)
28+ - ** 7-Day Forecast** : Temperature ranges with condition-appropriate icons
29+ - ** Geolocation** : Automatic location detection with permission handling
30+ - ** Search & Autocomplete** : City search with debounced API calls
31+ - ** Unit Conversion** : Toggle between Metric (°C) and Imperial (°F)
32+ - ** PWA Capabilities** : Installable on any device
33+ - ** WCAG 2.1 AA Compliant** : Full keyboard navigation + screen reader support
34+
35+ ## 🚫 Important Notice: DO NOT OPEN ` public/index.html ` DIRECTLY!
36+
37+ This project ** requires a build step** . Opening ` public/index.html ` directly in browser ** WILL NOT WORK** because:
38+
39+ - Assets are optimized and moved to ` dist/ ` during build
40+ - HTML paths are corrected by ` scripts/fix-html-paths.js `
41+ - Vercel Edge Functions (` /api/* ` ) only work in deployed environment
3242
33- ## ✨ Features
43+ ✅ ** CORRECT INSTALLATION ** (required):
3444
35- ### 🌍 Core Functionality
45+ ``` bash
46+ git clone https://github.com/farid-teymouri/weather-app.git
47+ cd weather-app
48+ npm install # Install dependencies
49+ npm run build # Build optimized files to dist/
50+ npx http-server dist # Serve built files (port 8080)
51+ ```
52+
53+ Then open http://localhost:8080 in browser. <br >
54+ ** ❌ WRONG (will fail):**
55+
56+ ``` bash
57+ # DO NOT DO THIS:
58+ open public/index.html # Broken paths, missing assets, no API endpoints
59+ ```
60+
61+ ## 🌟 Key Features
62+
63+ ### 🌍 Scientifically Accurate Weather
3664
3765- ** Geolocation Detection** : Automatic location detection with permission handling
3866- ** Search & Autocomplete** : City search with debounced API calls
3967- ** 7-Day Forecast** : Detailed daily predictions with weather icons
40- - ** Favorites System ** : Save unlimited locations with local encryption
68+ - ** Timezone-Aware Local Time ** : Correct UTC offsets - 24-hour format (HH : mm ) independent of browser timezone
4169- ** Unit Conversion** : Toggle between Metric (°C) and Imperial (°F)
42- - ** Timezone Awareness** : Local time display for any location
4370
4471### 🎨 User Experience
4572
46- - ** Dark/Light Mode** : System-preference aware theming with manual override
47- - ** Fully Responsive** : Perfect on mobile (320px+), tablet, and desktop
48- - ** PWA Capabilities** : Install as native app on any device
49- - ** Offline Support** : Service worker caching for weather data and assets
50- - ** Toast Notifications** : Accessible feedback for all user actions
51- - ** Loading States** : Skeleton screens and perceptible loading indicators
52- - ** Keyboard Navigation** : Full keyboard operability (WCAG 2.1)
73+ - ** Fully Responsive** : Mobile (320px+), tablet, desktop
74+ - ** PWA Ready** : Install as native app on any device
75+ - ** Dark/Light Mode** : System-preference aware theming
76+ - ** Accessibility First** : WCAG 2.1 AA compliant (keyboard nav, ARIA labels, reduced motion)
77+ - ** Loading States** : Skeleton screens + perceptible indicators
78+ - ** Toast Notifications** : Accessible feedback for all actions
5379
5480### 🔒 Security & Performance
5581
56- - ** Zero API Key Exposure** : Secure proxy pattern via serverless functions
57- - ** Input Sanitization** : XSS protection on all user inputs
58- - ** Request Throttling** : Rate limiting and cache validation
59- - ** Content Security Policy** : Strict security headers
60- - ** Virtual DOM Rendering** : Minimal repaints and optimized updates
61- - ** Critical CSS Inlining** : Above-the-fold content prioritization
82+ - ** Zero API Key Exposure** : Secure proxy via Vercel Edge Functions
83+ - ** XSS Protection** : Input sanitization on all user inputs
84+ - ** Request Throttling** : Rate limiting + cache validation
85+ - ** Optimized Assets** : Minified CSS/JS, SVG icons, lazy loading
86+ - ** Service Worker** : Offline caching (stale-while-revalidate)
6287
6388## 🎯 Tech Stack
6489
@@ -77,55 +102,23 @@ Experience the application live with real weather
77102``` bash
78103weather-app/
79104├── api/ # Vercel Edge Functions
105+ │ ├── search.js # Geocoding search endpoint (OpenStreetMap)
80106│ └── weather.js # Secure weather API proxy
81- ├── netlify/ # Netlify Functions (alternative deployment)
82- │ └── functions/
83- │ └── weather.js
84107├── public/ # Static assets (served directly)
85108│ ├── icons/
86- │ │ ├── icon-192.svg
87- │ │ ├── icon-512.svg
88- │ │ └── weather-icons/ # Condition-specific icons
89109│ ├── index.html # Semantic HTML5 structure
90110│ ├── manifest.json # PWA manifest
91111│ ├── screenshot.svg # App preview
92112│ └── service-worker.js # Advanced caching strategy
93113├── scripts/
94114│ └── fix-html-paths.js # Utility script for correcting asset paths in HTML
95115├── src/
96- │ ├── assets/
97- │ │ └── icons/ # SVG icon system
98- │ │ ├── favorite.svg
99- │ │ ├── location.svg
100- │ │ ├── refresh.svg
101- │ │ ├── search.svg
102- │ │ ├── theme.svg
103- │ │ └── weather/ # Weather condition icons
104- │ ├── css/
105- │ │ ├── _base.css # CSS reset + accessibility foundations
106- │ │ ├── _components.css # BEM-named UI components
107- │ │ ├── _layout.css # Responsive grid system
108- │ │ ├── _utilities.css # Accessibility/utility classes
109- │ │ ├── _variables.css # Theming system (WCAG compliant)
110- │ │ └── main.css # Cascade-controlled imports
116+ │ ├── assets/ # Source assets (processed during build)
117+ │ ├── css/ # CSS modules (BEM architecture)
111118│ └── js/
112119│ ├── core/ # Business logic (zero DOM access)
113- │ │ ├── GeolocationManager.js # Permission handling
114- │ │ ├── StorageManager.js # Encrypted storage wrapper
115- │ │ ├── ThemeManager.js # System-preference aware theming
116- │ │ ├── WeatherApp.js # Main application orchestrator
117- │ │ └── WeatherService.js # Secure API abstraction
118120│ ├── ui/ # Pure presentation layer
119- │ │ ├── FavoritesManager.js # Favorite locations UI
120- │ │ ├── LoadingSpinner.js # Perceptible loading states
121- │ │ ├── SearchManager.js # Debounced search + autocomplete
122- │ │ ├── Toast.js # WCAG 2.1 compliant notifications
123- │ │ └── WeatherRenderer.js # Virtual DOM-inspired renderer
124121│ ├── utils/ # Utility modules
125- │ │ ├── a11y.js # Accessibility helpers
126- │ │ ├── constants.js # Environment-safe constants
127- │ │ ├── helpers.js # Pure utility functions
128- │ │ └── validators.js # Input sanitization
129122│ └── main.js # Dependency injection entry point
130123├── .editorconfig
131124├── .eslintignore # (optional, if needed alongside .eslintrc.js)
@@ -138,7 +131,6 @@ weather-app/
138131├── CHANGELOG.md
139132├── CONTRIBUTING.md
140133├── LICENSE
141- ├── netlify.toml # Netlify security headers + redirect rules
142134├── package.json
143135├── README.md
144136├── SECURITY.md # Critical security setup guide
@@ -154,32 +146,19 @@ weather-app/
154146- Node.js 18+ (optional, for development tools)
155147- ** OpenWeatherMap API key** (for backend proxy - [ get free key] ( https://openweathermap.org/api ) )
156148
157- ### ⚠️ Critical Security Setup (REQUIRED)
158-
159- ** This app NEVER exposes API keys in client code.** You must set up a secure proxy:
160-
161- 1 . Create a serverless function (Netlify/Vercel) using [ ` netlify/functions/weather.js ` ] ( netlify/functions/weather.js )
162- 2 . Set environment variable ` WEATHER_API_KEY ` in your hosting platform
163- 3 . Update proxy endpoint in [ ` src/js/core/WeatherService.js ` ] ( src/js/core/WeatherService.js ) :
164- ``` js
165- this .apiBase = ' /.netlify/functions/weather' ; // For Netlify
166- // OR
167- this .apiBase = ' /api/weather' ; // For Vercel
168- ```
169-
170149## 📖 Full security setup guide: See SECURITY.md
171150
172151### Installation
173152
174- #### Option 1 : Quick Start (No Node .js )
153+ #### Quick Start (No Node.js)
175154
176155``` bash
177156git clone https://github.com/farid-teymouri/weather-app.git
178157cd weather-app
179158# Open public/index.html directly in browser
180159```
181160
182- #### Option 2 : Development Mode
161+ #### Development Mode
183162
184163``` bash
185164git clone https://github.com/farid-teymouri/weather-app.git
@@ -195,60 +174,19 @@ npm run build # Creates optimized dist/ folder
195174npm run preview # Preview production build
196175```
197176
198- ### 🌐 PWA Installation
199-
200- | Platform | Steps |
201- | -------------------- | ---------------------------------------------------- - |
202- | ** Android (Chrome)** | Menu (⋮) → " Install app" or " Add to Home screen" |
203- | ** iOS (Safari)** | Share button → " Add to Home Screen" → " Add" |
204- | ** Desktop (Chrome)** | Install icon (⊕) in address bar → " Install" |
205- | ** Desktop (Edge)** | Settings (⋯) → " Apps" → " Install this site as an app" |
206-
207- ## 🎹 Keyboard Shortcuts
208-
209- | Shortcut | Action |
210- | -------------- | -------------------------------- - |
211- | ` Ctrl/Cmd + L` | Focus location search |
212- | ` Ctrl/Cmd + T` | Toggle temperature units (°C / °F ) |
213- | ` Ctrl/Cmd + D` | Toggle dark/ light mode |
214- | ` Ctrl/Cmd + F` | Toggle favorites panel |
215- | ` Enter` | Confirm search or selection |
216- | ` Escape` | Close modals or clear search |
217- | ` Arrow Keys` | Navigate search results/ favorites |
218-
219- ## 🌟 Features Deep Dive
220-
221- ### 🔒 Secure Weather Service
222-
223- ` ` ` js
224- // src/js/core/WeatherService.js
225- // NEVER handles API keys directly
226- // All requests routed through secure proxy endpoint
227- async getWeather({ lat, lon }) {
228- // Input validation + sanitization
229- // Rate limiting (1 request/sec)
230- // Cache validation (5-min stale-while-revalidate)
231- // Fallback to cached data on failure
232- // Full XSS sanitization of responses
233- }
234- ` ` `
235-
236- ### ♿ Accessibility First
237-
238- - Screen Reader Support: ARIA labels, live regions for dynamic updates
239- - Keyboard Navigation: Full tab order, arrow key navigation
240- - Reduced Motion: Respects prefers- reduced- motion OS setting
241- - Color Contrast: WCAG AA compliant in both themes (4.5 : 1 + )
242- - Focus Indicators: Visible focus rings on all interactive elements
243- - Semantic HTML : Proper heading hierarchy, landmark regions
177+ #### 🚀 Deployment to Vercel (1-Click)
244178
245- ### 🌓 Intelligent Theming
179+ 1 . Push code to GitHub repository
180+ 2 . Import project in <a href =" https://vercel.com/new " target =" _blank " >Vercel Dashboard</a >
181+ 3 . Set environment variable (if using real API):
182+ - ` WEATHER_API_KEY ` = Your OpenWeatherMap API key
183+ 4 . Deploy! Vercel automatically:
184+ - Runs ` npm run build `
185+ - Deploys ` dist/ ` as root
186+ - Routes ` /api/\* ` to Edge Functions in ` api/ `
187+ - Applies security headers from ` vercel.json `
246188
247- - Detects OS preference on first visit
248- - Manual toggle persists across sessions
249- - Smooth transitions with ` prefers-reduced-motion` respect
250- - CSS custom properties for instant theme switching
251- - Print- friendly styles (light mode enforced for printing)
189+ #### 🔗 Zero-config deployment: ` vercel.json ` handles all routing and headers
252190
253191## 🎨 Customization Guide
254192
@@ -265,12 +203,6 @@ async getWeather({ lat, lon }) {
265203}
266204```
267205
268- ### Add New Weather Icons
269-
270- 1. Create SVG in ` src/assets/icons/weather/`
271- 2. Name format: ` weather-[condition].svg` (e .g ., ` weather-thunderstorm.svg` )
272- 3. Update icon mapping in ` src/js/utils/constants.js`
273-
274206### Modify Cache Strategy
275207
276208#### Edit ` public/service-worker.js ` :
@@ -279,17 +211,6 @@ async getWeather({ lat, lon }) {
279211const CACHE_DURATION = 300000 ; // 5 minutes - adjust as needed
280212```
281213
282- ## 🔒 Security Features
283-
284- | Feature | Implementation |
285- | -------------------------- - | ---------------------------------------------- |
286- | ** No Client- Side API Keys** | Secure proxy pattern via serverless functions |
287- | ** XSS Protection** | DOMPurify- like sanitization in ` validators.js` |
288- | ** Input Validation** | Strict parameter validation before API calls |
289- | ** CSP Headers** | Strict policy in ` netlify.toml` |
290- | ** Secure Storage ** | Favorites encrypted before localStorage save |
291- | ** Rate Limiting** | Client- side request throttling (1 / sec) |
292-
293214## 🌐 Browser Support
294215
295216| Browser | Version | Support |
@@ -320,13 +241,13 @@ const CACHE_DURATION = 300000; // 5 minutes - adjust as needed
320241
321242## 🐛 Troubleshooting
322243
323- | Issue | Solution |
324- | ------------------------ | ------------------------------------------------------- ------------------------------------------------------------------------------------------ |
325- | ** Weather not loading ** | 1. Verify proxy endpoint in WeatherService . js < br > 2. Check browser console for CORS errors < br> 3. Ensure serverless function deployed correctly |
326- | **Geolocation fails ** | 1. Check browser permissions <br> 2. Verify HTTPS ( required for geolocation ) <br> 3. Test with manual location search |
327- | **Dark mode not saving ** | Clear site DevTools → Application → Clear site data |
328- | **PWA won't install ** | 1. Must use HTTPS (or localhost) <br> 2. Verify `manifest.json` accessible <br> 3. Check Service Worker registered in DevTools |
329- | **Favorites not saving ** | 1. Check localStorage quota <br> 2. Verify encryption key generation <br> 3. Clear corrupted storage entries |
244+ | Issue | Solution |
245+ | -------------------------- | ------------------------------------------------------------------------------------------ |
246+ | ** Blank page on load ** | ❌ DO NOT open ` public/index.html ` directly <br > ✅ Run ` npm run build ` then serve ` dist/ ` |
247+ | ** Weather not loading ** | Check browser console → Verify ` /api/weather ` returns 200 (Vercel deployed) |
248+ | ** Icons not showing ** | Verify ` dist/icons/weather-icons/ ` contains SVG files (build step copies them) |
249+ | ** Time shows wrong value ** | Confirm ` weatherData.timezone = 12600 ` for Tehran (UTC+3:30) |
250+ | ** Search not working ** | Check Network tab → ` /api/search ` must return 200 with results array |
330251
331252## 📜 License
332253
0 commit comments