# Weather.mjs AC Piece - Architectural Plan **Created:** December 6, 2025 **Status:** βœ… Implemented ## πŸŽ‰ Implementation Complete The `weather.mjs` piece has been implemented as a **non-interactive, Weather Channel style passive display** featuring: - **Auto-cycling views** (10 second intervals): Current Conditions β†’ 7-Day Forecast β†’ Today's Details β†’ Extended Outlook - **Scrolling crawl bar** at bottom with current conditions summary - **Open-Meteo API** (free, no API key required) - **Geocoding** for city name lookup - **Classic Weather Channel "Local on the 8s" aesthetic** with blue gradient background, panel layouts, and view indicator dots ### Usage ``` weather # Weather for New York (default) weather los angeles # Weather for LA weather tokyo # Weather for Tokyo weather 48.8567,2.3508 # Weather by coordinates ``` --- ## πŸ“‹ Original Overview This document outlines the architecture and implementation plan for a `weather.mjs` piece that allows users to query and display weather information through the AC prompt system. ## 🎯 User Experience Goals ### From AC Prompt Usage: ``` weather β†’ Get weather for current location (IP-based) weather los angeles β†’ Get weather for Los Angeles weather 90210 β†’ Get weather by ZIP code weather tokyo β†’ Get weather for Tokyo, Japan weather 48.8567,2.3508 β†’ Get weather by coordinates (Paris) weather forecast london β†’ Get multi-day forecast for London weather --help β†’ Show usage information ``` ### Display Options: - **Current conditions** - Temperature, humidity, wind, conditions - **Forecast mode** - Multi-day forecast view - **Visual representation** - Weather icons, colors based on conditions - **Sound cues** - Audio feedback for weather conditions (rain, thunder, etc.) --- ## πŸ”¬ Weather API Research & Recommendations ### Option 1: **Open-Meteo** ⭐ RECOMMENDED **URL:** https://open-meteo.com/en/docs | Pros | Cons | |------|------| | βœ… **No API key required** | ❌ No city name lookup (needs geocoding first) | | βœ… Completely free for non-commercial use | ❌ Requires separate geocoding API call | | βœ… No rate limits for reasonable use | | | βœ… Open source | | | βœ… High accuracy with multiple weather models | | | βœ… 16-day forecasts available | | | βœ… Hourly, daily, and 15-minute data | | | βœ… No account creation needed | | **Example API Call:** ``` https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t=temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m&daily=weather_code,temperature_2m_max,temperature_2m_min&timezone=auto ``` **Geocoding API (also free, no key):** ``` https://geocoding-api.open-meteo.com/v1/search?name=London&count=1 ``` --- ### Option 2: **WeatherAPI.com** **URL:** https://www.weatherapi.com/ | Pros | Cons | |------|------| | βœ… Built-in city/ZIP/IP lookup | ❌ Requires API key | | βœ… Rich data (astronomy, marine, sports) | ❌ Rate limits on free tier | | βœ… 14-day forecast | ❌ Account creation required | | βœ… Air quality & pollen data | ❌ Free tier: 1M calls/month | | βœ… Weather alerts | | **Example API Call:** ``` http://api.weatherapi.com/v1/current.json?key=YOUR_KEY&q=London ``` --- ### Option 3: **OpenWeatherMap** **URL:** https://openweathermap.org/api | Pros | Cons | |------|------| | βœ… Well-documented | ❌ Requires API key | | βœ… One Call API 3.0 comprehensive | ❌ Free tier: 1000 calls/day | | βœ… Weather maps available | ❌ Account creation required | | | ❌ Premium features cost money | --- ### πŸ† Final Recommendation: **Open-Meteo** **Why Open-Meteo is best for AC:** 1. **No API key management** - Simplifies deployment, no env vars needed 2. **No account creation** - Zero friction for contributors 3. **Free forever** - No risk of hitting rate limits or unexpected costs 4. **Open source philosophy** - Aligns with AC's spirit 5. **Excellent data quality** - Uses multiple national weather services **Implementation Strategy:** 1. Use Open-Meteo Geocoding API to convert city names β†’ coordinates 2. Use Open-Meteo Weather API with coordinates for weather data 3. Support direct lat/lon input for power users --- ## πŸ—οΈ AC Piece Architecture ### File Location ``` system/public/aesthetic.computer/disks/weather.mjs ``` ### Core Structure ```javascript // Weather, 2025.12.06 // Get weather information from the AC prompt. /* #region πŸ“š README Usage: weather - Weather for current location (IP geolocation) weather [location] - Weather for a city, ZIP code, or coordinates weather forecast [location] - Multi-day forecast Examples: weather weather new york weather 90210 weather 48.8567,2.3508 weather forecast london #endregion */ /* #region 🏁 TODO - [] Basic weather display - [] Location geocoding - [] IP-based geolocation fallback - [] Multi-day forecast view - [] Weather condition icons - [] Sound effects for conditions - [] Temperature unit toggle (C/F) #endregion */ let weatherData = null; let location = null; let loading = true; let error = null; let mode = 'current'; // 'current' or 'forecast' // πŸ₯Ύ Boot async function boot({ params, net, num }) { // Parse command parameters // Fetch weather data // Handle geocoding if needed } // 🎨 Paint function paint({ wipe, ink, screen, write }) { // Display weather information // Show loading state // Render weather icons } // πŸŽͺ Act function act({ event: e }) { // Handle keyboard input (refresh, toggle units) } // πŸ“° Meta function meta({ piece }) { return { title: "Weather", desc: "Check the weather from the prompt.", }; } export { boot, paint, act, meta }; ``` ### API Wrapper Functions ```javascript // Geocoding: City name β†’ Coordinates async function geocode(query) { const url = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(query)}&count=1`; const res = await fetch(url); const data = await res.json(); if (data.results && data.results.length > 0) { return { name: data.results[0].name, country: data.results[0].country, latitude: data.results[0].latitude, longitude: data.results[0].longitude, }; } return null; } // Weather: Coordinates β†’ Weather Data async function getWeather(lat, lon, forecast = false) { const params = new URLSearchParams({ latitude: lat, longitude: lon, current: 'temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m,wind_direction_10m,precipitation', daily: 'weather_code,temperature_2m_max,temperature_2m_min,precipitation_probability_max,sunrise,sunset', timezone: 'auto', forecast_days: forecast ? 7 : 1, }); const url = `https://api.open-meteo.com/v1/forecast?${params}`; const res = await fetch(url); return await res.json(); } // IP Geolocation fallback (using ipinfo.io free tier or similar) async function getLocationFromIP() { // Could use various free IP geolocation services // Or default to a fallback location } ``` ### WMO Weather Codes β†’ Display Mapping ```javascript const WEATHER_CODES = { 0: { text: 'Clear sky', icon: 'β˜€οΈ', color: 'yellow' }, 1: { text: 'Mainly clear', icon: '🌀️', color: 'yellow' }, 2: { text: 'Partly cloudy', icon: 'β›…', color: 'gray' }, 3: { text: 'Overcast', icon: '☁️', color: 'gray' }, 45: { text: 'Foggy', icon: '🌫️', color: 'gray' }, 48: { text: 'Depositing rime fog', icon: '🌫️', color: 'gray' }, 51: { text: 'Light drizzle', icon: '🌧️', color: 'blue' }, 53: { text: 'Moderate drizzle', icon: '🌧️', color: 'blue' }, 55: { text: 'Dense drizzle', icon: '🌧️', color: 'blue' }, 56: { text: 'Light freezing drizzle', icon: '🌧️', color: 'teal' }, 57: { text: 'Dense freezing drizzle', icon: '🌧️', color: 'teal' }, 61: { text: 'Slight rain', icon: '🌧️', color: 'blue' }, 63: { text: 'Moderate rain', icon: '🌧️', color: 'blue' }, 65: { text: 'Heavy rain', icon: '🌧️', color: 'darkblue' }, 66: { text: 'Light freezing rain', icon: '🌨️', color: 'teal' }, 67: { text: 'Heavy freezing rain', icon: '🌨️', color: 'teal' }, 71: { text: 'Slight snow', icon: '❄️', color: 'white' }, 73: { text: 'Moderate snow', icon: '❄️', color: 'white' }, 75: { text: 'Heavy snow', icon: '❄️', color: 'white' }, 77: { text: 'Snow grains', icon: '❄️', color: 'white' }, 80: { text: 'Slight rain showers', icon: '🌦️', color: 'blue' }, 81: { text: 'Moderate rain showers', icon: '🌦️', color: 'blue' }, 82: { text: 'Violent rain showers', icon: 'β›ˆοΈ', color: 'darkblue' }, 85: { text: 'Slight snow showers', icon: '🌨️', color: 'white' }, 86: { text: 'Heavy snow showers', icon: '🌨️', color: 'white' }, 95: { text: 'Thunderstorm', icon: 'β›ˆοΈ', color: 'purple' }, 96: { text: 'Thunderstorm with slight hail', icon: 'β›ˆοΈ', color: 'purple' }, 99: { text: 'Thunderstorm with heavy hail', icon: 'β›ˆοΈ', color: 'purple' }, }; ``` --- ## πŸ“Š Data Flow ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ AC Prompt Input β”‚ β”‚ weather [location] [options] β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Parameter Parsing β”‚ β”‚ - Extract location string β”‚ β”‚ - Detect coordinates vs city name vs ZIP β”‚ β”‚ - Parse options (forecast, units, etc.) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β–Ό β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Coordinatesβ”‚ β”‚ City Name β”‚ β”‚ No Locationβ”‚ β”‚ Detected β”‚ β”‚ Detected β”‚ β”‚ (use IP) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Open-Meteo β”‚ β”‚ β”‚ β”‚ Geocoding API β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Open-Meteo Weather API β”‚ β”‚ (with lat/lon coords) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Process & Display β”‚ β”‚ - Format temperatures β”‚ β”‚ - Map weather codes β”‚ β”‚ - Render to screen β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## 🎨 Visual Design ### Current Weather View ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β˜€οΈ Clear sky β”‚ β”‚ β”‚ β”‚ Los Angeles, CA β”‚ β”‚ β”‚ β”‚ 72Β°F β”‚ β”‚ Feels like 74Β°F β”‚ β”‚ β”‚ β”‚ πŸ’¨ Wind: 8 mph NW πŸ’§ Humidity: 45% β”‚ β”‚ β”‚ β”‚ Press R to refresh β”‚ β”‚ Press F to toggle Β°F/Β°C β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### Forecast View ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 7-Day Forecast - Los Angeles β”‚ β”‚ β”‚ β”‚ Today β˜€οΈ 72Β°F / 55Β°F β”‚ β”‚ Sat 🌀️ 74Β°F / 58Β°F β”‚ β”‚ Sun β›… 70Β°F / 56Β°F β”‚ β”‚ Mon 🌧️ 65Β°F / 52Β°F 40% rain β”‚ β”‚ Tue 🌧️ 63Β°F / 50Β°F 60% rain β”‚ β”‚ Wed 🌀️ 68Β°F / 54Β°F β”‚ β”‚ Thu β˜€οΈ 72Β°F / 56Β°F β”‚ β”‚ β”‚ β”‚ Press R to refresh β”‚ β”‚ Press C for current β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## πŸ”Š Audio Integration (Future) Weather-appropriate ambient sounds: - Rain: Gentle rain audio loop - Thunder: Thunder sound effects - Wind: Wind ambience for high wind speeds - Clear: Optional pleasant ambience Could integrate with AC's sound system via `sound.synth()` or audio samples. --- ## πŸ› οΈ Implementation Phases ### Phase 1: MVP (This PR) - [x] Basic piece structure - [ ] Open-Meteo API integration - [ ] City name geocoding - [ ] Current weather display - [ ] Temperature in both C and F (toggle) ### Phase 2: Enhanced Features - [ ] Multi-day forecast view - [ ] Better visual design with pixel weather icons - [ ] Coordinate input support - [ ] ZIP code support - [ ] IP-based location fallback ### Phase 3: Polish - [ ] Animated weather effects (rain, snow particles) - [ ] Sound effects for conditions - [ ] Caching to reduce API calls - [ ] Sunrise/sunset theming --- ## πŸ“ Files to Create ``` system/public/aesthetic.computer/disks/weather.mjs (main piece) ``` Optionally: ``` system/public/aesthetic.computer/disks/common/weather-icons.mjs (icon sprites) system/public/aesthetic.computer/disks/common/weather-api.mjs (API helpers) ``` --- ## πŸ”— References - [Open-Meteo API Docs](https://open-meteo.com/en/docs) - [Open-Meteo Geocoding API](https://open-meteo.com/en/docs/geocoding-api) - [WMO Weather Codes](https://open-meteo.com/en/docs#weathervariables) - [AC Piece Architecture](../WRITE-A-PIECE.md) - [AC Profile Piece (fetch example)](../system/public/aesthetic.computer/disks/profile.mjs) - [AC Rain Piece (visual example)](../system/public/aesthetic.computer/disks/rain.mjs) --- ## βœ… Success Criteria 1. User can type `weather london` and see current weather 2. User can type `weather` and get weather based on IP location 3. User can type `weather forecast paris` and see 7-day forecast 4. Temperature can be toggled between Β°C and Β°F 5. Weather conditions are clearly displayed with icons/colors 6. Errors are handled gracefully (no location found, API down, etc.)