How TREK's Weather Forecast Integration with Open-Meteo API Works
TREK retrieves weather data through a thin service layer that validates coordinates against Zod schemas, caches results in memory with TTL-based expiration, and routes requests to Open-Meteo's forecast or archive endpoints based on date ranges, translating WMO weather codes into localized descriptions.
TREK is an open-source application that provides weather forecasts without requiring API keys by leveraging the free Open-Meteo service. The integration is implemented in TypeScript and handles everything from request validation to intelligent endpoint selection and response caching. This article examines the exact implementation found in the mauriceboe/TREK repository.
Request Validation and Schema Design
The integration begins with strict parameter validation using Zod. Incoming queries must satisfy the schemas defined in shared/src/weather/weather.schema.ts, which enforce lat and lng as required strings while making date optional. When omitted, the system returns current weather conditions; when provided, it triggers forecast or archive logic depending on the date's temporal distance.
The lang parameter defaults to German (de) and drives the localization of weather descriptions later in the pipeline.
Intelligent Caching Strategy
Before initiating network requests, the service checks an in-memory Map cache using a deterministic key format computed by the cacheKey function.
// From server/src/services/weatherService.ts
const cacheKey = (lat: string, lng: string, date?: string) =>
`${lat}_${lng}_${date || 'current'}`;
The cache implements time-to-live (TTL) policies differentiated by data type:
- Current conditions: 15 minutes
- Short-term forecasts (up to 16 days): 1 hour
- Archive/climate data: 24 hours
A concurrency guard prevents duplicate fetches for identical in-flight requests. The inFlight Map stores pending promises keyed by the same cache key, ensuring that simultaneous requests for the same coordinates and date share a single network call.
Open-Meteo Endpoint Selection Logic
The service determines which Open-Meteo endpoint to query based on the requested date's relationship to the current time. This logic resides in server/src/services/weatherService.ts between lines 58-97.
Current Weather (no date parameter):
- Endpoint:
api.open-meteo.com/v1/forecast - Parameters:
current=variables for immediate conditions
Forecast Range (-1 to +16 days):
- Endpoint:
api.open-meteo.com/v1/forecast - Parameters:
daily=arrays withforecast_days=16
Historical Data (< -1 day):
- Endpoint:
archive-api.open-meteo.com/v1/archive - Returns observed data for the specific calendar day
Climate Fallback (> +16 days):
- Endpoint:
archive-api.open-meteo.com/v1/archive - Strategy: Queries a 5-day window around the same calendar day from the previous year to provide climate estimates
All requests include timezone=auto to ensure localized time formatting in the response.
Data Transformation and WMO Code Mapping
Open-Meteo returns numeric WMO weather codes that require translation into human-readable strings. TREK maintains two lookup tables in weatherService.ts:
WMO_MAP: Provides short labels (e.g., "Partly cloudy")WMO_DESCRIPTION_ENandWMO_DESCRIPTION_DE: Offer detailed explanations
The service constructs a WeatherResult object containing:
- Temperature aggregates (average, max, min)
- Derived
mainanddescriptionfields from WMO lookups - Sunrise and sunset times
- Precipitation sums and maximum wind speeds
- Optional
hourlyarrays for detailed forecasts
Error Handling and Security
Network requests use Node's native fetch implementation. The service validates HTTP status codes and checks for error fields in the JSON payload, throwing a custom ApiError class when Open-Meteo returns invalid data.
Security constraints are enforced in server/src/middleware/globalMiddleware.ts, where the Content Security Policy (CSP) explicitly whitelists https://open-meteo.com, https://api.open-meteo.com, and the archive subdomain in the connect-src directive. This authorization allows browser clients to reach the API while maintaining strict security boundaries.
Usage Examples
HTTP API Endpoint
Request current weather for Berlin:
GET /api/weather?lat=52.5&lng=13.4&lang=en
Request a specific date forecast:
GET /api/weather?lat=52.5&lng=13.4&date=2025-08-01&lang=en
Example response structure:
{
"temp": 22,
"temp_max": 25,
"temp_min": 18,
"main": "Partly cloudy",
"description": "Partly cloudy",
"type": "forecast",
"sunrise": "05:12",
"sunset": "21:03",
"precipitation_sum": 0,
"wind_max": 12
}
Direct Service Integration
Import and call the service functions directly from your TypeScript code:
import { getWeather, getDetailedWeather } from './services/weatherService';
// Current conditions
const current = await getWeather('52.5', '13.4', undefined, 'de');
// 16-day forecast window
const forecast = await getWeather('52.5', '13.4', '2025-08-01', 'en');
// Hourly detail (uses archive API for dates beyond 16 days)
const detailed = await getDetailedWeather('52.5', '13.4', '2026-09-15', 'en');
Summary
TREK's Open-Meteo integration demonstrates a production-ready pattern for consuming third-party weather APIs:
- Validation layer: Zod schemas in
weather.schema.tsenforce type safety on inputs - Smart routing: Automatic selection between forecast and archive endpoints based on temporal distance
- Performance optimization: In-memory caching with differentiated TTLs and request deduplication via
inFlightpromises - Localization: WMO code translation supporting English and German descriptions
- Security: CSP whitelisting in
globalMiddleware.tsrestricts outbound connections to authorized domains
Frequently Asked Questions
Does TREK require an API key for Open-Meteo?
No. TREK leverages Open-Meteo's free public API endpoints that do not require authentication. The service constructs URLs directly to api.open-meteo.com and archive-api.open-meteo.com without inserting API keys, making the integration immediately usable without configuration.
How does TREK handle dates beyond the 16-day forecast limit?
When a user requests a date more than 16 days in the future, TREK falls back to the archive API and retrieves climate data from the previous year. Specifically, it queries a 5-day window around the same calendar day from historical records, providing representative weather patterns rather than specific forecasts.
What happens when multiple users request the same weather data simultaneously?
The inFlight Map in weatherService.ts stores pending promises for ongoing requests. If a second request arrives with identical parameters (latitude, longitude, date, and language) while the first is still fetching, the service returns the same promise to both callers. This prevents duplicate network requests and reduces load on the Open-Meteo servers.
How are weather condition codes translated into text?
Open-Meteo returns numeric WMO standard codes. TREK maps these to human-readable strings using lookup tables defined in weatherService.ts. The WMO_MAP provides short labels like "Partly cloudy," while WMO_DESCRIPTION_EN and WMO_DESCRIPTION_DE contain longer explanations, with the appropriate language selected based on the lang parameter.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →