Build / Web apps

Weather app for your phone

An installable web app with current conditions, active alerts and the next 48 hours for wherever the phone is.

TypeScriptPWAEdge function
Weather app for your phone: illustrative mockup with sample data
Example build (illustrative). Sample data, not a real product, not real results.

What it does

The phone sends its location to your own endpoint. The endpoint asks the API for current conditions and a handful of forecast hours at once, and returns one JSON blob. The page draws it. Your key never touches the phone. Add it to the home screen and it behaves like an app.

  • In the page, call navigator.geolocation.getCurrentPosition, then fetch your endpoint with lat and lon.
  • Show the severe alerts as they come. Do not reword them. This is not an official NWS product.

API calls

Set your key once: export TFX_KEY=tfx_live_.... Free previews need no key.

Right now: conditions plus severe alerts

request
curl "https://data.truefixr.com/v1/data?dataset=weather&lat=30.27&lon=-97.74"

A forecast hour, 0 to 48 ahead

request
curl "https://data.truefixr.com/v1/data?dataset=weather&lat=30.27&lon=-97.74&hours_ahead=24"

Code (TypeScript)

Cut down on purpose. Print the real response keys on your first call before you map fields.

weather-phone-app.ts
interface Env { TFX_KEY?: string }

const API = "https://data.truefixr.com/v1/data";
const HOURS = [0, 6, 12, 24, 48];

async function hour(lat: string, lon: string, h: number, key?: string) {
  const u = new URL(API);
  u.searchParams.set("dataset", "weather");
  u.searchParams.set("lat", lat);
  u.searchParams.set("lon", lon);
  u.searchParams.set("hours_ahead", String(h));
  if (key) u.searchParams.set("details", "true");
  const r = await fetch(u, { headers: key ? { Authorization: `Bearer ${key}` } : {} });
  if (!r.ok) throw new Error(`weather ${h}h: HTTP ${r.status}`);
  return r.json();
}

export default {
  async fetch(req: Request, env: Env): Promise<Response> {
    const q = new URL(req.url).searchParams;
    const lat = q.get("lat");
    const lon = q.get("lon");
    if (!lat || !lon) return new Response("lat and lon required", { status: 400 });

    const rows = await Promise.all(HOURS.map((h) => hour(lat, lon, h, env.TFX_KEY)));
    const body = { now: rows[0], alerts: rows[0].alerts ?? [], hourly: rows };
    return new Response(JSON.stringify(body), {
      headers: { "content-type": "application/json", "cache-control": "private, max-age=300" },
    });
  },
};