Freedom Sale
Independence Day Special — Unlock the AI Path 70% off our most popular AI course · Limited time offer
--Days
--Hrs
--Min
--Sec
Claim Your Discount
✦ Beginner ⏱ 40 min

⛅ Build a Weather Dashboard with Vanilla JavaScript

🎯 What You'll Build

A beautiful weather dashboard that shows current temperature, wind speed, humidity, and a 7-day forecast for any city — no API key required.

📋 What You'll Need

1

Understand the API — no key needed

Open-Meteo gives you free weather data with no signup. You call it with coordinates (latitude and longitude).

// Open-Meteo API — no API key required
// Example: Get current weather for Mumbai (19.07°N, 72.87°E)

const url = 'https://api.open-meteo.com/v1/forecast' +
  '?latitude=19.07&longitude=72.87' +
  '&current=temperature_2m,windspeed_10m,relativehumidity_2m,weathercode' +
  '&daily=temperature_2m_max,temperature_2m_min,weathercode' +
  '&timezone=auto&forecast_days=7';

fetch(url)
  .then(r => r.json())
  .then(data => console.log(data));
💡 Tip: To get coordinates for any city, search on Google: "Mumbai coordinates" — you get latitude and longitude instantly. We will add a city search in step 4.
2

Build the HTML layout

Create index.html with cards for current conditions and a forecast row.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Weather Dashboard</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

<?php require_once __DIR__ . '/../promo_banner.php'; ?>

  <div class="app">
    <div class="search-bar">
      <input type="text" id="cityInput" placeholder="Enter city name..." />
      <button onclick="searchCity()">Search</button>
    </div>

    <div class="current-card" id="currentCard">
      <div class="city-name" id="cityName">—</div>
      <div class="temperature" id="temperature">—</div>
      <div class="condition" id="condition">—</div>
      <div class="details">
        <span>💨 Wind: <b id="wind">—</b></span>
        <span>💧 Humidity: <b id="humidity">—</b></span>
      </div>
    </div>

    <div class="forecast-grid" id="forecastGrid"></div>
  </div>

  <script src="app.js"></script>
</body>
</html>
3

Write the JavaScript to fetch and display weather

Create app.js to call the API and populate the page.

// app.js

const WMO_CODES = {
  0: '☀️ Clear sky', 1: '🌤️ Mainly clear', 2: '⛅ Partly cloudy',
  3: '☁️ Overcast', 45: '🌫️ Foggy', 51: '🌦️ Light drizzle',
  61: '🌧️ Light rain', 63: '🌧️ Moderate rain', 65: '🌧️ Heavy rain',
  80: '🌦️ Showers', 95: '⛈️ Thunderstorm'
};

function getCondition(code) {
  return WMO_CODES[code] || '🌡️ Unknown';
}

async function fetchWeather(lat, lon, cityName) {
  const url = `https://api.open-meteo.com/v1/forecast` +
    `?latitude=${lat}&longitude=${lon}` +
    `&current=temperature_2m,windspeed_10m,relativehumidity_2m,weathercode` +
    `&daily=temperature_2m_max,temperature_2m_min,weathercode` +
    `&timezone=auto&forecast_days=7`;

  const res  = await fetch(url);
  const data = await res.json();

  // Current conditions
  document.getElementById('cityName').textContent    = cityName;
  document.getElementById('temperature').textContent = `${data.current.temperature_2m}°C`;
  document.getElementById('condition').textContent   = getCondition(data.current.weathercode);
  document.getElementById('wind').textContent        = `${data.current.windspeed_10m} km/h`;
  document.getElementById('humidity').textContent    = `${data.current.relativehumidity_2m}%`;

  // 7-day forecast
  const grid = document.getElementById('forecastGrid');
  grid.innerHTML = '';
  const days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];

  data.daily.time.forEach((date, i) => {
    const day  = days[new Date(date).getDay()];
    const max  = data.daily.temperature_2m_max[i];
    const min  = data.daily.temperature_2m_min[i];
    const icon = getCondition(data.daily.weathercode[i]).split(' ')[0];
    grid.innerHTML += `
      <div class="forecast-card">
        <div class="day">${i === 0 ? 'Today' : day}</div>
        <div class="icon">${icon}</div>
        <div class="temps">${max}° / ${min}°</div>
      </div>`;
  });
}

// Default city on load
fetchWeather(19.07, 72.87, 'Mumbai');
4

Add city search using the Geocoding API

Let users type any city name. Use Open-Meteo's free geocoding API to convert it to coordinates.

async function searchCity() {
  const input = document.getElementById('cityInput').value.trim();
  if (!input) return;

  const geoUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(input)}&count=1`;
  const geoRes  = await fetch(geoUrl);
  const geoData = await geoRes.json();

  if (!geoData.results || geoData.results.length === 0) {
    alert('City not found. Try a different spelling.');
    return;
  }

  const { latitude, longitude, name, country } = geoData.results[0];
  fetchWeather(latitude, longitude, `${name}, ${country}`);
}

// Also trigger search on Enter key
document.getElementById('cityInput').addEventListener('keypress', e => {
  if (e.key === 'Enter') searchCity();
});
[User types "Tokyo" and clicks Search]

Tokyo, Japan
13°C
⛅ Partly cloudy

💨 Wind: 12 km/h    💧 Humidity: 68%

[7-day forecast cards: Mon 15°/9°, Tue 17°/11°, ...]
5

Style the dashboard with CSS

Create style.css for the dark weather card design.

/* style.css */
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Segoe UI', sans-serif; background: #0f172a; color: #fff; min-height: 100vh; padding: 40px 20px; }
.app { max-width: 700px; margin: 0 auto; }

.search-bar { display: flex; gap: 10px; margin-bottom: 28px; }
.search-bar input { flex: 1; padding: 12px 18px; border-radius: 10px; border: 1.5px solid #334155; background: #1e293b; color: #fff; font-size: 1rem; }
.search-bar input::placeholder { color: #64748b; }
.search-bar button { padding: 12px 22px; background: #F59C0D; color: #fff; border: none; border-radius: 10px; font-weight: 700; cursor: pointer; font-size: 1rem; }
.search-bar button:hover { background: #e08b00; }

.current-card { background: linear-gradient(135deg, #162447, #1e3a6e); border-radius: 20px; padding: 40px; text-align: center; margin-bottom: 24px; }
.city-name { font-size: 1.1rem; opacity: 0.7; margin-bottom: 8px; }
.temperature { font-size: 5rem; font-weight: 800; line-height: 1; margin-bottom: 8px; }
.condition { font-size: 1.2rem; opacity: 0.85; margin-bottom: 24px; }
.details { display: flex; justify-content: center; gap: 32px; font-size: 0.9rem; opacity: 0.8; }

.forecast-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 10px; }
.forecast-card { background: #1e293b; border-radius: 12px; padding: 14px 8px; text-align: center; border: 1px solid #334155; }
.forecast-card .day { font-size: 0.7rem; opacity: 0.65; text-transform: uppercase; margin-bottom: 8px; }
.forecast-card .icon { font-size: 1.6rem; margin-bottom: 6px; }
.forecast-card .temps { font-size: 0.8rem; font-weight: 700; }

@media (max-width: 500px) {
  .forecast-grid { grid-template-columns: repeat(4, 1fr); }
  .temperature { font-size: 3.5rem; }
}
💡 Tip: Open-Meteo also has hourly data — add &hourly=temperature_2m to the URL and display a temperature graph using the Canvas API or a small charting library like Chart.js.

🎉 You Did It!

Your weather dashboard works for any city in the world with zero API keys or accounts. The same Open-Meteo + Geocoding API pair can power weather widgets on any website.

Found something wrong?

Spotted a bug, broken code, or something that doesn't look right? Tell us what's off and we'll fix it.