Keyboard first, and thumb first
A command palette, G-then-a-letter shortcuts, swipe and long-press on habits, pull to refresh, and why each one is a shortcut on top of a button rather than the only way in.
18 posts.
In: Design Security & Privacy Product Postmortems Engineering Infrastructure
A command palette, G-then-a-letter shortcuts, swipe and long-press on habits, pull to refresh, and why each one is a shortcut on top of a button rather than the only way in.

Reloading any page in the app, or opening a shared link, landed on Today. The SPA rewrite rules pointed at /index.html, and Cloudflare Pages redirects that to /. It had been true for every deployment.

A habit reminder now has Done and Snooze buttons. The service worker that handles them has no access token, by design, so each button carries a signed, single-purpose link instead.

The new daily coach is a few if-statements over your own data. Why that beats a generated paragraph, and why the app shows only the notes its existing cards don't already cover.

Habit routines and the focus timer shipped without touching the streak engine. Why a routine stores nothing but a list of ids, and why the timer stores a start time instead of counting.

The app's Permissions-Policy says camera=(). Barcode scanning shipped anyway, by reading a photo instead of a video stream, and the lookup sends the barcode and nothing else.

Three real bugs found by using the OTP flow the way a person actually would: a stuck login, a false 'already registered' error, and a confirmation screen that didn't lead anywhere. Plus a status page that finally watches the whole stack.

Turnstile went on signup, login, forgot-password, resend-verification and recover for one reason: those five endpoints can empty a free email quota or grind past a rate limit, and a CAPTCHA on the feed or the streak grid would only annoy people who never touch them.

A small bar row and a keep-rate percentage on every habit's detail page - kept in lime, missed in flame, because the week strip and calendar markers already meant that, and a new chart is the wrong place to invent a third colour convention.

Habits already had a category and a colour. The one thing Today's week board didn't do with that was use it to group the rows - and it still doesn't, for the common case of one category, on purpose.

The home screen used to be a stack of coach cards. It now opens on a tear-off date and this week as a board you can cross off, because the first question anyone has is 'what's left today?'

Picked once at onboarding, read from localStorage ever since - and gone the moment someone switched phones or cleared their browser. It was account state that had been living like a device preference.

The old look was near-black with a lime accent: a fitness app that looked like every fitness app. The new one is a printed wall calendar you cross off in marker, because that's what the product actually is.

The wall calendar palette lasted a day. What we rolled back, what we kept, and why structure and colour are separate decisions.

Adding an 'Add a note' action to a toast revealed that no toast button in the app had ever worked: the swipe-to-dismiss handler captured the pointer and stole every click.

PaceStreak had German and Spanish catalogues. They're gone now. Removing a language isn't deleting two files: it's the picker, the stored preference, the tests and every place that assumed more than one.

How the PaceStreak app saves every session to the device first, queues writes in an IndexedDB outbox, and syncs across devices with an idempotent batch endpoint and a sequence cursor.

Logging a habit works the same from the Today row, the week strip and the calendar: a big minus and plus, a few one-tap amounts, and a note.
PaceStreak is a habit and streak tracker for training and everything else worth doing regularly.