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 with forecast_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_EN and WMO_DESCRIPTION_DE: Offer detailed explanations

The service constructs a WeatherResult object containing:

  • Temperature aggregates (average, max, min)
  • Derived main and description fields from WMO lookups
  • Sunrise and sunset times
  • Precipitation sums and maximum wind speeds
  • Optional hourly arrays 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.ts enforce 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 inFlight promises
  • Localization: WMO code translation supporting English and German descriptions
  • Security: CSP whitelisting in globalMiddleware.ts restricts 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →