SkyCast — Advanced Weather Intelligence
A full-featured, real-time weather progressive web application built with vanilla HTML, CSS, and JavaScript. No frameworks. No build tools. Just clean, well-structured code.
Developer
Features
GPS Location
Automatically detects the user's precise location using the browser Geolocation API, with graceful fallback to city search.
Live Weather
Fetches real-time temperature, feels-like, humidity, wind, pressure, UV index, and visibility from Open-Meteo.
24-Hour Forecast
Hourly breakdown for the next 24 hours including rain probability and weather icon per hour.
14-Day Forecast
Extended 14-day daily forecast with high/low temperatures, rain probability, and average humidity.
Air Quality Index
US AQI with animated ring gauge, PM2.5, PM10, NO₂ and O₃ pollutant bars, and health advice text.
City Compare
Side-by-side weather comparison of any two cities worldwide with instant API look-up.
Saved Favorites
Up to 8 locations can be saved to browser localStorage for quick one-tap access.
Sun Progress Bar
Animated sunrise-to-sunset arc showing real-time sun position based on local timezone data.
File Structure
The production version is 3 files for simplicity and portability.
├── index.html ← full HTML structure
├── styles.css ← ALL styles merged
├── app.js ← ALL JavaScript merged
└── documentation.html ← this file
Data Flow
SkyCast follows a simple, linear data pipeline from user action to rendered UI.
User Action
User opens the app, clicks a city chip, types a search, or presses the GPS button.
Geocoding
Open-Meteo Geocoding API converts a city name to latitude/longitude coordinates. For GPS, Nominatim (OSM) does the reverse — coords → human-readable location name.
Parallel API Fetch
Two API calls fire simultaneously via Promise.all(): the Open-Meteo weather API (current + hourly + daily) and the Open-Meteo Air Quality API (AQI + pollutants).
Data Normalisation
Raw API responses are transformed into a single currentWeatherData object. Hourly data is sliced to the next 24 hours; daily data is iterated into 14 day objects with computed average humidity.
Render
renderDashboard() calls each sub-renderer in order: hero → metrics → AQI → hourly → 14-day forecast. All DOM writes use setEl() to safely update elements by ID.
APIs Used
Open-Meteo Weather API Free · No Key
Provides current conditions (temperature, humidity, wind, pressure, UV, cloud cover, visibility, precipitation), plus hourly and 14-day daily forecasts. open-meteo.com
Open-Meteo Air Quality API Free · No Key
Returns US AQI, PM2.5, PM10, nitrogen dioxide (NO₂) and ozone (O₃) for any coordinates. air-quality-api.open-meteo.com
Open-Meteo Geocoding API Free · No Key
Converts city names to latitude/longitude. Used for city search and the global capitals dropdown. geocoding-api.open-meteo.com
Nominatim / OpenStreetMap Free · No Key
Reverse geocoding — converts GPS coordinates to a human-readable location name (village, district, state, country). nominatim.openstreetmap.org
Zero API keys required. SkyCast intentionally uses only free, open APIs with no authentication requirement. This means it can be deployed and run by anyone without signing up for any service.
Local Setup
SkyCast requires no build tools, no npm, no Node.js. All you need is a browser and a local static file server (to satisfy browser CORS restrictions on the Geolocation API).
Option A — VS Code Live Server (Recommended)
Install the Live Server extension in VS Code, right-click index.html and choose Open with Live Server.
Option B — Python HTTP Server
# Navigate to the project folder cd skycast/ # Python 3 python -m http.server 8080 # Then open http://localhost:8080 in your browser
Option C — Node.js serve
npx serve .
# Then open the URL shown in terminal
Note: GPS will not work if you open index.html directly as a file:// URL. A local server is required for the Geolocation API to function correctly.
Deployment
SkyCast is a fully static application — deploy it anywhere that serves static files. The live version runs on Cloudflare Pages at sky-cast.pages.dev.
Git Workflow
# First-time setup git init git remote add origin https://github.com/username/WeatherApp.git git add . git commit -m "First commit" git branch -M main git push -u origin main # Subsequent pushes git add . git commit -m "update" git push
Cloudflare Pages
Connect your GitHub repo to Cloudflare Pages. Set build command to none and output directory to /. Every push auto-deploys.
GitHub Pages
Enable GitHub Pages on the main branch in repository settings. The site will be live at username.github.io/WeatherApp.
JS Module Reference
| Function | Module (§) | Description |
|---|---|---|
| CONFIG | §1 Config | Global app state: unit preference, favorites array, last location |
| WEATHER_CODES | §1 Config | Map of WMO weather codes to icon, color, and text description |
| AQI_LEVELS | §1 Config | Array of AQI thresholds with color and health advice |
| convertTemp() | §2 Utils | Converts Celsius to °C or °F based on CONFIG.isMetric |
| showToast() | §2 Utils | Displays a transient notification message at screen bottom |
| getSunProgress() | §2 Utils | Returns 0–1 fraction of daylight elapsed for sun progress bar |
| handleGPS() | §3 API | Triggers browser geolocation and calls reverseGeocode + weather |
| fetchCoordinates() | §3 API | Geocodes a city name and loads weather for that location |
| getLiveWeatherData() | §3 API | Main data-fetch: calls weather + AQI APIs in parallel |
| compareCities() | §3 API | Geocodes two cities and fetches weather for both simultaneously |
| renderDashboard() | §4 Render | Master render that calls all sub-renderers in sequence |
| renderHero() | §4 Render | Updates location name, temperature, condition, sun bar |
| renderAQI() | §4 Render | Animates AQI ring, sets badge color, updates pollutant bars |
| startLocalClock() | §4 Render | Starts a 1-second interval showing the location's local time |
| init() | §5 App | Entry point: populates UI lists, binds events, fires GPS |
| setTheme() | §5 App | Toggles dark/light theme on <html> data-theme attribute |
CSS Architecture
All styles are written in pure CSS3 using custom properties (variables) for theming and a CSS Grid layout system. There is no preprocessor (Sass/Less) and no utility framework (Tailwind).
| Section | Lines (approx.) | Contents |
|---|---|---|
| §1 Variables | ~80 | Dark and light theme tokens: colors, glass, shadows, icons |
| §2 Reset | ~40 | Box-model reset, base typography, scrollbar styling, utilities |
| §3–4 Background/Loader | ~50 | Ambient orbs, loading screen with progress bar |
| §5–9 Layout | ~180 | App wrapper, sticky header, search bar, quick-nav, grid, footer |
| §10 Hero | ~110 | Temperature display, weather icon, sunrise/sunset bar |
| §11 Metrics | ~55 | 6-card metrics grid with icon wraps and bar charts |
| §12 AQI | ~70 | SVG ring gauge, pollutant bars, badge coloring |
| §13 Compare | ~55 | Input wraps, VS divider, compare results grid |
| §14 Forecast | ~80 | Hourly scroll and 14-day card scroll containers |
| §15 Animations | ~90 | All @keyframes, stagger delays, reduced-motion support |
| §16 Responsive | ~150 | 6 breakpoints: 1200, 1024, 768, 480px + landscape + safe areas |
The dark theme is the default (:root) and the light theme is applied via [data-theme="light"] on the <html> element, toggled by JavaScript and persisted to localStorage.
Configuration
All user-facing configuration is centralised in the CONFIG object and the static arrays at the top of app.js.
| Key | Type | Default | Purpose |
|---|---|---|---|
| CONFIG.isMetric | boolean | true | Temperature unit: true = °C, false = °F |
| CONFIG.favorites | string[] | [] | Saved location strings from localStorage |
| CONFIG.lastLocation | object | null | Most recently loaded location (lat, lon, name) |
| INDIAN_CITIES | string[] | 15 cities | Quick-access city chips in the nav bar |
| GLOBAL_CAPITALS | string[] | 30 capitals | Dropdown list of world capital cities |
To add more Indian cities or global capitals, simply append to the INDIAN_CITIES or GLOBAL_CAPITALS arrays at the top of app.js.
// Example: add Siliguri to city chips const INDIAN_CITIES = [ "Kolkata", "Mumbai", ..., "Siliguri" ];
SkyCast Documentation — Built by Susovon Jana, Ph.D. · Live: sky-cast.pages.dev