Three products I built end to end, each one click from its live version — then fifteen years of employment, described in words, because that work belongs to the companies I did it for.
Plane Spotter Board answers one question: is anything worth driving to the airport fence for in the next half hour? It lists aircraft on approach to an airport, filterable by airframe — quads, double-deckers, widebodies, freighters — alongside the runway direction in use, the field’s weather and where each flight came from.
The first version had every open browser poll the ADS-B aggregators itself. That does not survive more than a handful of users: the community APIs are rate-limited, and upstream load grew with every tab. Now one server polls each airport every fifteen seconds and fans the result out to every browser over Server-Sent Events. Upstream cost is a function of how many airports are watched, not how many people are watching, and nothing on a request path ever calls upstream.
There is no database, because the data has a useful life of seconds — an aircraft on final is on the ground two minutes later. The server keeps the last good snapshot in memory; when every upstream host fails, it keeps serving that snapshot, marked stale with its age, while it backs off.
The tests run against captured real API responses rather than hand-written mocks. A mock only tests my assumption about a payload; a recording of what the aggregator actually returned over Pearson tests the payload. Looking at real traffic is also how the board learned that a flight number’s stored route is often not the route being flown — so it shows the route as scheduled instead of asserting it.
The API runs on my own hardware, so the live board is occasionally in its error state. The source and the screenshot above show what it does when it is up.
PanMilli is the shop for my handcrafted hats, crowns and accessories. I designed and built it end to end: the storefront, checkout, order emails and the admin dashboard behind them.
Etsy stays the single source of truth for inventory. Firebase Cloud Functions sync listings — prices, images, variations and personalisation options — through the Etsy Open API, so a product is edited in one place and the storefront never waits on Etsy to render.
Payments go through Stripe’s Payment Element, and an order is only recorded and emailed once Stripe’s webhook confirms the payment. Pages are pre-rendered for search engines, and every pull request runs lint, unit tests and Playwright end-to-end tests before it can merge. I also built the brand’s companion Shopify store.
The website for E’shee Clinical Esthetic, a skincare business. I designed it, built it, and have maintained it ever since — an ongoing engagement rather than a launch-and-leave project.
The live site carries the product catalogue, articles and a glossary, and separate sections for professionals and distributors. It is the other half of client work: keeping a site running and current for years after launch.
Its replacement is in preview: a React rebuild with a cleaner storefront — serums, creams, peels and complete systems — shown above. Checkout and accounts are switched off in the preview until it goes live.
Most of my fifteen years have been spent on large, consumer-facing applications in regulated financial environments, where performance, accessibility and cross-browser reliability are requirements rather than nice-to-haves.
A recurring thread is shared components. I contribute to CIBC’s corporate component library today. Before that I delivered reusable UI components at RBC, extended the corporate component set at NielsenIQ, led LoyaltyOne’s migration from AngularJS to React, and built a library of reusable React components at Citco. At Morneau Shepell I designed UI concepts and then built them.
Accessibility has been part of the job since Morneau Shepell, where I brought markup into compliance with WCAG 2.0 and AODA; at CIBC every feature ships to strict accessibility requirements with analytics built in. These days I also work with AI-assisted, spec-driven development, using GitHub Copilot and GitHub Spec Kit.
Client-facing digital banking in Vue 3 and TypeScript — a new login system, client information, data sharing between applications — and components for the corporate library.
RBC
Senior Front-end Developer · –
Data-visualisation components and large-dataset export in React and TypeScript, integrated with .NET APIs.
NielsenIQ
Senior Front-end Developer · –
Replaced native Qlik components with custom ones for faster page loads, and extended the corporate Bootstrap component set.
Citi
Senior Front-end Developer · –
A React analytics widget turning tables into interactive 2D and 3D models with D3, over an ELK presentation layer.
LoyaltyOne (AIR MILES Reward Program)
Senior Front-end Developer · –
Led the migration from AngularJS to React over Node.js microservices; D3 visualisation and in-app PDF export.
Citco Group
UI/UX Front End Developer · –
A reusable React component library for a data-driven financial platform, and the team’s Jest and Selenium testing standards.
Morneau Shepell
UI/UX Developer · –
UI concepts built in AngularJS, JSON-driven form generation, and WCAG 2.0 and AODA compliance work.
Canadian Tire
Front End Web Developer · –
New features and a reusable refactor of the presentation layer.
Torstar Digital
Web Developer · –
Components and widgets; migrated ASP Classic applications to .NET.