Case study · Life Time · 2022 to 2025
Life Time's first Vue 3 page, then the sign-up flow behind the digital guest pass
I started by rewriting Find a Location, the page people use to find a club, as the first Vue 3 code on Life Time's public website. Then I led frontend on the Account team, where I wrote the web code behind the digital guest pass and handled sign-ups for hundreds of thousands of new accounts.
- Role
- Principal Software Engineer (contractor)
- Team
- On the Account team, me leading frontend, a junior frontend engineer, a senior backend developer, a PM, and QA
- Stack
- Vue 3, Vue 2, TypeScript, Pinia, Google Maps, Vitest, Playwright, Datadog
Find a Location, rebuilt in Vue 3
The old page was jQuery. The project had three goals: retire the jQuery code, move to a new and very different visual design, and work well on phones. The organization had already chosen Vue 3 as its direction, and I was the one who knew it. The page is still live and, as of September 2026, looks the way it did when I shipped it.

An HTML and CSS specialist built the new design as static markup. I made it a working app: search with Google Places autocomplete, club results from existing APIs, amenity filters, a custom-styled Google Map, and a phone layout where the list and map become separate views. I called the Google Maps JavaScript API directly instead of using a Vue wrapper library, so I could reuse patterns that already worked. The app runs inside the site's Adobe Experience Manager pages, next to the Vue 2 build the rest of the site still loads.
One state change, two ways to select a club
The map and the list had to stay in step. Clicking a marker scrolls the list to that club, and clicking a row does the same thing as clicking its marker. I built this around shared Pinia state: the marker and the row each set the same selected club in the store, and everything else reacts to that one change. It doesn't matter which one you click, because both reach the same end state through the same code.

I wrote unit tests for the Vue logic in Vitest and a few Playwright tests that click through from a result to a club's page. The launch had no deployment problems.
The digital guest pass
Members used to bring a guest to the front desk, where the guest filled out paperwork and a waiver. Members got two passes a month. Life Time announced the digital guest pass in May 2024, about four months after I joined the Account team. The idea came from marketing and business development, and I wrote the web code that made it work.
A member texts a pass link from the app. The link tells our page who invited the guest. We ask for the guest's email first: an existing account goes to log in, and anyone else goes to sign up. The new account records whose guest it is, and when the guest logs in to the app, the app reads that and shows a QR code that gets them into the club.
Most of the tricky work was handling users in different states, starting with people who already had accounts. The handoff to the app turned out simple, since the identifier traveled from the text message, through our page and the new account, to the app at login.
Every guest now needed a free account, which fed Life Time's push to grow its free LT Digital subscription. LT Digital passed 1 million subscribers by October 2024 and 1.7 million by February 2025, around when my contract ended. My code handled the sign-ups for hundreds of thousands of them. (Life Time's public numbers don't say how many came through guest passes.)
The same flow for race packet pickup
In fall 2024, I generalized the flow for Life Time's athletic events, starting with race packet pickup. Participants get an email whose link carries the event, our sign-up page customizes itself for that event, the account records it, and the app shows a QR code for the pickup line. I made the page data-driven: a map from event ID to welcome text and branding, so adding an event meant adding an entry, not writing a new page.
The Life Time Miami Marathon and Half in February 2025 was one of the first events to use it, with a fast-track app lane at bib pickup. The Life Time Chicago Half Marathon now requires all participants to use the app for packet pickup.
Frontend errors that showed up before anyone reported them
I brought Datadog browser logs to the account section, with logging and proper error handling throughout, so exceptions in the UI (including unhandled ones we'd never have seen) showed up in Datadog. Alerts in Microsoft Teams told us when things looked abnormal. Many turned out to be API failures, not bugs in our code, and because the UI saw them first, we were often the ones telling other teams about problems in their APIs.
Retrying account creation under load
The most perplexing alerts were account-creation failures that came in spurts, worst right after Life Time emailed a race's participants and invited them all to sign up at once. Life Time learned to stagger those emails. The backend couldn't simply be changed, so I did what the frontend could: up to seven attempts with exponential backoff, about two minutes of spinner in the worst case, then a message to try again later. The backend team confirmed a retry couldn't create a duplicate account.
What I'd do differently
I didn't add jitter, a small random delay on each retry that keeps thousands of clients from retrying at the same moment. I'd add it next time. More to the point, retries were a band-aid. The real fix belonged on the backend, such as a queue to spread out sign-ups during a spike.
Along the way
- My first months were cleaning up older JavaScript that loaded on every page of the member and marketing sites. I traced what actually ran, deleted the dead code, and replaced jQuery with native JavaScript, leaving a little in one section already slated for a rewrite.
- Without being asked, I reviewed pull requests across every frontend repo in the organization, pushing for modern JavaScript and Vue code that would carry over to Vue 3. Most of the developers came from backend work and often took the suggestions.
- On the Account team, I mentored our junior frontend engineer, who took over the account frontend when I left.