All work

Case study

NH iPhone Pickup

A live web app that shows which iPhone models are available for in-store pickup at New Hampshire’s three Apple Stores, and sends a push notification when one comes in.

Problem

Pickup stock for a new iPhone changes store by store. Checking Salem, Nashua and Manchester one at a time is slow, and a page that called the upstream source from every visitor’s browser would multiply requests for the same answer.

Approach

  • One server endpoint, /api/stock, runs as a Cloudflare Pages Function. It queries Apple’s public pickup-availability endpoint for the three stores and returns one normalized result.
  • Responses are cached at the edge with stale-while-revalidate: fresh for 30 seconds, kept for up to 10 minutes, so visitors share one upstream request and still get a fast answer while it refreshes.
  • A separate Cloudflare Worker runs on a cron trigger every 5 minutes and sends push alerts only when a model is available, at the check times each user picked (up to four a day), with instant alerts during launch windows.
  • The interface ships in 9 languages (English, Spanish, Chinese, Japanese, Portuguese, French, German, Korean, Italian), picked from the browser’s language.
  • It installs as a PWA with a web app manifest and a service worker.

Engineering highlights

  • Web Push implemented without a push library: VAPID (ES256) request signing and aes128gcm payload encryption written against the Web Crypto API, running in the Workers runtime.
  • Push subscriptions stored in Workers KV, with subscribe, unsubscribe and test endpoints.
  • The VAPID private key lives in an environment secret, never in the repository.
  • A health-check endpoint for the deployed functions.

Challenge

Sending encrypted Web Push from an edge function, where the usual approach is a Node library.

Solution

I followed the Web Push specs directly: sign the VAPID JWT with ES256 and encrypt each payload with aes128gcm using Web Crypto, so the whole alert pipeline runs on Cloudflare with no extra server.

Status

Live and maintained.