I like forums. Debates, questions, answers, opinions, etc. That feeling of an asynchronous community, where answers are thought through and content lasts, is what makes the internet an interesting place. That is why I like reading them and taking part in them. But I had never designed or built one. In my spare time I started sketching one, and I ended up building my humble headless, federated forum, with simple, modern technologies and open standards.And I learned a lot along the way. A forum looks simple, but it hides the classic problems of any server. Who can do what? How do you tell a moderator from a regular user? What happens when you have to ban someone? How do you stop someone from stealing an account? Roles, permissions, bans and security. I had to solve them one by one, and you don't learn that by reading.Let me tell you how I made Tyrtulia.A forum with no interfaceThe server only offers a solid, documented API. It is REST with hypermedia: the client only knows one route, GET /, and discovers everything else by following links. Underneath there are some very boring standards:RFC 9110: HTTP semantics, with ETag and If-Match so edits don't overwrite each other.RFC 9457: errors.RFC 7396: partial updates with PATCH.RFC 6570: URL templates.RFC 4287: Atom feeds.RFC 9562: UUIDv7 identifiers.JSON Schema: validation.Server-Sent Events: real-time events.There is no web interface, no forms, no advanced authentication systems, no file handling (images, attachments, etc.), and nothing that isn't strictly needed to read and write messages.That is why it is so light. It uses between 60 and 70 MB of RAM and about 50 MB of disk. It only needs Python and SQLite to run.An API that discovers itselfHow does a client know what it can do? The server tells it with links. Look at the same request, GET /, made by a guest (simplified):{ "name": "Forum of example.org", "_links": { "self": {"href": "/", "method": "GET"}, "latest": {"href": "/threads", "method": "GET"}, "search": {"href": "/search{?q,author,in}", "method": "GET", "templated": true}, "login": {"href": "/sessions", "method": "POST", "schema": "/schemas/session"} }}And now by alice, logged in:{ "name": "Forum of example.org", "_links": { "self": {"href": "/", "method": "GET"}, "latest": {"href": "/threads", "method": "GET"}, "search": {"href": "/search{?q,author,in}", "method": "GET", "templated": true}, "createThread": {"href": "/threads", "method": "POST", "schema": "/schemas/thread"}, "notifications": {"href": "/notifications", "method": "GET"}, "events": {"href": "/events", "method": "GET", "type": "text/event-stream"} }}If I change a route tomorrow, no client breaks, because none of them knew it in advance. They just follow the links the server gives them.Why not use one that already exists?I know there are very complete free software forums:Discourse: the most popular one today.Flarum: PHP with MySQL.NodeBB: Node.js, with MongoDB, Redis or PostgreSQL. It stands out for real time with WebSockets.Or the good old classic: phpBB.They are all fantastic, but they are designed to be used from a web browser. They also have an ambitious scope. That is ideal for large communities, but too much for a small, light forum.That said, Tyrtulia doesn't give up on the browser: it can be indexed by search engines and anyone can read it on the web.No passwordsNo OAuth, no OpenID, no sign-up forms. There are two ways to authenticate:Your Unix user: the client talks to the forum through a Unix socket. The operating system tells the forum which user is on the other side. No sign-up, no login. Your user is your account.SSH key: the client connects over HTTP and the forum sends it a challenge. The client signs it with your private SSH key and the forum verifies it with your public key.There is no registration over HTTP. If you have a Unix user on the server, you already have an account: it is created the first time you connect through the socket. From there you can add your SSH keys to log in from outside. If you don't have a user on the machine, the administrator creates an account for you with your public key from the command line. On a tilde, having a Unix user is already the invitation.Easy to use, secure, and no passwords to steal.What changes compared to BBJThe idea isn't mine. I was inspired by BBJ, a bulletin board for the terminal built for small communities or clubs (tildes, pubnixes, club servers, etc.). I took its spirit and brought it to my own ground. Still, there are important differences.First, the foundations.BBJTyrtuliaAPI styleRPC: everything is POST /api/REST with hypermedia (HAL): only GET / is knownPermissionsThe client asks (is_admin, edit_query)Links that appear or disappearAuthenticationUnsalted SHA-256 hash of the password on every requestNo passwords: Unix socket or SSH-signed challengeErrors6 custom numeric codesRFC 9457 with a catalog of typesPaginationEverything at onceCursor basedConcurrencyThe last edit wins, silentlyETag and If-MatchText formatCustom language ([bold: ...], [red: ...])Standard MarkdownValidationA db_validate endpointJSON Schema linked from each formConfigurationconfig.jsonTOMLThen, the features I missed.BBJTyrtuliaReply to a specific post>>N quotes in the textLinked replies, with a tree viewMentionsNoYesNotificationsNo (pending since 2017)Inbox with replies, mentions and alertsReal timeNo, you have to pollServer-Sent Events, with resumeEdit historyNo, editing overwritesFull, with diffs and revertDeletionDeletes the rowTombstone: numbering is preservedSearchEach client searches what it has downloadedServer-side full text, accent and case insensitiveFeedsNoAtom for the forum and each threadModerationAdmin or notRoles, hidden posts, reports and a public logRate limitingNoPer user and per IPWhat they share is a small server built on SQLite and several text clients against a documented API.ClientsA headless forum needs clients, no way around it.Tyrtulia TUITyrtulia TUI is the terminal client, built with Textual.tyrtulia.elIf you know me a little, you know this package was a must: tyrtulia.el.Tyrtulia WebTyrtulia Web is more a mirror of the content than a client. Its goal is to let search engines index the forum and let anyone read it from a browser.It has an unstyled theme and another one that mimics my website.FederationYou can connect to one forum or set up several. Federation happens in the clients: servers don't talk to each other or copy messages between them. Each forum is independent, with its own users, rules and moderators.Instead of splitting them into tabs or accounts, the clients mix the threads of all of them into a single list.Of course, you can only write in the forums where you have an account. In the rest you can only read.I think it's a pretty cool feature, because it keeps the API code much simpler and lets you explore other forums at zero cost.Try itIt has been fun to design and build. Of course there are more complete forums, more powerful federation systems, and even decentralized systems that leave Tyrtulia in the dust (Aether, Nostr...). But its niche is very specific: a light, closed-access, federated, indexable, secure forum with text clients. For everything else, there are better things out there.If you feel like trying it, the installation guide is in the Tyrtulia repository.I look forward to your feedback.Help me keep writing Every coffee gives me a push toward the next article. Sure, it's on me!Send an email to comment+article-b5c8c6aa@andros.dev to leave a comment. The subject will be ignored.