Skip to content

nishadnp/weather-app

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

80 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Day & Night Weather Dashboard

A sophisticated, data-driven weather application demonstrating advanced vanilla JavaScript architecture with strict Model-View-Controller separation of concerns, procedural celestial geometry, and dynamic UI context binding.


Project Overview

The Day & Night Weather Dashboard is a real-time weather forecasting application that transcends traditional weather data visualization by introducing contextual UI generation and procedural astronomical tracking. Built entirely in Vanilla JavaScript without frameworks, the application demonstrates enterprise-grade architectural patterns while maintaining a minimal, composable codebase.

Core Proposition

This is not merely a weather displayβ€”it's an intelligent information system that:

  • Transforms raw meteorological data into UI-ready models via a centralized view model
  • Procedurally renders celestial motion using SVG coordinate geometry and real-time astronomical calculations
  • Dynamically adapts visual context (backgrounds, map styles, typography) based on solar cycles and atmospheric conditions
  • Manages complex state through a centralized controller with zero global mutation
  • Maintains architectural purity via strict MVC boundaries and chart-level Model-Renderer-Config isolation

Architecture

Design Principles

The application adheres to three foundational architectural principles:

  1. Separation of Concerns (SoC): Each module has a single, well-defined responsibility with minimal cross-module coupling.
  2. Unidirectional Data Flow: Data flows strictly from Models β†’ Views β†’ Controller event handlers, preventing circular dependencies.
  3. Immutable Configuration: API keys, chart dimensions, and UI thresholds are frozen constants to prevent accidental runtime mutations.

Directory Structure

src/
β”œβ”€β”€ index.html                 # Application shell (semantic HTML5)
β”œβ”€β”€ index.js                   # Entry point
β”‚
β”œβ”€β”€ api/                       # External API integration layer
β”‚   β”œβ”€β”€ weather.js            # Visual Crossing weather API client
β”‚   β”œβ”€β”€ dynamicBackground.js  # Unsplash image fetching
β”‚   β”œβ”€β”€ geolocation.js        # Browser Geolocation API wrapper
β”‚   └── map.js                # Geoapify static map URL builder
β”‚
β”œβ”€β”€ models/                    # Data transformation layer (MVC Models)
β”‚   └── weatherViewModel.js   # Raw API β†’ UI-ready data structure
β”‚
β”œβ”€β”€ components/               # UI rendering layer (MVC Views)
β”‚   β”œβ”€β”€ index.js             # Component export barrel
β”‚   β”œβ”€β”€ header.js            # Header date display
β”‚   β”œβ”€β”€ sidebar.js           # Weather metrics + air quality
β”‚   β”œβ”€β”€ weatherHero.js       # Main weather display
β”‚   β”œβ”€β”€ insights.js          # Wind stats + astronomy toggle
β”‚   └── nextdaysForecast.js  # 5-day forecast cards
β”‚
β”œβ”€β”€ charts/                   # Specialized visualization modules
β”‚   β”œβ”€β”€ windChart/
β”‚   β”‚   β”œβ”€β”€ config.js        # Chart dimensions & scaling
β”‚   β”‚   β”œβ”€β”€ windChartModel.js      # Hourly wind β†’ SVG coordinates
β”‚   β”‚   └── windChartRenderer.js   # SVG histogram + trendline
β”‚   β”‚
β”‚   β”œβ”€β”€ forecastChart/
β”‚   β”‚   β”œβ”€β”€ config.js
β”‚   β”‚   β”œβ”€β”€ forecastChartModel.js  # Temperature data β†’ coordinates
β”‚   β”‚   └── forecastChartRenderer.js  # Quadratic bezier trendlines
β”‚   β”‚
β”‚   └── astroObjectPosition/
β”‚       β”œβ”€β”€ computePosition.js      # Sun/moon trajectory computation
β”‚       β”œβ”€β”€ renderAstroObject.js    # SVG circle positioning + phase
β”‚       └── index.js               # Orchestration entry point
β”‚
β”œβ”€β”€ ui/                       # Application controller (MVC Controller)
β”‚   └── controller.js        # Event binding + data pipeline orchestration
β”‚
β”œβ”€β”€ utils/                    # Pure utility functions
β”‚   β”œβ”€β”€ weatherUnit.js           # Unit system management (metric/US/UK)
β”‚   β”œβ”€β”€ weatherLevels.js         # Metric β†’ interpretation mapping
β”‚   β”œβ”€β”€ time-fns.js              # Timezone-aware time utilities + "vibe" engine
β”‚   β”œβ”€β”€ customDropDown.js        # Accessible dropdown component
β”‚   └── capitalizeFirstLetter.js # String utility
β”‚
└── styles/                   # Component-scoped and utility CSS
    β”œβ”€β”€ main.css             # Entry point (import order = cascade priority)
    β”œβ”€β”€ base.css             # Global reset + typography
    β”œβ”€β”€ layout.css           # App grid layout
    β”œβ”€β”€ components/          # Component-specific styles
    β”‚   β”œβ”€β”€ header.css
    β”‚   β”œβ”€β”€ sidebar.css
    β”‚   β”œβ”€β”€ weatherHero.css
    β”‚   β”œβ”€β”€ insights.css
    β”‚   └── nextdaysForecast.css
    └── utilities/           # Reusable utility classes
        β”œβ”€β”€ glass-panel.css          # Glassmorphism effect
        β”œβ”€β”€ customDropdown.css       # Dropdown styling
        β”œβ”€β”€ toggleSwitch.css         # Sun/moon mode toggle
        └── accessibility.css        # Screen reader utilities

MVC Architecture Breakdown

Model Layer: src/models/weatherViewModel.js

The Model acts as the "brain" of the application, transforming raw Visual Crossing API responses into structured, component-aware objects.

Responsibilities:

  • Normalize nested API response into flat, UI-optimized structure
  • Extract component-specific data subsets (header, sidebar, weatherHero, insights)
  • Compute derived values (e.g., centered 39-hour window from hourly data)
  • Generate simplified forecast objects for card rendering

Key Pattern:

// Raw API response β†’ component-indexed model
processWeatherData(rawAPIData) β†’ {
  conditions,
  header: { date },
  sidebar: { humidity, uvIndex, ... },
  weatherHero: { temperature, location, ... },
  insights: { centered39hWindow, astronomy { sun, moon } },
  nextFiveDays: [ { dayName, highTemp, icon } ]
}

Benefits:

  • Single source of truth for data transformation
  • Components consume only their required data slice
  • API schema changes isolated to one module
  • Easy to extend with new data fields

View Layer: src/components/ and src/charts/

Views are stateless, pure rendering functions that accept processed models and update DOM.

Component Structure:

renderXXX(processedData) β†’ DOM mutations only

Chart Structure (Model-Renderer-Config Pattern):

config.js           β†’ Immutable dimensions, thresholds
chartModel.js       β†’ Raw data β†’ SVG coordinates
chartRenderer.js    β†’ Coordinates β†’ DOM SVG elements
index.js            β†’ Orchestrate model + renderer

Example: Wind Chart

  • config.js: SVG height=70px, visualMax=30m/s, barCap=0.7
  • windChartModel.js: Convert hourly wind speeds to bar heights and gust line positions
  • windChartRenderer.js: Create SVG <rect> elements and <polyline> trendline
  • Result: Composable, testable, dimension-agnostic visualization

Controller Layer: src/ui/controller.js

The Controller orchestrates the complete data pipeline: events β†’ models β†’ views.

Orchestration Flow:

User Input (form/button)
    ↓
bindFormEvents() / bindLocationButton()
    ↓
getWeather(location, unitSystem)  [API call]
    ↓
processWeatherData()  [Model transformation]
    ↓
updateBackgroundImage()  [Dynamic context]
    ↓
renderAll()  [Component rendering]
    β”œβ”€β”€ renderHeader()
    β”œβ”€β”€ renderSideBar()
    β”œβ”€β”€ renderWeatherHero()
    β”œβ”€β”€ renderInsights()
    └── renderNextDaysForecast()

Key Patterns:

  • Lazy DOM node caching via IIFE pattern to avoid null reference errors
  • Single isInitialized guard prevents event listener duplication
  • Centralized state management (currentProcessedData, currentTimeVibe)
  • Promise chaining for sequential API β†’ transform β†’ render pipeline

Key Features

1. Procedural Celestial Tracking

The application renders the sun and moon trajectories in real-time using procedural geometry rather than pre-computed sprites.

How It Works:

  • SVG Arc Definition: An SVG <path> element defines an elliptical arc representing the celestial object's path above the horizon.
  • Time-Based Progress: Current time (in seconds since midnight) is normalized to a 0–1 progress value between rise and set times.
  • Coordinate Extraction: track.getPointAtLength() returns the (x, y) position at the specified progress along the arc.
  • Dynamic Positioning: The circle element (<circle>) is continuously updated with new coordinates as time advances.

Mathematical Foundation:

// Normalized progress: 0 = rise, 1 = set
progress = (currentTimeInSeconds - riseTimeInSeconds) / (setTimeInSeconds - riseTimeInSeconds)

// Arc traversal: SVG path length β†’ screen coordinates
[x, y] = track.getPointAtLength(progress * totalArcLength)

// Result: Sun/moon appears to move along the arc in real-time

Edge Case Handling:

  • Midnight Crossing: Objects that rise before midnight and set after correctly compute elapsed time across the day boundary.
  • Polar Regions: Handles scenarios where celestial objects never set or never rise (constant visibility).

2. Dynamic Lunar Shrouding (Lunar Phase Simulation)

The application renders real-time lunar phase visualization using a calculated offset shadow.

Implementation:

  • Phase-Based Offset: Moon phase (0 = new, 0.5 = full, 1 = new) is mapped to a horizontal shadow offset.
  • Crescent Effect: A dark SVG circle (moon-shroud) slides across the visible moon circle to create crescent, gibbous, and full phase appearances.
  • Offset Calculation:
    const radius = 6;  // Moon circle radius
    offset = (phase - 0.5) * (radius * 4)
    // phase 0 β†’ offset = -12 (full dark)
    // phase 0.5 β†’ offset = 0 (no shadow, full moon)
    // phase 1 β†’ offset = +12 (full light)

Visual Result:

  • New Moon: Shroud completely covers the moon
  • Crescent: Shroud partially offset, creating thin crescent
  • Full Moon: Shroud hidden (offset = 0), moon fully visible
  • Gibbous: Shroud progressively offset, showing intermediate phases

3. Contextual UI: The "Vibe" Engine

The application dynamically adapts its visual context (backgrounds, map styles, text hierarchy) based on the time of day relative to solar cycles.

"Vibe" Categories:

Vibe Time Window Background Theme Map Style UI Intent
night moody Before dawn OR after dusk (+30min buffer) Dark, stormy dark-matter Calm, reduced contrast
sunrise dawn 30min before to 1hr after sunrise Golden, warm klokantech-basic Awakening energy
morning light 1hr after sunrise to noon Bright, clear osm-bright Vibrant, optimistic
afternoon sun Noon to 1hr before sunset Vivid, saturated osm-bright Peak energy
sunset golden hour 1hr before to 30min after sunset Golden, warm dark-matter Romantic, reflective

Implementation:

// Solar cycle calculation
getTimeVibe(timezone, sunriseTime, sunsetTime) β†’ vibe string

// Context binding
currentTimeVibe β†’ Unsplash image search query
currentTimeVibe β†’ Geoapify map style selection
currentTimeVibe β†’ CSS variable values (future extensibility)

Real-World Impact:

  • A weather query at 6:30 AM automatically fetches "sunrise dawn" imagery and applies warm map styling.
  • The same location at 3 PM renders "afternoon sun" context with bright map styles and saturated backgrounds.
  • User never explicitly selects contextβ€”it's derived from solar physics.

4. Multi-Unit System Support

The application dynamically switches between three standardized unit systems without requiring page reload.

Supported Systems:

  • Metric: Β°C, km/h, km
  • US: Β°F, mph, miles
  • UK: Β°C, mph, miles

Implementation:

  • Centralized weatherUnit.js manages active unit system
  • setUnitSystem(unitSystem) updates global state before data fetch
  • All chart renderers query formatUnit(measurement) at render time
  • Wind speed models apply unit-specific conversion factors

5. Air Quality Monitoring (AQI + Pollutant Tracking)

Real-time pollutant concentration display with color-coded risk levels.

Monitored Pollutants:

  • PMβ‚‚.β‚…: Fine particulate matter (Β΅g/mΒ³)
  • PM₁₀: Coarse particulate matter (Β΅g/mΒ³)
  • O₃: Ozone (ppb)
  • NOβ‚‚: Nitrogen dioxide (ppb)

AQI Categories:

  • 0–50: Good (green)
  • 51–100: Moderate (yellow)
  • 101–150: Unhealthy (Sensitive Groups) (orange)
  • 151–200: Unhealthy (red)
  • 201–300: Very Unhealthy (purple)
  • 300+: Hazardous (maroon)

6. Advanced Forecast Visualization

39-Hour Centered Window: Wind chart displays hourly data centered on the current hour (19.5 hours past + current + 19 hours future).

Temperature Trendlines: Forecast chart renders high/low temperature curves using quadratic BΓ©zier splines for smooth interpolation between daily points.


7. Optimized Initial Load (UX)

The application implements a "Smart Start" sequence to ensure the user is never met with a blank state:

  1. Primary Action: Attempts to utilize the Browser Geolocation API to provide hyper-local weather immediately upon arrival.
  2. Graceful Fallback: If location access is denied or unavailable, the Controller automatically initializes with a high-context default city (e.g., Dubai).

8. Robust Asynchronous State Management

The application implements a dedicated Loading Lifecycle to bridge the gap between user intent and API resolution.

  • UX Consistency: Employs a custom-animated "Thematic Pulse" overlay that maintains visual continuity with the application's astronomical theme while preventing "stale data" confusion.

  • Performance Testing: Engineered to maintain UI responsiveness even under significant network latency, verified using Chrome DevTools' Slow 3G throttling.

  • Fail-Safe Logic: Utilizes try...catch...finally blocks within the Controller to ensure the UI state resets correctly even if API requests are interrupted or exhausted.


Tech Stack

HTML5 CSS3 JavaScript Webpack Vercel

Core Language & Runtime

  • Vanilla ES6+: No frameworks; pure JavaScript modules with native import/export
  • Native Web APIs: Fetch, Geolocation, Date (date-fns for timezone support)

Styling

  • CSS3: Grid, Flexbox, Custom Properties, Glassmorphism backdrop filter
  • Component Architecture: BEM-inspired naming with scoped component stylesheets
  • Intrinsically Responsive Design: Utilizes CSS Grid and Flexbox to maintain layout integrity across varying viewport widths without heavy reliance on fixed breakpoints.

Build & Development

  • Webpack 5: Module bundling, asset management, dev server
  • Babel: (implicit via webpack) for ES6 transpilation
  • ESLint + Prettier: Code quality and formatting enforcement
  • Husky + lint-staged: Pre-commit hooks for linting/formatting

External APIs (3rd-Party)

Service Purpose Rate Limit Documentation
Visual Crossing Weather & astronomy data 40 queries/day Weather API Documentation
Unsplash Dynamic background imagery 50 reqs/hour Unsplash Developers
Geoapify Static map rendering 3k reqs/day Geoapify APIs Documentation
Browser Geolocation User coordinates Built-in MDN

Note: Rate limits are based on the current API configuration used in this project (development/free-tier credentials). If you use your own API keys or different subscription tiers, these limits may differ.

Libraries

Library Purpose Size
date-fns Timezone-aware date manipulation ~13KB (modular)
@fontsource Self-hosted typography (Inter, Plus Jakarta Sans) ~50KB total

Getting Started

Prerequisites

  • Node.js 16+ and npm 8+
  • Environment Variables: Create .env in project root
    WEATHER_API_KEY=your_visual_crossing_api_key
    UNSPLASH_KEY=your_unsplash_access_key
    GEOAPIFY_KEY=your_geoapify_api_key

Installation

git clone https://github.com/nishadnp/weather-app.git
cd weather-app
npm install

Development

npm run dev
# Opens http://localhost:8080 with hot reload

Production Build

npm run build
# Outputs optimized bundle to dist/

Code Quality

npm run lint           # Run ESLint
npm run lint:fix       # Fix linting issues
npm run format         # Run Prettier

Data Flow Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     USER INTERACTION                        β”‚
β”‚            (Search form / Current location button)          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     ↓
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚   UI CONTROLLER            β”‚
        β”‚ ui/controller.js           β”‚
        β”‚ β€’ Event binding            β”‚
        β”‚ β€’ Unit system selection    β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     ↓
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚   API INTEGRATION LAYER    β”‚
        β”‚ api/weather.js             β”‚
        β”‚ β€’ Fetch raw API data       β”‚
        β”‚ β€’ Handle errors            β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     ↓
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚   DATA TRANSFORMATION (MODEL)      β”‚
    β”‚ models/weatherViewModel.js         β”‚
    β”‚ β€’ Normalize nested structures      β”‚
    β”‚ β€’ Extract component-specific data  β”‚
    β”‚ β€’ Compute derived values           β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 ↓
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚         CONTEXT DERIVATION                       β”‚
    β”‚ β€’ Time vibe calculation                          β”‚
    β”‚ β€’ Background image fetch                         β”‚
    β”‚ β€’ Map style selection                            β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 ↓
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  VIEW RENDERING LAYER                       β”‚
    β”‚  β”œβ”€β”€ Header              (date display)     β”‚
    β”‚  β”œβ”€β”€ Sidebar             (metrics + AQI)    β”‚
    β”‚  β”œβ”€β”€ Weather Hero        (conditions)       β”‚
    β”‚  β”œβ”€β”€ Insights            (wind + astro)     β”‚
    β”‚  └── Next 5 Days Forecast (cards + chart)   β”‚
    β”‚                                             β”‚
    β”‚  CHART SUBSYSTEMS:                          β”‚
    β”‚  β”œβ”€β”€ Wind Chart          (bars + trendline) β”‚
    β”‚  β”œβ”€β”€ Forecast Chart      (bezier curves)    β”‚
    β”‚  └── Astro Chart         (arc + shadows)    β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 ↓
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚    RENDERED DOM        β”‚
        β”‚   (User sees result)   β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Architecture Principles: Why This Design?

1. Single Responsibility Principle

  • Each module has one reason to change
  • weatherViewModel.js changes only if API schema changes
  • windChartModel.js changes only if chart math changes
  • Components change only if DOM structure changes

2. Unidirectional Data Flow

  • Data flows: Controller β†’ Model β†’ Views
  • Views never modify Model; only Controller does
  • No circular dependencies or mutual modification
  • Easier to trace data mutations for debugging

3. Configuration Over Code

  • Chart dimensions live in config.js files
  • Thresholds for level mapping in weatherLevels.js
  • API endpoints frozen in constants
  • Non-developers can adjust UI without touching logic

4. Composition Over Inheritance

  • Utility functions are pure, stateless
  • Components are small, focused, reusable
  • Charts are self-contained with model/renderer/config
  • Easy to add new features without modifying existing code

5. Progressive Enhancement

  • Static HTML provides baseline functionality (no JS)
  • CSS handles layout and basic styling
  • JavaScript layers interactivity and real-time updates
  • Graceful degradation if APIs fail

Extensibility Examples

Add a New Weather Metric

  1. Add field to Visual Crossing API request
  2. Normalize in models/weatherViewModel.js
  3. Create new component: components/newMetric.js
  4. Call renderer in controller.js's renderAll() function

Add a New Chart Type

  1. Create folder: src/charts/newChart/
  2. Implement: config.js, newChartModel.js, newChartRenderer.js, index.js
  3. Import and orchestrate in relevant component
  4. Chart is instantly testable, reusable, dimension-agnostic

Support a New Unit System

  1. Add entry to weatherUnit.js UNIT_MAP
  2. Update conversion factors in relevant chart models
  3. UI automatically adapts on dropdown selection

Performance Considerations

  • Lazy DOM Queries: Nodes cached on first access via ??= operator
  • Event Delegation: Single listener on document for dropdowns
  • Efficient Rerenders: Only modified data sections trigger DOM updates
  • SVG Optimization: Chart paths computed once, reused for scaling
  • Async Image Loading: Background images fetch without blocking UI
  • Minimal Bundle: No frameworks; ~100KB minified + gzipped

Browser Support

  • Chrome/Edge: 90+
  • Firefox: 88+
  • Safari: 14+
  • Mobile: iOS Safari 14+, Chrome Android

(Requires ES6 support: arrow functions, destructuring, template literals, fetch API)


Development

Folder Structure Conventions

src/
β”œβ”€β”€ api/         β†’ External API clients (no DOM access)
β”œβ”€β”€ models/      β†’ Pure data transformations (no side effects)
β”œβ”€β”€ components/  β†’ View functions (DOM mutations only)
β”œβ”€β”€ charts/      β†’ Visualization subsystems (MRC pattern)
β”œβ”€β”€ ui/          β†’ Application controller (event orchestration)
β”œβ”€β”€ utils/       β†’ Pure utility functions (reusable across modules)
└── styles/      β†’ Component + utility CSS

Code Style

  • Naming: camelCase for variables/functions, BEM for CSS classes
  • Comments: JSDoc for public APIs; inline for complex logic
  • Modules: One default export per file; named exports for utilities
  • Immutability: Use Object.freeze() for config; avoid direct mutation

Testing

Currently no test framework, but architecture enables easy testing:

// Model is pure function β†’ easy to unit test
processWeatherData(mockAPIResponse) β†’ assert output structure

// Chart model is isolated β†’ test without rendering
getWindChartModel(mockHours, config) β†’ assert coordinate precision

// Chart renderer is predictable β†’ mock DOM and assert SVG attributes

Known Limitations

  1. Real-Time Updates: Application doesn't auto-refresh; requires manual location re-entry
  2. Offline Mode: No service worker; requires internet connectivity
  3. Historical Data: Only current forecast; no historical data archive
  4. Accessibility: Charts are primarily visual; however, core weather status and loading states utilize ARIA live regions and roles for screen reader compatibility.
  5. Mobile: Responsive design present but not fully optimized for touch interactions

Deployment & CI/CD

  • The application is architected for modern cloud environments and is currently deployed via Vercel.

  • Automated Pipeline: Integrated with GitHub to trigger automated builds and deployments on every git push.

  • Environment Security: API keys (Visual Crossing, Unsplash, Geoapify) are managed through Vercel Environment Variables, ensuring sensitive credentials are never exposed in the client-side source code or version control.

  • Production Optimization: Leverages Vercel’s edge network for fast asset delivery and optimized performance of the bundled Webpack output.


License

License: ISC

See LICENSE file for details.


Credits & Acknowledgements

Iconography & UI Assets

  • Weather Icons: Created by Dr. Lex (Alexander Thomas), based on the original Dark Sky icon set. Used under Creative Commons - Attribution license. (Source: dr-lex.be).

  • Astronomy Icons:

  • General UI Icons: Curated from Google Material Symbols for high-density dashboard clarity.

  • Typography: Inter and Plus Jakarta Sans self-hosted via Fontsource.


Design Inspiration

UI Reference: Based on the Weathrly Weather Forecasting Web Design on Dribbble.

Technical Execution: The static high-fidelity mockup was translated into a functional, state-driven dashboard. The implementation prioritizes intrinsic responsiveness using CSS Grid and Flexbox, custom glassmorphism effects, and real-time SVG coordinate geometry for celestial tracking.

Contact & Support

  • Author: nishadnp
  • Issues: GitHub Issues
  • Discussions: GitHub Discussions

Built with β˜€οΈ and πŸŒ™ by nishadnp

A celebration of Vanilla JavaScript, MVC architecture, and the poetry of procedural geometry.

About

A dynamic weather forecast app using the Visual Crossing API. Toggle between Celsius and Fahrenheit, with live weather-based backgrounds. Built with an emphasis on strict MVC architecture and procedural SVG rendering.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Generated from nishadnp/webpack-template