Diya Sabharwal

San Francisco, CA

The Charms app icon

Charms

a bracelet for your phone

Diya Sabharwal · design case study

Charms is an iOS app I created, designed and coded on my own. You draw charms and send them to friends, they add them to their bracelet, and the bracelet lives in their Dynamic Island whenever they’re using their phone.

1person
Designed, coded and shipped alone
2months
Of nights and evenings
30in beta
Partners, parents and long-distance friends
40on the waitlist
Signed up after I presented it at the Gumloop Design Gallery

How it works

You make a charm on your phone, tell a friend its magic word, and they wear it on theirs

  1. Draw a charm

    Draw one by hand, or pick a stock charm.

  2. Seal it behind a magic word

    Pick a magic word, then press and hold the charm. There’s a haptic, and the word’s letters circle it like an incantation and pass into it as it seals.

  3. Your friend whispers the word

    You tell your friend the word. They open Charms, tap receive and type it in.

  4. It lands in their dish

    The charm arrives with a small ceremony, and they accept it into their dish, the jewelry tray on the app’s home screen.

Worn on the Dynamic Island, all day

They drag it from the dish onto the bracelet to wear it. Once worn, it stays on the Dynamic Island through everything else they do. Press the island and the whole bracelet opens, with each charm’s giver underneath.

And on the lock screen, two ways

While they’re wearing charms, a Live Activity puts the bracelet on the lock screen with each charm’s giver. A widget under the clock keeps it there always: just the charms, no names.

The lock screen with the bracelet as a Live Activity, each charm labeled with its giver
Live Activity
The lock screen with the bracelet widget under the clock, charms only
Widget

The metaphor

I extended the charm bracelet into every surface of the app, and it ended up making the product decisions

It started as a question: what if you could send gifts and keep them on your phone? A Tamagotchi app keeps a pet on the Dynamic Island. What if friends could send each other gifts that live there?

Thinking that through, the gifts became charms and the island became a charm bracelet. I didn’t stop there. Skeuomorphism mattered to me, so each question that came up next was answered the same way: by the real object.

The top of a phone home screen, with a small cat charm sitting in the Dynamic Island
It began as gifts kept on the island
The same screen with the Dynamic Island opened into a gold thread, a cat charm called Miso hanging from it
It became a bracelet that opens from it

3

How many charms can you wear? The island fits three

The island is a small surface, and three charms is the limit for readability. Any more and nothing reads, so the limit became the design.

The expanded island: three charms on a gold thread, Matcha from Maya, PikaWhat from diya, GOAT from Sarah

Where do the rest go? Not a gallery, a jewelry tray

People want to collect more than three. I considered a gallery view, then extended the metaphor instead: an actual jewelry tray on the app’s home screen. Charms rest there, and the screen stays clean.

The app's home screen: a jewelry tray holding charms under the bracelet

How do you put one on? Tray to bracelet, by hand

You pick a charm up off the tray and drag it onto the bracelet, the way you would with a real one.

Should charms expire? Charms don’t explode

A common request was exploding charms: charms that expire, streaks like Snapchat. It would help retention. But charms in the real world don’t explode.

And streaks fatigue people. The research shows a short burst of motivation, then exhaustion and bad feelings toward the app. My friends and I stopped using Snapchat for exactly that reason. Charms are meant to be ambient, so they are permanent.

The request, acted out

12

How many can you keep? A tray holds twelve

A real jewelry tray only holds so much. I translated that constraint directly.

And when the tray is full? Another tray, two dollars

A power user who wants to keep more than twelve buys another tray, and another, and keeps collecting. Anyone who doesn’t want to pay lets a charm go.

The real-world constraint became a business model that makes sense inside the metaphor. It is upcoming, which is why this screen is a wireframe.

The atelier

Where a charm gets made: pick one, draw one, or trace one

  • Every stock charm comes with a note

    Tap send charm and the stock charms appear. Each one arrives with a cute note already written, which teaches people how to write their own.

  • Or draw your own

    A hand-drawn cat charm on the atelier canvas, with four inks and two pen widths below

    Four inks and two pen widths. This is where the app turns sentimental for people.

  • Stencils on demand, from an on-device model

    Ask for a stencil by name and an outline appears on the canvas for you to trace, so anyone can draw better.

  • Add a note, seal it

    Once the charm is drawn, you add its note. Here selenalee writes “matcha queen!!” on her matcha, and the note hangs under the charm wherever it goes.

AI that helps you draw and never draws for you

This is my intentional use of AI: not a replacement for human creativity but an augmenter of it. That’s what I think intelligent creative tools should do: empower creativity, and never make people feel replaced.

The stencil helps people draw better without taking away the satisfaction of drawing by hand, or the sentiment of sending something hand-drawn.

Keepsakes, across two phones

My cousin and his fiancée wear keepsakes from each other on their phones: hand-drawn charms with each other’s names, their dogs, their inside jokes.

My friends and I send each other little digital gifts from across the world, now that we’ve all graduated.

One phone, held in a hand: its island open on three hand-drawn charms, the name Sid in gold script, a Celtics crest, and a dog called Sweet Syrus
The other phone: a red heart captioned My beautiful Divya, a moon called Night, and a dog called Duncan
My cousin’s and his fiancée’s phones, photographed when the app was still called Bijoux

Under the hood

The design decisions and the engineering decisions were the same decisions, made once

Each charm is a damped pendulum

Inside the app, the worn charms aren’t animated, they’re simulated. Each one is a damped pendulum pivoting at its ring. Tilt the phone and they swing toward the new down, overshoot and settle. A flick of the wrist adds a kick.

Every charm has its own spring, so the cat swings slower and wider than the star.

target = atan2(g.x, −g.y)        // where down is, clamped to ±0.6 radk = 20 + 14 × (5 − sway.duration)  // heavier art, softer springvel += (−k·(θ − target) − 2ζ√k·vel + kick)·dtθ += vel·dt                      // ζ = 0.42, underdamped

One clock for the whole bracelet

Physics at 60 hertz could eat a battery, so the whole bracelet runs on one clock. Three charms cost one timer, not three, and the gyro is only awake while the app is in front. With Reduce Motion on, it never spins up.

The Dynamic Island can’t run any of this, so its Live Activity is kept off that clock.

CoreMotionGravity and rotation rate at 60 Hz, started on foreground, stopped on background
One CADisplayLinkIntegrates every pendulum in one step and publishes one dictionary of angles
SwiftUIrotationEffect anchored at the ring, no per-charm timers, the idle breath is a sine inside the same step
Live ActivityA ContentState handed to the OS when what you wear changes, no timers, no motion, never continuous

A word is a key, a username is a query

Sending started with usernames, a chain of four hops. Each one can be stale, offline or racing another write.

A magic word collapses it to one hop. The word becomes the record’s name, and CloudKit refuses a name that already exists. The receiver needs nothing but the word.

By usernameLook up the directory recordResolve it to an ownerEscrow the gift under a random codePush, then hope they fetchFour hops
By magic wordSave the record gift-OUR-SONG-7Sealed, or taken, in one round tripClaim is a fetch by id, no index, no queryOne hop, atomic

A gesture can’t be the only door

The seal is a press and hold, and VoiceOver and Switch Control can’t perform that. When either is running, a labeled button appears in its place, and the ritual stays as it is for everyone else.

Everything the visuals say is also spoken.

What VoiceOver says“PikaWhat, press and hold to seal it under this word”“letters, with at least one number, done”“seal it under this word, button”“PikaWhat, a hand-drawn charm from diya, on your bracelet, double-tap to open”
The seal screen with a magic word entered and both of its rules ticked
The seal screen without VoiceOver

Luminance is the alpha, not a green screen

The stock charms are painted, and their art arrives as objects on solid black. The obvious move is a color key, but a key clips the soft brush edge and tints it.

So the alpha comes from luminance instead. That keeps the painted edge soft, which is the difference between a sticker and a painted object.

The same painted charm three ways: on black, as an alpha mask made from its brightness, and composited on color
Painted on blackAlpha from luminanceOn anything
a = max(r, g, b)                    // black matte: brightness is alphaif a == 0: out = (0, 0, 0, 0)else: out = (r·255 ÷ a, g·255 ÷ a, b·255 ÷ a, a)// unpremultiply, or the edges go muddy

Worn is a boolean, not a second list

Worn is a field on the charm, not a separate bracelet collection. The dish and the bracelet are two filters over one array.

That removes a whole class of race conditions: there is no move to fail halfway, a charm can’t be in both places, and the island can’t drift out of step.

var wornObjects: [Charm] { myCharms.filter(\.isDynamicIslandEnabled) }var dishObjects: [Charm] { myCharms.filter { !$0.isDynamicIslandEnabled } } // one array, two projections, no move operationmyCharms[idx].isDynamicIslandEnabled.toggle()   // every surface recomputes
dishfilter false
isDynamicIslandEnabled
braceletfilter true
Build details

A bracelet for your phone

  • One metaphor, carried from the first tap to the price tag
  • AI that augments a hand, and never replaces it
  • A password, dressed as a magic word
  • The technical side, abstracted away