Sitting in the train home, it’s nearly 23:00 and I’m tired. My wife is sitting next to me and we are both staring into our phones.
I was following a conversation of @raelzero, @neauoire, @cblgh, @grey, @cancel, @aw, and @inscript about long form writing, the benefit of mailing lists and forums and all that, I’m thinking about wikis, as I often do. Like: write long texts, like on a blog; reply to each other, like mails, with threads grouped by topics, like forums, and editable, like a wiki.
I guess forum posts are usually editable. So perhaps it’s just a forum after all. And I’m thinking of Gemini, and how I generated names for visitors based on their client certificates, and my capsule hosting. But of course it would all work using HTML as well. It’s just that these days I like to design Gemini first and add HTML later…
Perhaps I could add an in-reply-to field for threading, creation and modification dates for sorting, and tags for a forum-like overview to a simple posting engine like Transjovian Capsules.
provide every visitor with a writeable capsule – App::Phoebe::Capsules
It might work. But who would use it? Nobody would, that’s for sure. So I think I’ll spend my time on something else. 😅
I’m reminded of a very old idea by Lion Kimbro that Mattis Manzel called One Big Soup, and the Thread Server in particular. Those never went anywhere, I think.
We need a server that can tell us, given one URL, what the threads are it belongs to. Every thread has a name, and a tree of nodes. Every node has an URL and another name. Since URLs are unique, we don’t need yet another identifier. – ThreadServer
Rather, we believe in networking WikiEngines with all SocialSoftware so that wiki, with its inherent advantages for managing semi-stable collective text, replaces less effective content management paradigms. – OneBigSoup
Currently, people using Gemini might depend on a search engine and a special UI where the search engine tries to identify threads in articles by looking at the link structure. The benefit is that it requires zero attention by authors. The drawback is that it requires a search engine to do – a big centralising force, for sure!
Maybe I should just write a thread server. Here’s how I imagine it would work:
You write something and post it. It has a URL.
Visit the thread-server of your choice and click “new thread”. Paste your URL. Perhaps the software you are using already does it for you. Perhaps the thread server scans your gemlog when you notify it, like Antenna does. You get back a thread URL. Go back to your post and add the thread URL.
Somebody else sees your post and replies to it. The reply also has a URL, of course.
They visit the same thread-server, looking at the thread URL. There, they pick the exact post they were replying to and click “new reply”. They paste their URL. They get back a reply URL.
They go back to their post and add the reply URL.
Readers of either post can now click on the additional link and see all the related posts in a thread view without the need of a search engine scanning the entire space non-stop and guessing the thread structure. It’s all there, built by humans, on a human scale.
It would be nice if thread servers were integrated into post writing tools, of course.
Anti-spam and anti-harassment features… Hm. We could have accounts. Invitation only. Then everybody can remove the URLs to their own posts in the thread (without removing the node itself so that threading still works), and everybody can change the text of their posts since that is not stored on the thread server. We’d have administrators to kick out members if communication breaks down. Yikes.
Or we could design it with smallness in mind. If only me and five friends are going to use a thread-server, we can just have one token that we share with each other, a password without a username. Anybody who knows it is an admin and can delete any URL and any thread. Encourage the next five people to run their own thread server. I like this better!
The thread server is a centralising instance, unfortunately. A thread and all its replies are registered on the same thread server. Your next thread, however, and all its replies, can be registered on a different thread server. Five friends can put up a thread server for themselves. Somebody can put up a thread server for thirty people.
If we want more people to join, perhaps we need two tokens. The admin token I mentioned above is what allows five friends to administer the site. A contributor token would allow you to add your new posts and replies to the thread server. It can be passed along like a secret among people in the know, or it can be posted somewhere hard to find, or on the front page, depending on your level of trust. When spammers and vandals come, change it, and rethink how you publish it. Experiment.
The benefit of a thread server is that there’d be an overview of the entire thread: who participated, how old the replies are, and we could try different ways of visualising it. And it doesn’t need search engines, nor guesswork, nor algorithms. It’d be human scale.
The problem is that extra step of adding the URLs of our posts to the thread server. Chances are that we won’t do it unless it can be automated.
I mean, I will surely be able to do the right thing for Emacs. But what about everybody else? 😀
At the same time, the external thread server allows us to get something up and running without requiring all clients to support it. We can provide simple and specific tools that register threading for us.
And we can still think about the UI. Perhaps we can make it easier to use?
You write something and post it. It has a URL.
Visit the thread-server of your choice and click “add post”. Paste your URL. It scans the post and it lists all the links in your post, asking you if your post is a reply to any of them. The list shows URL, text, and an indicator or counter if the URL is already in the database, making it more likely candidate. You click on the post that you consider to be your post’s ancestor, if any. There can be only one (at least for now). If your post is not a reply click on the “new thread” link. You get back a thread URL.
Go back to your post and add the thread URL.
Somebody else sees your post and replies to it. The reply also has a URL, of course.
They visit the same thread-server and click “add post”. They paste their URL. It scans the post and it lists all the links in their post, asking them if their post is a reply to any of them. Your link is among the list. They click on your post. They get back a reply URL.
They go back to their post and add the reply URL.
Slightly less discipline is required. But still, it’s not zero.
I’d still love that thread view, though! It can be simple, like in Mastodon: show all the ancestors, sorted by creation time, then the post you’re looking at, then all the descendants in depth-first & creating-time order. I find it more or less intuitive. An old school threading view like in Usenet clients or web forums would also work, of course. Or some SVG visualisation with clickable links? Who knows! We can think about those once the thread server itself is up.
And we could have feeds! A feed for every thread. A feed for all the follow-ups to your own posts, or just the immediate replies. A feed for all the threads with specific tags.
Did I talk about tags? We should definitely add tags.
#Gemini #Social Media
(Please contact me if you want to remove your comment.)
⁂
If I’m serious about there being a lot of thread servers out there, we should agree on an API. The goal is two independent implementations and running code!
Here goes.
A thread consists of linked nodes. Each node has an optional link to a parent node. A node without a parent link starts the thread. It is called the thread node. A node with a parent link is called a reply node.
When talking about a particular node we call it the context node.
All the nodes reachable by following parent links are the ancestors of a context node.
All the nodes sharing a common ancestor belong to the same thread.
The descendants of a context node are all the nodes that have the context node in their ancestors.
Each node has two attributes: URL, creation date.
The thread node has an extra title attribute.
There is no concept of node ownership. Anybody can create a node linking somewhere. The author of a linked resource doesn’t necessarily need to know about it.
The thread title is determined by the author of the linked resource: the thread server uses the title attribute, the first heading on the page, the beginning of the text, or the URL.
The thread server should present URLs in some sort of human readable form. The simplest solution is to just print the URL. The next best solution would be to decode the URLs for better readability: render international domain names and decode percent-encoded paths.
The thread server may request titles for each node. If it does, the results must be cached.
Each thread server should have a notion of thread activity. For example, if a thread received a reply in the last thirty days, it is called “active”. Inactive threads are called “archived”.
Since we assume a thread server for a small community, it is unnecessary to allow multiple, active threads for the same URL.
The UI for the operations is not specified.
Every thread server has a base URL; no query and no fragment to the URL. This shows some basic instructions for humans to read.
gemini://transjovian.org:1965/threads https://transjovian.org:1965/threads
“/list” shows all the active thread. The presentation is left to the thread server.
Inactive threads should no longer be shown so that they cannot be resurrected. This used to be called “thread necromancy“.
Whether to show just thread nodes or whether to include reply nodes is left to the thread server.
“/thread/” shows the threads the URL belongs to. The URL may belong to a reply node or to a thread node. The presentation is left to the thread server.
The thread server may present the thread using a threaded view, as was popular with Usenet clients or forums, allowing readers to treat each node as a folder, collapsing and expanding them as desired.
A └┬B │├─F │└─G ├C ├D │├─H ││ ├─J ││ └─K │└─I └E
The server may present the thread using some graphical representation as ASCII art or a SVG document.
A┬B┬─F ├C└─G ├D┬─H┬─J └E└─I└─K
The server may present just a subset of the thread based on the context node provided. Let’s take the context view of the Mastodon web UI as an example. It lists all the ancestors in order of creation date, then the context node, then all the descendants, depth-first, with siblings sorted by creation date.
Using the thread example from above and assuming the context node is D, the thread server would list the ancestors: A. Then the context node: D. Then the descendants in depth first order: H J K I. All the other branches are not shown.
To get a complete view, you would need to pick the thread node as your context node. If you did that, then the thread server would list the ancestors first: none. Then the context node: A. Then the descendants in depth first order: B F G C D H J K I E.
“/embedded/” shows the threads the URL belongs to. The presentation is left to the thread server, but it must be as minimal as possible: no headers, footers, if at all possible. The intended purpose is for people to include this output in their own sites, e.g. at the end of their own posts.
“/add/;token=” creates a new thread node with the given URL, if no active node for the URL exists. The title is determined by the thread server.
If the server doesn’t check the token, it is optional: “/add/”. In this case the server should check the client certificate.
“POST /add” submits the form with the parameters “url” and “token”. This creates a new thread node with the given URL, if no active node for the URL exists.
The token is mandatory.
The title is determined by the thread server.
“/reply//;token=” creates a new reply node with the given URL for the given parent URL.
If the server doesn’t check the token, it is optional: “/reply//”. In this case the server should check the client certificate.
“POST /reply” submits parameters “url“, “parent“, and “token”. This creates a new thread node with the given URL, if no active node for the URL exists.
The token is mandatory.
The title is determined by the thread server.
“/delete/;token=” deletes the URL and title indicated from all the known nodes for that URL. If there are no replies to the URL, the node is deleted.
If the server doesn’t check the token, it is optional: “/delete/”. In this case the server should check the client certificate.
“POST /delete” submits parameters “url“ and “token”. This deletes the URL and title indicated from all the known nodes for that URL. If there are no replies to the URL, the node is deleted.
The token is mandatory.
– Alex 2021-12-19 13:35 UTC
---
great reading. must think some more...
– ariane 2021-12-27 02:13 UTC
---
If you implement something, I will also implement something! Two independent implementations is my goal! 😀
– Alex 2021-12-28 15:07 UTC