Ein eigener Mastodon-Reply-Button

Mastodon ist unter anderem deshalb so toll, weil es dezentral ist. Allerdings kann genau das auch zu Frust führen; schon mal versucht, auf einen Mastodon-Post zu verlinken, damit jemand darauf reagieren kann?

Die Person wird mit hoher Wahrscheinlichkeit auf einer fremden Instanz landen und muss von dort erst einmal zur eigenen Instanz finden, um dort dann auf den Post reagieren zu können. Auch ein einfacher "Folgen"-Button wird so schnell zur Hürde.

Das haben auch andere erkannt und arbeiten an Lösungen, wie dem "Universal Follow Button", der vielleicht einmal kommen mag. Und während ich diesen Artikel fast fertig habe, erscheint der neue Share-Button von Mastodon, dazu später mehr.

Auf meiner Seite habe ich deshalb versucht, Dine zu vereinfachen. Leserinnen geben ihre Mastodon-Instanz ein und werden dann direkt zum passenden Post geleitet.

Zu (fast) jedem meiner Beiträge auf meiner Seite gibt es auch einen Mastodon-Post. Reaktionen auf diesen Post werden synchronisiert und unter dem Beitrag auf meiner Seite angezeigt, darum kümmert sich der [[/kirby/indieconnector|IndieConnector]].

Ich kann also automatisch auf diesen Post verweisen, würde dann aber auf das oben beschriebene Problem stoßen. User würden auf meine Instanz gelangen, nicht auf ihre, und könnten nicht direkt reagieren – suboptimal.

Statt den Post direkt zu verlinken, müssen meine Leserinnen erst einmal ihre Instanz eintragen und können sich entscheiden, ob diese Instanz (im Browser) gespeichert werden soll:

Das Formular ist schlicht aufgebaut:

<form action="/reply/mastodon" method="post">
    <input type="url" value="" name="instance" id="instance" placeholder="https://mastodon.instance" required>
    <input type="hidden" name="target" value="<?= $mastodonUrl ?>">
    <button type="submit" class="button-primary">Ok</button>

    <input type="checkbox" name="rememberInstance" id="rememberInstance" value="true">
    <label for="rememberInstance" class="remember">
        Remember
    </label>
</form>

Im Wesentlichen enthält das Formular zwei Daten:

  1. Die Instanz des Users
  2. Meine jeweilige Mastodon-Post-URL

Ein Klick auf den Button leitet dann zur Instanz weiter und zeigt dort meinen Post an, auf den dann direkt reagiert werden kann.

Ich löse das über eine [[/kirby|Kirby]]-Route, die Umsetzung funktioniert aber genauso gut mit einer einfachen PHP-Datei, die irgendwo aufrufbar ist.

So sieht die Route aus:

[
    'pattern' => 'reply/mastodon',
    'method' => 'POST',
    'action' => function () {
        $request = kirby()->request();
        $data = $request->data();

        if (!isset($data) || empty($data)) {
            return new Response('No POST data found', 'text/plain', 400); // Not Acceptable
        }

        $instanceUrl = Url::stripPath($data['mastodonInstance']);
        $url = $instanceUrl . '/authorize_interaction?uri=' . $data['target'];

        if ($data['rememberInstance'] == true) {
            // set cookie
            Cookie::set('mastodon_instance', $instanceUrl, [
                'lifetime' => time() + 60 * 60 * 24 * 365,
                'path' => '/',
                'httpOnly' => false,
            ]);
        }

        header::redirect($url);
    },
],

Der Code sähe ohne Kirby ähnlich aus (gekürzt):

$data = $_POST;

$parsedUrl = parse_url($data['mastodonInstance']);
$instanceUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'];

$url = $instanceUrl . '/authorize_interaction?uri=' . $data['target'];

if (!empty($data['rememberInstance'])) {
    setcookie(
        'mastodon_instance',
        $instanceUrl,
        [
            'expires'  => time() + 60 * 60 * 24 * 365,
            'path'     => '/',
            'httponly' => false,
        ]
    );
}

header('Location: ' . $url);

Hier ist es zudem sinnvoll, zu prüfen, ob die Daten leer sind und ob es sich um einen POST-Request handelt. Da viele Leserinnen hier vermutlich ein CMS nutzen werden, habe ich mich entschlossen, diese Details wegzulassen, weil sie wahrscheinlich sowieso vom System gehandhabt werden.

Die eigentliche Magie ist in einer Zeile versteckt und ziemlich simpel:

$url = $instanceUrl . '/authorize_interaction?uri=' . $data['target'];

Wir bauen aus den gegebenen Informationen eine neue URL zusammen, beginnend mit der eingegebenen Instanz (ohne eventuellen Pfad hinten dran) dem Pfad /authorize_interaction und dem uri-Parameter, der die volle URL zu unserem Mastodon-Post enthält.

Der Endpunkt /authorize_interaction macht genau das, was man vermuten könnte: Er erlaubt die Interaktion mit, in diesem Fall, einem Post. Durchlaufen wir den Flow, sind wir also bereits auf der eigenen Instanz und haben dort dann über den Endpunkt die Möglichkeit, auf den Post zu reagieren, egal auf welcher Instanz sich dieser befindet.

Das geht übrigens auch mit User-Profilen und ist praktisch für einen "Follow-Button", wie ihn der Dienst oben anbieten will.

Unsere Leserinnen müssen also im besten Fall nur einmal ihre Instanz hinterlegen und können dann ohne weitere Umstände mit unseren Mastodon-Inhalten interagieren, denn sie gelangen immer auf ihre eigene Instanz und sehen dort den jeweiligen Post oder das Profil. Wir haben ihnen das umständliche Suchen und Copy & Paste abgenommen.

Nun gibt es seit dem 2. März einen offiziellen Share-Button von Mastodon, den man sich einfach zusammenklicken kann:

https://blog.joinmastodon.org/2026/03/a-new-share-button/

Und obwohl ich die Idee gut finde, habe ich zwei Probleme damit:

  1. Er erzeugt einen neuen Beitrag
  2. Er streicht die Dezentralität

In meinem speziellen Use-Case ist es so, dass der IndieConnector nur Reaktionen von Posts abholt, die im Plugin hinterlegt sind. Es besteht eine 1:1-Beziehung zwischen Blogbeitrag und Mastodon-Post. Der Share-Button erzeugt aber immer neue Beiträge. Das ist zumindest nicht das, was ich will.
Er ist aber sicherlich für all diejenigen passend, die gerne möchten, dass Leserinnen schnell und einfach Zitate oder URLs als eigene Posts teilen können. Aber!

Alles läuft über share.joinmastodon.org. Dort müssen die User dann ihre Instanz eingeben und werden dann auf diese Instanz umgeleitet, um dort unter dem share-Endpunkt einen neuen Post zu erstellen.

Wir können uns denken, was im Hintergrund passiert: vermutlich genau das, was wir im oben beschriebenen PHP-Code machen.

Das ist an sich vollkommen okay, wäre da nicht eine Sache: Es gibt eine zentrale Schnittstelle. Jeder Share-Button oder -Link läuft nun über share.joinmastodon.org. Man möge mich pingelig nennen, aber genau das wollten wir ja mit Mastodon gerne vermeiden.

Nun ist nicht jeder Entwickler oder möchte sich irgendeinen, irgendwas tuenden PHP-Code vibe coden, dafür ist das zumindest ein guter Anfang. Wer aber kann, sollte vielleicht eher den oben beschriebenen Weg gehen. Dieser hat den Charme, dass unsere eigene Webseite die "zentrale" Schnittstelle ist, und auf der befindet sich die Leserin sowieso schon. Außerdem ist der /authorize_interaction Endpunkt kein reiner Mastodon-Endpunkt, sondern Teil von ActivityPub und kann also auch außerhalb von Mastodon benutzt werden.

Ich bin gespannt, wie der Follow-Button umgesetzt werden wird. Ihr habt jetzt jedenfalls ein paar einfache Zeilen PHP-Code und einen hilfreichen Endpunkt zur Hand, mit denen ihr all das schon jetzt ohne externe Services einbauen könnt. Viel Spaß!

Bei Mastodon reagieren

Trage Deine Mastodon-Instanz ein. Du wirst dann zum Post weitergeleitet und kannst dort reagieren.

Du kannst diesen Beitrag von Deinem Blog aus kommentieren.

Dieser Beitrag reagiert auf Webmentions. Du kannst ihn von Deiner Webseite aus verlinken und eine Webmention verschicken. Dein Beitrag taucht dann hier in den Kommentaren auf. Deine Seite unterstützt keine Webmentions? Trage den Link zu Deinem Post hier ein:

Kommentar schreiben
Mit dem Absenden stimmst du zu, dass die eingegebenen Daten gespeichert und in Form eines Kommentars dargestellt werden dürfen.

Reaktionen