Anonymous social network · full product with AI
ECOA

Problem
People want to vent and be heard without showing their face, and traditional networks punish vulnerability.
Solution
Text-only network where each person is a number: anonymity guaranteed by the database architecture (not even the API can link account to post), 2-stage AI moderation, e-mail-free account recovery and end-to-end privacy compliance.
How it was built
The production stack is Next.js 16 (App Router, Turbopack) on Supabase Postgres in the sa-east-1 region, chosen for in-Brazil data residency with LGPD in mind. It's deliberately simpler than the target architecture documented in the project's blueprint (NestJS, Redis, NATS JetStream, Meilisearch, React Native/Expo): the MVP swapped all of that for a faster validation shortcut. Since the product is text-only with no social graph (no following, no followers), the most expensive problem in a social network, timeline fan-out, simply doesn't exist. Each post weighs a few KB and the feed query is a Postgres view with keyset pagination, with no queue or dedicated cache needed.
Anonymity here isn't 'no signup', it's a database-level guarantee. Each person enters via Supabase's signInAnonymously() and gets a public_number generated by a Postgres function (random draw with a uniqueness check), shown as "User #48291". The internal UUID (profiles.id) never leaves the database: a revoke select strips the default table privilege on posts, comments and profiles from the authenticated role, then a grant select restores access only to an explicit column list, excluding user_id. In practice, even a malicious client-side query can't join account to content, because the privilege to do so doesn't exist at the database-role level. It isn't an application rule that could be worked around. There's no browsable profile page either: tapping a "#48291" opens no history, a deliberate anti-stalking design choice.
Moderation runs in two stages, both in lib/moderation.ts. Stage 0 is deterministic and instant: Unicode NFKC normalization (against homoglyph bypass tricks), link blocking, a PII regex (email and phone) that only flags, and a crisis-signal regex ("I want to die", "hurt myself") that never blocks publishing, because it only exists to trigger support. Stage 2 is optional: a call to Claude Haiku with structured JSON output, whose system prompt explicitly instructs "when in doubt, don't flag", because a false positive silencing someone in distress is treated as worse than a false negative. The design is fail-open by principle: if the API goes down or hits its 8-second timeout, content passes through. Today, with no API budget provisioned in production, only stage 0 is actually active. Community reports auto-remove content via a Postgres trigger once 3 distinct reporters flag the same item, with no dedicated moderation queue app. The raw Supabase dashboard fills that role in the MVP.
A few decisions make the kind of product this is clear. There will never be private messaging, treated in the project as "a harassment and grooming vector". There will never be free-form hashtags: just a curated taxonomy of 13 topics, specifically to prevent coordinated campaigns. And the feed is chronological, with no infinite scroll, with a "breathing milestone" every ~50 posts, a structural anti-addiction decision rather than just a UX nicety. Email-free account recovery uses a 6-word passphrase (a 240-word list, ~47 bits of entropy) hashed with bcrypt, reassigned via an RPC with ON UPDATE CASCADE propagating through posts, comments and reactions. The current limits are documented honestly: the recovery-attempt counter gets wiped out by the same transaction rollback that produces the auth error. It's a known, accepted gap, since the passphrase's entropy and bcrypt's cost already cover most of the risk. A 19-scenario e2e suite runs against the real database, including a check that column-level privacy actually prevents user_id from leaking.
Anonymity via column privilege
revoke select plus an explicit column-list grant: not even the API can link account to post.
2-stage moderation, fail-open
Always-on deterministic regex plus optional Claude Haiku. AI downtime never blocks a post from publishing.
Email-free recovery
A 6-word bcrypt-hashed passphrase reassigns the account via RPC, with zero personal data required.
Anti-manipulation by design
No free hashtags, no DMs and 13 curated topics: a structure built against coordinated campaigns.
More screens
Stack
- Next.js
- TypeScript
- Supabase
- PostgreSQL
- Claude API


