A beautiful weather dashboard that shows current temperature, wind speed, humidity, and a 7-day forecast for any city — no API key required.
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' +
'¤t=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));
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>
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}` +
`¤t=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');
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°, ...]
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; }
}
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.
Spotted a bug, broken code, or something that doesn't look right? Tell us what's off and we'll fix it.