Tanmay made you a case study

The unwrapping is the gift.

Dearly is a free, no-login way to send someone a wrapped moment instead of a text — live at fromdearly.com, built solo, end to end. So this case study arrives the way the product arrives. Untie it.

Drag the tab • or tap to untie — the product's own words Opened. Drag it back to wrap it up again.

RoleProduct design & frontend build, solo TypeSelf-initiated · shipped ScopeProduct · UX · Visual system · Build PostedAug 9, 2026 — live
Why this exists

I went looking for this, and every version of it was a chore.

This didn't start as a product idea. It started as a failed errand: I wanted to send someone something that felt like more than a text, went looking for a way to do it, and gave up. Three things were wrong with everything I tried — and each one turned into a decision.

01

It only went one way.

You send a thing into the void. The person receives it and there's nowhere to put what they felt about it — no reply, no acknowledgement, nothing back. For something whose entire purpose is connection, the connection was one-directional.

→ Became the hardest problem in the build. See Afterglow.
02

Too many choices, or none at all.

Either a catalogue of hundreds of templates to scroll before you can start, or a single fixed card with your name dropped into it. Both fail the same way: the effort goes into picking instead of into what you actually wanted to say.

→ Three wraps. Not one, not a hundred.
03

The whole thing felt like admin.

Make an account. Confirm an email. Now make them make an account. A gesture that should take two minutes turned into a form-filling session, and the feeling drained out somewhere around the password field.

→ No account, either side. One screen, one link.
Packed · the wrapping room, step by step

Six decisions, one screen.

The sender never navigates anywhere. A live preview holds the left half the whole way down, and every choice on the right repaints it before they've finished making it — so “what will they actually see” is never a guess. Half-finished words and picked media survive a reload, and a chosen add-on won’t wrap empty — it has to hold a real photo or a playable note before the wrap moves on.

Step 01, Who is this between: sender and receiver cards side by side, an occasion picker, and the wish textarea with a character counter reading 93 characters of you.
01

Who it’s between. Two named cards, not one form. The sender’s email exists only so a reply can find its way back — the receiver never sees it.

The occasion picker with Just because selected, above the wish textarea reading 'Remember that road trip playlist we made? I still cannot hear that one song without laughing.' and a counter showing 93 characters of you.
02

The wish. One open textarea, no blanks to fill, and a counter that reads “93 characters of you” rather than characters remaining.

Step 02, Choose the wrapping: three named wrap styles, with Raspberry love note selected and the live preview re-themed to raspberry and cream.
03

The wrapping. Three, not one and not a hundred. Each is a full re-theme — picking one repaints the parcel on the left mid-thought.

Step 03, Leave fingerprints: optional voice note and photo memory, above a pink panel describing the receiver's experience.
04

Fingerprints, optional. A voice note and a photo, both opt-in: “pick one, both, or neither — the wish is complete on its own.”

Step 04, Choose the timing: right now, tomorrow morning, or a custom moment, with Wrap it waiting at the bottom.
05

The timing, then wrap. Now, tomorrow at 9am, or an exact moment — the option that forces real infrastructure behind the send button.

Step 05: Sam's wish is ready. Choose how it lands — Email from Dearly, or copy the link and send it anywhere — with the receiver's address and a preview of the delivery email.
06

Choose how it lands. Wrapping mints two private links. Copy the link, send it anywhere sits level with email, not beneath it.

Keep scrolling 01 / 06
In transit · the part that took longest

Knowing whether it actually arrived.

This was the hardest thing in the project, and it's invisible. Writing and wrapping a gift is a screen problem. Getting it to land — and knowing when it didn't, and why, and where it stopped — is a different kind of problem, and it took the longest to get right.

A gift is not a page view. If it silently fails to arrive, the sender doesn't just lose a feature — they think their person got something and was unmoved enough not to mention it. Silent failure is the worst possible bug in a product like this.

How a gift actually travelsthe shape that made tracking possible
1 · WrapThe gift is created first, as its own step, and comes back with a permanent home. It exists before anyone has tried to send it anywhere.
2 · DeliverSending is a separate operation against that gift, not part of making it. Splitting the two is what makes the rest of this possible.
Because of thatScheduling is real: “tomorrow at 9am” is a delivery booked against a gift that already exists, not a request held open in a browser tab.
And because of thatA failed send is recoverable instead of fatal. The gift didn't evaporate — delivery just hasn't happened yet, and can be retried or rerouted.
Handing it overEmail is one channel; “copy the link and send it myself” is an equal one, not a consolation prize. Some gifts are better handed over in person.
When it failsThe failure has a written script, not a red triangle: “Delivery could not be completed. Copy the private link instead.” The moment survives the outage.

The bot problem, without a puzzle.

Anything that sends email on a stranger's behalf gets abused within days of going live. The standard fix is a CAPTCHA — which would mean asking someone to identify traffic lights in the middle of the most sincere thing they'll do all week. Cloudflare Turnstile sits on both doors instead — sending a gift, and sending a feeling back — and shows itself only when the traffic looks wrong; the cost tops out at a single checkbox. No grid of blurry crosswalks between a person and the thing they meant to say.

Delivered · the ten seconds that matter

The other side of one link.

No form, no account wall, no install — they land on a page built only for them and pull the ribbon with their hands. What follows is every screen they actually meet, straight from the live product, in the order they meet it. The stages after the wish exist only because a voice note and a photo were attached — and each one gets a ground colour of its own. Two quiet courtesies hold the pacing: each stage’s media is preloaded before its reveal, and the first genuine untie is the one the record keeps — replaying never re-marks the gift as newly opened. At the end, Tuck this wish away saves the wish as a letter, not an export.

Arrived: A page built only for them — their name, the occasion, and an arrived stamp, before they have touched anything. The wish: The note gets the screen to itself. No nav, no branding competing for the read, nothing hurrying them along. The memory: A photo becomes its own stage on its own ground — presented as a polaroid, not an attachment. The voice: Press play. Stay awhile. The one moment where the right thing to do is stop reading and listen. The reply: It asks for one feeling back, routed privately to a sender whose address was never revealed.

Arrived. A page built only for them — their name, the occasion, and an arrived stamp, before they have touched anything.

The wish. The note gets the screen to itself. No nav, no branding competing for the read, nothing hurrying them along.

The memory. A photo becomes its own stage on its own ground — presented as a polaroid, not an attachment.

The voice. “Press play. Stay awhile.” The one moment where the right thing to do is stop reading and listen.

The reply. It asks for one feeling back, routed privately to a sender whose address was never revealed.

Part two · the machine

What one link touches.

Everything above is the ceremony. This is the crate it ships in — one app on Cloudflare, and the short list of things it talks to. The stack was chosen the way the wrapping was: as few pieces as possible, each with one job, nothing the ceremony doesn’t need.

The wrapping room

Next.js + React, in TypeScript

One app renders both sides of the gift. Framer Motion runs the choreography — the untie, the lid, the staged reveals — as material behaviour, not decoration.

↓ wrapped, then handed over
The sorting floor · server routes

One route, one job

Create, deliver, media, reply, report, manage, delete. The gift is created first and delivered second — the split from part one lives here, as two different routes.

↓ and behind it, three rooms
D1 · the ledger

Every fact with a timestamp: gifts, deliveries, reactions, reports, retention cleanup. If the tracking page says it, a row here says it first.

R2 · the vault

Photos and voice notes, served only through the app’s own private routes — never from a public bucket.

Turnstile · the doorman

On both doors, invisible until the traffic looks wrong — part one already made this argument.

↓ handed to the courier
Resend · the courier

Email out, truth back

Three transactional emails leave — the gift, the sender’s confirmation, the reply notification. Webhooks come back and write down what actually happened.

↓ and at the far end
The other end

Two capability links, no accounts

One the receiver opens, one the sender keeps. The links are the identities — the closing argument of part one is a line of architecture here.

Still in transit · what the courier reports back

An email can land six different ways.

Part one called silent failure the worst bug this product could have. This is how failure is made loud: the courier’s webhooks write the truth back onto the delivery — six states, each with a consequence — and the tracking page shows those stored facts, never a simulated progress bar.

Addresses get the same care as feelings. After delivery the system keeps a masked destination hint and the provider’s status, so a send can be retried without the stored address ever being shown again — and a suppressed address stops being written to at all.

Accepted

The courier took the parcel. The clock starts.

Delivered

Landed. The tracking page flips the moment the webhook does.

Delayed

Still moving. Honest limbo beats fake certainty.

Bounced

The address wasn’t real. The sender is told — and offered the link instead.

Complained

Marked as spam. The address joins the suppression list and Dearly stops writing.

Failed

The courier gave up. The gift survives — delivery retries, or gets handed over by hand.

After it leaves your hands

The wait gets a page of its own.

Press send on most things and you get confetti and a dead end. Here the editable send screen folds away into a calmer post-send state, and a confirmation email carries the sender’s private management link — their only key back in. Behind that link: a page that says what has actually happened. Delivered, untied, expiring, deleted — every state on it is a stored fact from the courier and the ledger, never a simulated progress bar.

The private sender view on Dearly's yellow ground: Sam's gift after wrapping, marked for Alex's eyes, with copy-receiver-link and delete buttons, a send-again field that never shows the stored address, status cards reading Gift untied and Delivered beside an expiry date, a Little echoes section holding a LOVE reply, and an email-activity list with masked addresses. The private sender view — every state on it is a stored fact

Three letters, one voice.

All the email is transactional — Resend carries it, webhooks grade it — but none of it reads like infrastructure. One system for all three: Dearly’s wordmark on a dark ground, a colour-blocked header, one message, one button. Personal, never promotional — the inbox is someone else's house, so the letters arrive dressed for the occasion.

The receiver's delivery email on desktop and phone: a pink-headed card on a dark canvas reading 'This has your name all over it', with an Untie your gift button. 01 — the only thing between a link and a ceremony
The sender's confirmation email on desktop and phone: 'Your gift is wrapped. This is your way back.' above a Keep track of the gift button carrying the private management link. 02 — the management link travels here, and nowhere else
The reply notification email on desktop and phone: 'Something came back to you', with the receiver's LOVE reaction and written reply quoted on a pink card. 03 — and when something comes back

And what the receiver keeps.

The last stage of the ceremony offers a keepsake: Tuck this wish away saves the wish as a small paper object with a folded corner — a letter, not a PDF export with a timestamp. The gift expires in ninety days; the letter is the part that was always meant to outlive the link.

The keepsake moment on Dearly's blue ground: 'Keep this one close' above a folded-note object labelled Tuck this wish away, with an Unwrap the gift again button beneath. The folded note — a letter, not an export
The fine print, kept human

A link is a key, not a password.

No accounts means access is a capability: whoever holds the link holds the gift. That tradeoff isn’t buried in a policy PDF — it’s written in the product’s own voice at fromdearly.com/trust, and every promise on that page has machinery behind it.

A small promise, said clearlyand what enforces it
01 · The link is the keyGifts are unlisted, unsearchable, and have no public gallery. Held up by: capability URLs minted per gift — nothing to browse, nothing to guess.
02 · Addresses stay outThe receiver never sees the sender’s email. Held up by: replies routed server-side, and only a masked destination hint kept after delivery.
03 · Every gift endsGifts and their private media expire after 90 days — or sooner, on the sender’s word. Held up by: retention cleanup that actually deletes. The receipt is below.
04 · Feelings aren’t inventoryNothing is sold, published, or advertised against. Held up by: the counting rules further down — content is never an event.
The honest limitDearly cannot stop a screenshot or a forwarded link, and says so in plain words. What it can do is hand the sender a kill switch — the management link deletes everything, immediately.
The off switch

Delete means deleted.

One press on the management link. No support ticket, no thirty-day limbo, no “deactivated” that secretly means archived. The receipt:

Delete, itemisedone click, everything below
  • The gift record itselfgone
  • The photo — the stored object, not a flaggone
  • The voice note — samegone
  • The asset records pointing at bothgone
  • Every reaction and written replygone
  • The delivery historygone
  • Any safety reports filed against itgone
  • Both private links — receiver’s and sender’sgone
What remainsNothing

Verified in production rather than assumed: after a delete, both links die, the rows are gone, and the media routes return nothing. The page below is what a dead link looks like — the product’s voice, not a 404.

Dearly's dead-link page: 'This little parcel has left the table. The link may have expired, been deleted by its sender, or taken a wrong turn. Private gifts stay private — even when they disappear.' Expired, deleted, or never real — same kind page
Counted · and never counted

Counted, never read.

There’s a first-party event when a gift is started, wrapped, sent, opened, replied to, kept. There is no event that knows who did it or what it said. The numbers can answer does the ceremony work — and cannot answer who stood in it.

Counted, anonymously

  • ✓A gift started
  • ✓Each wrapping step reached
  • ✓Add-ons chosen — photo, voice, both
  • ✓A gift completed
  • ✓The delivery method picked
  • ✓An unwrap begun — and finished
  • ✓A feeling sent back
  • ✓A keepsake saved

Plain first-party events, stored like everything else.

Never counted

  • ✗Names
  • ✗Email addresses
  • ✗The wish itself
  • ✗Written replies
  • ✗Photos or voice notes
  • ✗The private links
  • ✗IP addresses
  • ✗Browser fingerprints

No ad pixels, no profiles, nothing third-party.

When it doesn’t work

Failure gets the same voice.

Uploads that die mid-flight, media too big to keep, a courier outage, a webhook that never arrives, a link opened after its ninety days — each has a written script instead of a stack trace. The rule from part one holds at the edges too: the moment survives the outage.

The quiet audit.

The ceremony also holds when nobody is watching it with a mouse on a big screen: keyboard all the way through, visible focus, status and errors announced to screen readers, contrast and touch targets checked, and reduced motion honoured without gutting the reveal — the ribbon still unties, it just doesn’t make anyone wait. Desktop, phone, tablet, and the in-app browsers links actually get opened in.

Left out · on purpose and otherwise

What didn't go in the box.

One person, about a month, start to live. Scope was the whole game — three things came out along the way, for two different reasons, and both reasons are worth being straight about.

Cut listand where each one went
Money, in any formGift cards, chipping in, tipping the sender — the obvious next dimension for a gifting product. The payment rails didn't come together for a solo build, and rather than hold the launch hostage to that, the entire money dimension came out. Cut for a real-world constraint, not a design one.
Text messagesSMS delivery would beat email for something this personal — most of these gifts get handed over in a text anyway. It's carrier setup and per-message cost on a free product, so it waited. The copy-the-link channel exists partly to cover this gap by hand.
Accounts · history · a dashboardThis one was cut on purpose and stayed cut. Every one of them would have solved the reply problem the easy way, and every one would have reintroduced the exact friction that made the category feel like a chore. The harder path was the point.

What's next.

Money goes back on the table first — it's the one cut that was forced rather than chosen, and it's the difference between a thing people love and a thing that can sustain itself. SMS follows. Both are additive: neither requires an account, so neither breaks the one rule the product is actually built on.

Afterglow · complaint 01, answered

Where do you anchor a reply between two strangers?

Every messaging product solves replies with identity — two accounts and a thread between them. Take accounts away and there is nothing left to hang a conversation on. The answer was to make the links themselves the identities: wrapping mints two private URLs at once, one the receiver opens and one the sender keeps, so a feeling can travel back between two people who never signed up for anything.

Every stage gets a ground of its own — pink to arrive, paper for the wish, blue for a memory, coral for a voice, yellow to ask for something back. The page you just scrolled ran the same arc. It's your turn.

Wrap one for someone

fromdearly.com · free · no account for either of you