Insights

UnsentLetters: A Home for Letters Nobody Sends (What Building an Anonymous Platform Actually Teaches You)

· Insights

UnsentLetters collects anonymous letters people never sent: no accounts, seven tags, a public feed. The build taught hard lessons about anonymity and moderation.

UnsentLetters: A Home for Letters Nobody Sends (What Building an Anonymous Platform Actually Teaches You)

Last updated: November 13, 2026 · 6-minute read

One thousand characters, no name, no account, no send button that reaches anyone — that is the entire product of UnsentLetters, the anonymous platform I built for the letters people write and never send. It looks like the simplest app in my portfolio. It taught me the hardest lessons of any of them, because a platform whose only feature is other people's unguarded honesty is a moderation problem wearing a diary's clothes.

Everyone carries one. The resignation that stayed a draft, the apology typed at 2 a.m. and deleted by morning, the letter to someone who is gone. Writing it helps; sending it would not — or cannot. Existing outlets for that writing are either private journals, which give the words nowhere to land, or social feeds, which demand a name and an audience's judgment. UnsentLetters was built for the gap between those two: witnessed, but anonymous.

The Shape of the Thing

The form asks for almost nothing. A letter is capped at 1,000 characters — long enough for the thing itself, short enough that it has to be the thing. An optional tag sorts the feeling into one of seven: Love, Regret, Goodbye, Gratitude, Confession, Rage, Closure. Then it goes to the public feed, newest first, where letters can be searched, filtered by tag, and answered with comments, likes, and emoji reactions.

The stack is ordinary on purpose: React, TypeScript, and Vite on the front, Supabase over PostgreSQL behind it, Tailwind for the styling, deployed on Vercel. The deployment from the original build still answers at its Vercel address today. Ordinary stack, deliberate choice — the interesting problems in this product were never going to be technical novelty, and boring infrastructure is what lets you spend your attention on the human failure modes instead.

Anonymity here is architectural, not a promise in a privacy policy. The letter form inserts a row with text and tag and nothing else — the code carries the comment "No userid — anonymous by default" at the insert, because there is no account system to attach an identity to in the first place. You cannot leak what you never collected.

What Anonymity Actually Does to People

Building the container teaches you what the contents will be. Three lessons arrived whether I wanted them or not.

People write truer with no name attached, and truer is heavier. The seven tags look like a sorting convenience until you read a feed full of Regret and Goodbye and realise you have built a room where strangers grieve in public, kindly, at scale. The emotional register of an anonymous feed sits far above anything a named platform produces, because the social cost of honesty has been removed from the writing and quietly transferred to whoever maintains the room.

Constraints are a kindness. The 1,000-character cap and the single optional tag do more editorial work than any guideline page could. A cap forces the letter to be a letter, not a manuscript. A tag lets a writer say "this is Rage" before a single word is read, which protects readers as much as it organises writers. Structure is how a small platform shows care without a staff.

Engagement features are easy to build and hard to deserve. Comments, likes, reactions, share snapshots — the repo has them all, and each one is a door. A comment thread under a grief letter is a support group or a target, depending on who walks in first. Shipping the button is an afternoon. Deserving it is the whole job.

The Part I Got Wrong, In the Schema

Here is the honest part, and it is in the code for anyone to check. The database schema anticipated abuse properly: there is an interaction-log table and a blockedips table — the bones of an IP-level blocking system for a platform with no accounts to ban. But the client-side hook that was meant to enforce interaction limits, useInteractionBlock, ships disabled. Its own comment says so: "Blocker is disabled to allow all actions", and every check returns false.

So the moderation story of UnsentLetters, stated accurately, is this: the design knew abuse would come, built the tables for it, and the enforcement layer sits switched off in the shipped code. An anonymous, unmoderated, public feed is not a neutral default — it is a debt. On a quiet platform the debt sleeps. The week the platform gets discovered by the wrong crowd, it comes due all at once, with interest, in public, under letters written by people at their most vulnerable. If I reopen this project, the blocker stops being a no-op before any new feature ships. That ordering is the lesson, and it generalises to every anonymous product anyone builds: moderation is not a phase two feature. It is load-bearing, or the building is not finished.

One more nuance the schema teaches. The interaction logs record IP addresses — standard anti-abuse practice, and in real tension with the word anonymous on the landing page. No names, no accounts, no user IDs is the truth. "No data exists anywhere" would not be, and the difference between those two sentences is exactly where anonymous platforms earn or lose trust.

TL;DR

  • UnsentLetters is an anonymous letters platform: 1,000-character letters, no accounts, an optional tag from seven feelings, a public feed with search and tag filters
  • Anonymity is architectural — the database insert carries no user identity because no account system exists; React, TypeScript, Supabase, and Vercel carry the rest
  • Building it teaches three things: anonymous writing runs emotionally hotter, constraints like the character cap are a form of care, and engagement features are easy to build and hard to deserve
  • The shipped moderation is unfinished — the schema has interaction logs and a blocked-IPs table, but the client enforcement hook is disabled in the code, and the post says so plainly
  • The repo has been quiet since May 2026; the lessons shipped even though the platform's growth did not

Where It Falls Short

Beyond the moderation gap, which gets its own section above because it deserves one:

  • The repo has been quiet since May 2026. Six months without a push, zero stars, no community mileage. This is a finished build and an unfinished product, and this post is a lessons document, not a growth story. Inventing momentum here would be exactly the kind of claim this site does not publish.
  • Anonymity cuts both ways for readers. No accounts means no blocking a cruel commenter by identity, no following a writer whose letters move you, no notification when someone answers your letter. Every one of those absences is the anonymity promise working as intended — and each one is also a real cost.
  • 1,000 characters excludes real letters. Some unsent letters are four pages. The cap is a deliberate editorial line, but a line excludes whatever falls past it, and some of what it excludes is the best writing the premise could attract.
  • A dormant feed is a sad room. Anonymous platforms live on fresh letters from strangers. Without an audience flywheel, the feed a new visitor meets may be old — and an old feed teaches the opposite lesson from the one the product exists to teach.

The Verdict

UnsentLetters is the project I point to when someone asks what building in public actually teaches. Not distribution, not growth — those lessons failed to arrive. It teaches that a product's real surface area is human behaviour, that your schema will confess your priorities years later, and that "we will add moderation later" is a sentence a platform's most vulnerable users end up paying for. The code is MIT-licensed; the lessons were not free, but you can have them for the price of reading.

The writing side of building in public is covered in 12 weeks of blogging as a builder, and the rest of the portfolio — finished, unfinished, and honestly labelled — lives on the projects page.

---

Not affiliated with Supabase or Vercel. Sources: UnsentLetters GitHub repository, including its README, letter form and feed components, interaction-block hook, and Supabase schema types.

ansaribilal.com — technology, tested in public.