On the way
A bigger platform.
What is here now - guides, accounts, profiles and a community you can write in - is the floor, not the plan. What is still being built: keeping the platform patched and its backups tested, reactions and comments, direct messages between people, images and files attached to posts, and a feed that learns what you actually came here for.
Why this page exists.
The site has grown past the guides it started as. You sign in with a username rather than an address, you keep a profile, and you can write, publish and delete posts in three languages. All of that is done, and so it is not on this page. What is on this page is the rest: the parts still being built, written down in the open while they are still uncertain. Three decisions have been taken and are kept visible below; three calls are still open.
Decisions still open
Three calls we have not made yet.
Supabase, for the whole backend.
Supabase covers the database and sign-in in one place, so we are not assembling and running two unrelated services. Because we host it ourselves, the data never leaves our own infrastructure, and no third-party bill grows as engagement grows. The trade is that backups, upgrades, uptime and patching are ours to handle rather than a provider's. Permissions are enforced in the database itself, through Row Level Security, so a rule like "only the author can edit their own post" cannot be bypassed by a client. Most of what Supabase also ships - file storage, Realtime, analytics - stays switched off until a feature needs it, rather than being run because it is there.
A storage bucket, for attachments.
Avatars are resized in the browser and stored as data on the profile row, which keeps an image host off the list of things that can be down. That works for one small picture per person and it cannot work for a post carrying several images, a PDF or a video. So a bucket is being switched on for attachments - the one place the no-host rule had to bend. It is a real trade, taken deliberately, and it is named here rather than quietly dropped. Avatars stay as they are: one small picture per person is not worth a host.
Direct messages are private, and reportable.
Messages between two people are private, and nobody here reads them by default. A site that quietly reads private conversations has broken the thing it was built for, and a promise made after the feature ships is worth much less than one made before. The counterweight is abuse: a participant can report a conversation, and a report hands that one thread to moderators and nothing else. Private does not mean unaccountable - it means accountable to the person you are talking to, and to the law, and to nobody else.
How much of this do we build ourselves?
A ready-made CMS gives us auth, uploads and an admin panel immediately, but it is opinionated. Hand-rolling everything takes longer and keeps full control.
Do posts need a moderation step?
Settled, for now: anyone with an account may publish, with no approval queue and no verified email - an address is optional here, so gating on one would be gating on something the platform does not require. What is genuinely open is what happens the first time a stranger reads the feed and it has something in it they should not see. The report button and the queue that goes with it are not built yet: without a report, there is nothing to moderate.
Which languages do posts come in?
Our readers write and read in Arabic, French and English. Posts in one language with no translation quietly lose most of the audience.
What it runs on
Supabase bundles the database and sign-in into one coherent stack, instead of bolting unrelated services together. Since we host it ourselves, running it, upgrading it, backing it up and keeping it patched land on us too: the saving is the assembly, the cost is the operations. Most of what Supabase also ships is deliberately switched off until it earns its place.
- Platform
- Supabase - Postgres and sign-in in one place, self-hosted on our own infrastructure
- Database
- Supabase Postgres with the pgvector extension, for semantic search
- Data access
- The Supabase client over PostgREST. Row level security decides what a query may return, so the application never has to
- Accounts
- Supabase Auth. A username and a password; an email address is not required, and GoTrue is given one built from the handle
- Media
- Avatars stay as data on the profile row - cropped and compressed to WebP in the browser, so there is no host for them. Post attachments cannot work that way, so Supabase Storage is being switched on for those, with size and type limits
- Live updates
- Not running yet. One subscription per signed-in reader, when reactions, comments and direct messages land
- Permissions
- Row Level Security, so the database enforces who may do what - including refusing to let anyone grant themselves a role
- Transactional email
- Deferred until the domain is live. The platform works without one, and asking for an address nobody reads is how you lose people
The roadmap
What is left, roughly in order. Everything already shipped has been taken off this list.
- 1Security updates
Security updates
Keeping the platform patched is work, not a state. Supabase runs in containers we host, so the images have to be rebuilt and the dependencies kept current on a schedule rather than once. What is being worked on now: automated dependency and image scanning, a documented patch cadence, and turning the nightly database backup into something that is actually restored and tested instead of hoped for. None of it adds a feature, and all of it is the price of running the backend ourselves.
- Automated dependency and container scanning
- A written patch cadence, and someone to follow it
- Nightly backups, and a restore that is tested
- Least-privilege review of every database grant
- 2Attachments
Attachments
Images and files on a post - a photo of a certificate, a scanned form, a course brochure. This is the first feature to need a real storage bucket: a post carrying several files cannot be squeezed onto a database row the way an avatar can, so Supabase Storage is switched on for it, with a ceiling on size and a short list of allowed types. Video is named separately below, because it is the one attachment this project is least sure it can carry.
- Upload images and files to a post
- A storage bucket, with size and type limits
- Delete your own files, and remove them with the post
- Video, later and only if the bandwidth cost earns it
- 3Reactions and comments
Reactions and comments
A small fixed set of reactions instead of a generic like, threaded one level deep, plus follows. The admin panel is already built and shows everyone and everything that has been written; what it cannot do yet is decide anything, because there is no report button and therefore no queue to work through.
- Meaningful reactions, not just a like
- Threaded comments, one level
- Follow authors and topics
- A report button, and the queue that goes with it
- 4Direct messages
Direct messages
Private conversation between two people, one to one to begin with. Private means private: nobody here reads a thread by default, and the promise is written down before the feature exists because that is the only honest time to make it. The counterweight is abuse - a participant can report a conversation, and a report hands that one thread to moderators and nothing else. A block, a mute and a way to leave a thread come with it, not after it.
- One-to-one threads, private by default
- Read receipts and typing, or neither - still open
- Report a conversation, handing over that thread only
- Block, mute and leave
- 5Preferences and the feed
Preferences and the feed
Ask once what someone cares about, understand what each post is about, and show it to the people most likely to want it.
- One-time preference questions
- Post embedding and tagging
- A user vector from their behaviour
- Ranked feed with diversity rules
- 6Notifications
Notifications
Beyond release notes: replies, follows, new posts on topics you chose, and messages, in the app and by weekly email.
- Replies and follows in-app
- Live updates over a single connection
- Weekly digest email
- Per-notification controls
How the feed decides
The interesting part, written plainly.
Ask once
On first sign-in we ask three to five questions about topics and what you are trying to figure out. Skippable, editable later, never asked again.
Understand the post
Author-picked topics first, because they carry the most signal. Then reading time, language and media. Then one embedding vector of the text. AI summaries and tagging are optional and off by default.
Learn from behaviour
Every reaction, save and comment adds that post's vector to a rolling average for that person, with old signals decaying. Dismissals and 'not interested' count, in the other direction.
Rank, then spread out
Score each candidate, then apply rules so no single author floods the feed and nothing appears twice.
Roughly
score = w1·topic match
+ w2·similarity to what you engage with
+ w3·recency
+ w4·author affinity
+ w5·engagement quality
− w6·already seenTwo rules that decide whether it is any good
- Engagement quality is not raw counts. Weight by unique people, decay over time, and cap what one author can contribute - otherwise one popular post wins every slot forever.
- Always show why. Every card can say why you are seeing it. On a site people make decisions from, unexplained ranking is a trust problem.
What could go wrong
Named up front, not discovered later.
Spam, since anyone can post
Verified email to publish, rate limits, optional AI flags, one-tap report
Feed quality collapses
Quality-weighted engagement, diversity caps, explicit not-interested feedback
The feed is poor until there is data
Start on topics alone, and be honest about it early on
Privacy and data protection
Consent before tracking, export and delete account, clear retention
One person becomes the whole moderation team
The admin panel is built, so there is a place to work. What is not built is the report queue and the tooling to decide with - and that is the part that has to arrive before the panel is a moderation team rather than a look-up table
Abuse in private messages, where nobody can see it
A participant can report a thread, which hands that thread and nothing else to moderators. Block, mute and leave exist from the first version. Private does not mean unaccountable
Self-hosted attachments make bandwidth and storage the cost that scales worst
Size and type ceilings on every upload, and video deliberately deferred. Storage is the one place the no-image-host rule bends, so it is watched rather than assumed
AI costs creep upward
Embeddings only, and optional AI tagging stays off by default. Both are metered per call, so the bill tracks engagement instead of being fixed up front.
Infrastructure costs are ours now, and they scale with traffic and storage
Self-hosting swaps a SaaS bill for Postgres CPU, memory and IOPS, object storage, bandwidth and backups. Cheaper at small scale, and it becomes the dominant cost if the feed gets busy.
We operate the backend ourselves, so an unattended major upgrade can take the whole platform down at once - accounts, reads and writes together.
A staging instance to rehearse upgrades on, and a restore path tested before every production change. With a managed service this is the vendor's problem; here it is ours.
This is built in the open
Every decision, bug fix and release is written down and committed. If you want to follow along, read the code, report something awkward you find, or pick up a piece of it - the repository is the honest version of this page.
Everything on this page is still being built. The pages you can visit now are the finished part; what is written above is the rest.