- Initialize npm project with TypeScript
- Install dependencies: hono, vitest, wrangler
- Configure tsconfig.json for Cloudflare Workers
- Configure wrangler.toml
- Set up Vitest config
- Create
src/index.tswith Hono app skeleton and route registration
- Implement raw coordinate parsing (decimal degrees, comma-separated, cardinal directions)
- Implement Apple Maps URL parsing (extract
ll/qparams frommaps.apple.comURLs) - Implement Google Maps URL parsing (extract coords from
google.com/mapspath and query params) - Implement shortened URL resolution for
maps.app.goo.glandgoo.gl/maps(follow redirect, then parse) - Implement Canadian bounds validation (lat 40-70, lng -145 to -50)
- Write unit tests for all coordinate formats, edge cases, and invalid input
- Implement forecast fetch via
api.avalanche.ca/forecasts/en/products/point?lat=&long= - Define TypeScript types for the API response (danger ratings, problems, highlights, dates)
- Handle API errors (network failure, 404 no region, unexpected response shape)
- Write unit tests with mocked API responses (success, no region, error)
- Implement template formatter producing <=160 character SMS reply
- Handle danger rating enum-to-string mapping (low through extreme)
- Handle truncation of problem list and region name to stay within 160 chars
- Write unit tests with various forecast fixtures (short name, long name, many problems, no problems)
- Implement
POST /sms/incomingroute - Parse Twilio webhook body (form-encoded: Body, From, MessageSid)
- Wire together: parse coordinates -> fetch forecast -> format -> TwiML response
- Implement Twilio request signature validation (with env var to disable in dev)
- Implement error reply messages for each failure case
- Write integration tests with mocked Twilio requests and Avalanche.ca responses
- Implement
GET /healthreturning{ "status": "ok" }
- Implement stats store (circular buffer, counters, region map, uptime)
- Instrument SMS handler to record each request
- Implement phone number masking (
+1******7890)
- Implement
GET /admin/statsJSON endpoint - Build admin HTML page (inline CSS, vanilla JS, no framework)
- Display uptime, total requests, error count, recent requests table, requests-by-region list
- Poll
/admin/statsevery 30 seconds - Implement
GET /adminserving the HTML page
- Deploy to Cloudflare Workers (or Lambda)
- Set environment variables / secrets (TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
- Acquire Twilio phone number
- Configure Twilio incoming message webhook URL to point to deployed
/sms/incoming - End-to-end test: send SMS, receive forecast reply