Bloom
Alima's community ran on a registration form, a payment transfer and a Telegram invite. Bloom is the place it moved into — publications and announcements, courses with enrolment, events with sign-up, a diary, direct messages, and the admin console that decides who gets in.
A community of Russian-speaking women was being run out of a registration form, a bank transfer and a Telegram invite. That holds while the group is small and one person is willing to keep the whole thing in her head: who has paid, who is an expert, who is on which course, when the next meeting is.
It stops holding once the experts start publishing, courses run on their own schedules, and a member wants to find the meeting she signed up for without scrolling back through a chat. The community needed a place of its own — and a private one, since what members write is for members and for nobody else.
Build for the phone and nothing else. The founder's brief was that members would be on their phones, so the product is a 390 pixel column and every layout decision follows from that rather than being adapted down to it.
Put the rules in the database. Who may read a publication, who may see a request to join a course, whose message reaches whose phone: each of those is answered by row-level security in Postgres, not by a condition in the interface. An interface check is one forgotten branch away from leaking. A policy applies to every query that will ever be written, including the ones written months later.
Keep the product in the founder's own Russian. The copy she controls lives in one file, so changing what members read does not mean touching a component.
Next.js on the App Router with Supabase behind it. Thirty screens: the feed of publications and announcements, courses with enrolment requests and a diary inside each one, events with sign-up, direct and group messaging, member and expert directories, a notification bell, and an admin console for accounts, roles and access.
The schema is twenty-five tables, row-level security enabled on every one, with 137 policies between them. Migrations are applied from CI through Supabase's management API, so each schema change carries a commit, an author and a run log. A SQL suite asserts what the rules are meant to stop, which means a policy that quietly opens up fails a test rather than a member.
Web push is built on the specifications directly — encrypted to the device, signed as the app — with a service worker and an offline page. Two things reach a phone while the app is closed, and only two: a new message, and a new line on the bell. A phone that buzzes for everything is a phone with notifications switched off by Friday.
Membership is by invitation: an admin lets an email in after payment, and only then can an account be created. The landing page went up in two days and the members' platform over the five days after it — 161 commits across 68 merged pull requests, by one engineer with AI coding tools in the loop.