Is it hotter or colder this year?

Is it hotter or colder this year?

Where I live could generously be called "warm", but is usually closer to the surface of the sun, especially in late summer. That's why when the weather is not oppressively hot, I try my best to enjoy it. We're mid-May now and honestly, this spring has been... pleasant. Suspiciously pleasant but I'll take what I can get.

The last few weeks I've been telling myself that the weather must be a good bit cooler than last year, and I finally decided to do something about it. I worked with Claude and created a little web app that:

  • Lets you enter a free form address and then use Geocoding to convert it to a proper longitude and latitude. This is a super simple geocoding API with a generous free tier. Do note though it's North America only.
  • Uses the Pirate Weather API to get historical weather information. Date wise, I'm using this week, and then the same days over the previous four days.

As I mentioned, I worked with Claude on this and let it design the layout and write the code initially. I was kinda impressed by one part - the mapWithConcurrency function that lets you pass an array of async function with a desired max number to run at once. It handles doing the batching and returning the final result. That makes the calls for the weather data a bit more gentle on the provider.

However - I noticed it was taking a long time to finish. In theory, I'm doing 7 times 5 (this week plus four previous years) of calls which is 35 which doesn't seem like a lot, but I did some digging. Claude had used an endpoint that was a bit old. Doing some more research I switched to the proper endpoint... which didn't support CORS.

I write these posts for free — if they're useful to you, you can buy me a coffee. It helps more than you'd think.

Oh no!

Oh - actually - I just moved to this to val.town and built a quick server side proxy. It takes in the same arguments that's send to my client side code (lat, lng, and a timestamp), and passes it to the historical Pirate Weather endpoint. So here's the frontend code - again - this is being driven by a concurrency function:

async function fetchDayTemperatures(lat, lng, unixSeconds) {
  let req = await fetch(PIRATE_WEATHER_API_BASE, {
    method: "POST",
    body: JSON.stringify({
      lat,
      lng,
      unixSeconds,
    }),
  });
  return await req.json();
}

And here's the backend code:

export default async function (req: Request): Promise<Response> {
  const body = await req.json();
  const key = Deno.env.get("PIRATE");

  const url = new URL(
    `https://timemachine.pirateweather.net/forecast/${key}/${body.lat},${body.lng},${body.unixSeconds}`,
  );
  url.searchParams.set("units", "us");
  url.searchParams.set("exclude", "minutely,hourly,alerts,flags");

  const response = await fetch(url);
  const payload = await response.json();

  if (!response.ok) {
    throw new Error(payload.error || "Weather lookup failed.");
  }

  const day = payload.daily?.data?.[0];
  if (!day) {
    throw new Error("Weather data did not include a daily summary.");
  }

  return Response.json({
    timezone: payload.timezone,
    high: day.temperatureMax,
    low: day.temperatureMin,
  });
}

I barely modified this from the original client side code - only switching to an environment variable for the API (their API is free, but I might as well) and returning a proper Response object.

Here's a screenshot of it in action:

Screenshot

You can try this yourself here: https://weathercomparison.val.run/. If you want to see the code, and possibly fork the val, you can do so here: https://www.val.town/x/raymondcamden/weather-comparison

So, was it cooler?

No. I was wrong. Last year was cooler than this year, but the three years before that were all higher, with 2022 being pure hell. I remember that year seeing the city working on a road that had literally buckled because of heat.

Photo by Peter Albanese on Unsplash