2026-01-08 Text first for fedi ============================== My usual web client for fedi is @phanpy@hachyderm.io and I wonder if there's a way to add the following feature using tamper script or grease monkey: Replace every image attachment with the clickable alt text. If there is no alt text, no problem, just drop it. Naturally, I'd like the regular Phanpy goodies, too. But these are strictly nice to have. If the alt text is too long, show the "Read more" button. If the image is marked NSFW then hide the alt text behind a "Show content" button. The idea is to provide a text-first user-interface. I still want to see the avatars of people, and I still want to reveal the images, but I want to read the alt-text first to make sure this is something I want to look at. I also suspect that people with the same preference are a tiny minority, so it probably doesn't make sense to add it to Phanpy itself. But it would be nice to be able to a text-first user-interface. @jay@cathode.church uses a userScript to bring the title attribute back in the Masto 4.4+ web UI (source). Perhaps it can be adapted for a first iteration? Yes indeed! So, a Tampermonkey script. I also want the text columns to be a bit wider, mostly so the boost carousel shows more than just one boost. // ==UserScript== // @name Text Phanpy // @namespace http://phanpy.social/ // @version 2026-01-09 // @description Replace all images with their alt text // @author Alex Schroeder // @match https://phanpy.social/ // @icon https://phanpy.social/favicon.ico // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; GM_addStyle(':root { --main-width: 50em !important; }'); new MutationObserver(mutationList => { mutationList.forEach(mutation => { // watch for new 'img' and 'video' elements Array.from(mutation.addedNodes) .filter(el => el.nodeName != '#text') .flatMap(el => [ (el.tagName == 'IMG' || el.tagName == 'VIDEO') ? [ el ] : [], Array.from(el.getElementsByTagName('IMG')), Array.from(el.getElementsByTagName('VIDEO')) ]) .flat() .filter(el => el.parentElement.classList.contains("media")) .forEach(el => { el.setAttribute("style", "display: none") el.parentElement.setAttribute("style", "background: white") if (el.hasAttribute("alt") && el.getAttribute("alt") != "") { const d = document.createElement("div") d.setAttribute("style", "font-size: smaller; padding: 0.5rem") d.innerHTML = el.getAttribute("alt") el.parentElement.insertBefore(d, el) } else if (el.parentElement.nextElementSibling != null && el.parentElement.nextElementSibling.tagName == "FIGCAPTION") { const cap = el.parentElement.nextElementSibling const d = document.createElement("div") d.setAttribute("style", "font-size: smaller; padding: 0.5rem") d.innerHTML = cap.innerHTML el.parentElement.insertBefore(d, el) cap.remove() } else { var del = el if (del.parentElement.childElementCount == 1) { del = del.parentElement // media } if (del.parentElement.childElementCount == 1) { del = del.parentElement // media-container } del.remove() } }); }); }).observe(document.body, { childList: true, subtree: true }); })(); A screenshot of a post of mine where I posted two pictures; both are replaced by their alt text. #Fediverse #Phanpy