Gift Genie
An iOS app that remembers the people you buy gifts for and the dates you buy them for, suggests gifts by occasion and budget, and posts a physical card. Its design system is the most thoroughly argued of anything we have built.
In development — parts of this product have not shipped yet.

The problem
Gift-giving does not fail at the shop. It fails weeks earlier, at memory and follow-through — the birthday you meant to plan for, the friend you always buy for late, the card you never actually post. Choice was never the bottleneck.
So the brief was not a gift catalogue. It was an iOS app that holds the people you buy for and the dates you buy for, suggests something by occasion and budget when the date approaches, and posts a physical card so the intention turns into an object that arrives. Its design system is the most thoroughly argued of anything we have built, and that is the through-line of the sections below.
The interface problem
The brand book was explicit: a selected chip must be turquoise, never bright blue, "which reads as an action". A clean separation between what you can do and what is currently true.
It did not survive contact. Around sixty hand-written chip classes across twenty-two files were already painting selection blue, so the documented rule was false in the product long before anyone noticed. Asked to choose, the client kept blue and the action/state split was retired. Every call-to-action had also gone stadium-shaped, so a selected chip and a primary button now shared both colour and shape. Rather than reinstate a distinction nobody had followed, the system worked out what was actually separating them — a button is 52px tall and owns its line, a chip is 40px and sits in a row of siblings — and wrote that down instead.
The same drift hid in the app bar. Alignment flipped twice — centred as the iOS-native treatment, then left, once the screens were put side by side and the tab pages that draw their own in-body header turned out to have been left-aligned the whole time. The bar was also two points larger than the in-body header and sat the title seven points lower, enough to make one word read as a different level of heading depending on which screen drew it. The fix derives both values from one line box so they cannot drift apart again, and a test fails the build if a screen sets its own title style — thirteen screens were doing exactly that.
The design system
Most design systems list colours. This one rations them. Cool tones — deep blue, bright blue, turquoise — carry structure, action and state, the colours a user sees constantly. Warm tones, sun and coral, appear only where a gift is delivered, earned or celebrated, and are capped at roughly five per cent of any screen.
The target proportion is written down: sixty per cent neutral surface, twenty-five blues, ten turquoise, five warm. And so is the test — if a screen feels warm, something is being over-celebrated. That turns a subjective argument about tone into something two people can check.
Accessibility is a bar rather than an aspiration: every decision is judged at 44px, on a phone, in daylight. Tap targets never go below 44, layouts survive text scaled to 1.3×, and colour is never the only signal. The colour rules fall out of contrast rather than taste — warm accents always take ink labels because white on sun and white on coral both fail, and coral is too light to read as text at all, so error copy uses a separate darker token while the coral swatch is left to do fills and borders.
Under the interface
The app is Flutter and Dart on Material 3, with Firebase and sixty-three Cloud Functions behind it, and the design system it is held to runs to a 1,963-line document — the reason the arguments above could be settled by reference rather than by opinion.
Twenty-three feature modules keep the surface — gifting, reminders, occasions, the card pipeline, billing through RevenueCat — separable rather than tangled, so a change to how a card is posted never reaches into how a reminder is scheduled.
Palette
Bright blue
#0A8BFF
Every control — action and selection both
Deep blue
#14264D
Structure and dark surfaces
Pale aqua
#F0FBFB
One app-wide wash, painted once
Error text
#D9483A
Coral is too light to read as text
Scope
- Feature modules
- 23
- Design system doc
- 1,963 lines
- Backend functions
- 63
- Minimum tap target
- 44px
Screens



What we did
- Design system
- Product design
- Interface design
- Mobile build
Built with
- Flutter
- Dart
- Material 3
- Firebase
- Cloud Functions
- RevenueCat