Madblog: A Markdown Folder That Federates Everywhere
A lightweight blogging engine based on text files, with native Fediverse and IndieWeb support
I started working on Madblog a few years ago.
I wanted a simple blogging platform that I could run from my own Markdown files. No intermediaries. No bloated UI. No JavaScript. No databases and migration scripts. No insecure plugins. Just a git folder, an Obsidian vault or a synchronized SyncThing directory, and the ability to create and modify content by simply writing text files, wherever I am.
Drop a Markdown file in the directory, and it's live. Edit it, and the changes propagate. Delete it, and it's gone.
It's been running my personal blog and the Platypush blog for a while now.
With the new release, #madblog now gets a new superpower: it supports federation, interactions and comments both through:
- Webmentions - already implemented some weeks ago, you can also check out the previous blog article
- ActivityPub
Webmentions allow your site to mention and be mentioned by other sites that also implement them - like any WordPress blog with the Webmention plugin, or link aggregators like Lemmy or HackerNews. Interactions with any of your pages will be visible under them.
#activitypub support allows Madblog to fully federate with Mastodon, Pleroma, Misskey, Friendica or any other #fediverse instance. It turns your blog into a federated handle that can be followed by anyone on the Fediverse. It gives you the ability to mention people on the Fediverse directly from your text files, and get replies to your articles directly from Mastodon, get your articles boosted, shared and quoted like any other Mastodon post.
Demos
These blogs are powered by Madblog:
- blog.fabiomanganiello.com β Fediverse handle: @fabio@manganiello.blog
- blog.platypush.tech β Fediverse handle: @blog@platypush.tech
You can follow them from Mastodon (or any other Fediverse client), reply to articles directly from your instance, boost them, or quote them. You can also interact via Webmentions: link to an article from your own site, and if your site supports Webmentions, the mention will show up as a response on the original post. These blogs also have a Guestbook β mention the blog's Fediverse handle or send a Webmention to the home page, and your message appears on a public guest registry.
How Does It Compare?
If you've looked into federated blogging before, you've likely come across a few options:
-
WriteFreely is probably the closest alternative β a minimalist, Go-based platform with ActivityPub support. It's well-designed, but it uses a database (SQLite or MySQL), has its own (very minimal) editor, and doesn't support Webmentions. Additionally, it lacks many features that are deal-breakers for me.
- No export of all the content to Markdown, nor ability to run my blog from my Nextcloud Notes folder or Obsidian vault.
- No support for LaTeX or Mermaid diagrams.
- No support for federated interactions - any interaction with your articles on the Fediverse is simply lost.
- The UI is minimalist and not necessarily bad, but not even sufficiently curated for something like a blog (narrow width, Serif fonts not optimized for legibility, the settings and admin panels are a mess...).
- No support for moderation / content blocking.
- No support for federated hashtags.
-
WordPress with ActivityPub and Webmention plugins can technically do what Madblog does, but it's a full CMS with a database, a theme engine, a plugin ecosystem, and a much larger attack surface. If all you need is a blog, it's overkill.
-
Plume and Friendica offer blogging with federation, but they're full social platforms, not lightweight publishing tools.
Madblog sits in a different niche: it's closer to a static-site generator that happens to speak federation protocols. It implements a workflow like "write Markdown, push to server, syndicate everywhere".
Getting Started
Docker Quickstart
mkdir -p ~/madblog/markdown
cat <<EOF > ~/madblog/markdown/hello-world.md
This is my first post on [Madblog](https://git.fabiomanganiello.com/madblog)!
EOF
docker run -it \
-p 8000:8000 \
-v "$HOME/madblog:/data" \
quay.io/blacklight/madblog
Open http://localhost:8000. That's it β you have a blog.
The default Docker image (quay.io/blacklight/madblog) is a minimal build (< 100 MB) that includes everything except LaTeX and Mermaid rendering. If you need those, build the full image from source:
git clone https://git.fabiomanganiello.com/madblog
cd madblog
docker build -f docker/full.Dockerfile -t madblog .
See the full Docker documentation for details on mounting config files and ActivityPub keys.
Markdown structure
Since there's no database or extra state files involved, the metadata of your articles is also stored in Markdown.
Some things (like title, description) can be inferred from the file name, headers of your files etc., creation date defaults to the creation timestamp of the file and author and language are inherited from your config.yaml.
A full customized header would look like this:
---
title: Title of the article
description: Short description of the content
image: /img/some-header-image.png
author: Author Name <https://author.me>
author_photo: https://author.me/avatar.png
language: en-US
published: 2022-01-01
---
...your Markdown content...
Key Configuration
Madblog reads configuration from a config.yaml in your content directory. Every option is also available as an environment variable with a MADBLOG_ prefix β handy for Docker or CI setups.
A minimal config to get started:
title: My Blog
description: Thoughts on tech and life
link: https://myblog.example.com
author: Your Name
Or purely via environment variables:
docker run -it \
-p 8000:8000 \
-e MADBLOG_TITLE="My Blog" \
-e MADBLOG_LINK="https://myblog.example.com" \
-e MADBLOG_AUTHOR="Your Name" \
-v "$HOME/madblog:/data" \
quay.io/blacklight/madblog
See config.example.yaml for the full reference.
It is advised to keep all of your Markdown content under
<data-dir>/markdown, especially if you enable federation, in order to keep the Markdown folder tidy from all the auxiliary files generated by Madblog.
Webmentions
Webmentions are the IndieWeb's answer to trackbacks and pingbacks β a W3C standard that lets websites notify each other when they link to one another. Madblog supports them natively, both inbound and outbound.
When someone links to one of your articles from a Webmention-capable site, your blog receives a notification and renders the mention as a response on the article page. Going the other way, when you link to an external URL in your Markdown and save the file, Madblog automatically discovers the target's Webmention endpoint and sends a notification β no manual step required. All mentions are stored as Markdown files under your content directory (mentions/incoming/<post-slug>/), so they're version-controllable and easy to inspect.
You can enable pending-mode for moderation (webmentions_default_status: pending), or use the blocklist/allowlist system to filter sources by domain, URL, or regex. Webmentions are enabled by default β if you're running Madblog locally for testing, set enable_webmentions: false to avoid sending real notifications to external sites.
ActivityPub Federation
ActivityPub is the protocol that powers the Fediverse β Mastodon, Pleroma, Misskey, and hundreds of other platforms. Madblog implements it as a first-class feature: enable it, and your blog becomes a Fediverse actor that people can follow, reply to, boost, and quote.
Enable it in your config:
enable_activitypub: true
activitypub_username: blog
activitypub_private_key_path: /path/to/private_key.pem
Madblog will generate an RSA keypair on first start if you don't provide one. Once enabled, your blog gets a Fediverse handle (@blog@yourdomain.com), a WebFinger endpoint for discovery, and a full ActivityPub actor profile. New and updated articles are automatically delivered to all followers' timelines.
Here's what federation looks like in practice:
- Receiving mentions: when someone mentions your blog's Fediverse handle in a public post (not as a reply to a specific article), the mention shows up on your Guestbook page.
- Receiving replies, likes, boosts, and quotes: interactions targeting a specific article are rendered below that article β replies as threaded comments, likes/boosts/quotes as counters and cards. All stored as JSON files on disk.
- Sending mentions: just write the fully-qualified handle in your Markdown (
@alice@mastodon.social) and save the file. Madblog resolves the actor via WebFinger and delivers a proper ActivityPubMentiontag β the mentioned user gets a notification on their instance. - Federated hashtags: hashtags in your articles (
#Python,#Fediverse) are included as ActivityPubHashtagtags in the published object. Followers who track those hashtags on their instance will see your posts in their filtered feeds. -
Custom profile fields: configure additional profile metadata (verified links, donation pages, git repos) that show up on your actor's profile as seen from Mastodon and other Fediverse clients:
yaml activitypub_profile_fields: Git repository: <https://git.example.com/myblog> Donate: <https://liberapay.com/myprofile>
The federation layer also exposes a read-only subset of the Mastodon API, so Mastodon-compatible clients and crawlers can discover the instance, look up the actor, list published statuses, and search for content β with no extra configuration.
Madblog also supports advanced ActivityPub features like split-domain setups (e.g. your blog at blog.example.com but your Fediverse handle at @blog@example.com), configurable object types (Note for inline rendering on Mastodon vs. Article for link-card previews), and quote policies (FEP-044f, so Mastodon users can quote your articles too).
LaTeX and Mermaid
Madblog supports server-side rendering of LaTeX equations and Mermaid diagrams directly in your Markdown files β no client-side JavaScript required.
LaTeX uses latex + dvipng under the hood. Inline expressions use conventional LaTeX markers:
The Pythagorean theorem states that \(c^2 = a^2 + b^2\).
$$
E = mc^2
$$
Mermaid diagrams use standard fenced code blocks. Both light and dark theme variants are rendered at build time and switch automatically based on the reader's color scheme:
```mermaid
graph LR
A[Write Markdown] --> B[Madblog renders it]
B --> C[Fediverse sees it]
```
Install Mermaid support with pip install "madblog[mermaid]" or use the full Docker image. Rendered output is cached, so only the first render of each block is slow.
Tags and Categories
Tag your articles with hashtags β either in the metadata header or directly in the body text:
---
tags: "#python, #fediverse, #blogging"
---
# My Article
This post is about #Python and the #Fediverse.
Madblog builds a tag index at /tags, with per-tag pages at /tags/<tag>. Hashtags from incoming Webmentions are also indexed. Folders in your content directory act as categories β if you organize files into subdirectories, the home page groups articles by folder.
Feed Syndication
Madblog generates both RSS and Atom feeds at /feed.rss and /feed.atom. You can control whether feeds include full article content or just descriptions (short_feed: true), and limit the number of entries (max_entries_per_feed: 10). limit and offset parameters are also supported for pagination.
Aggregator Mode
Madblog can also pull in external RSS/Atom feeds and render them alongside your own posts on the home page β useful for affiliated blogs, or even as a self-hosted feed reader:
external_feeds:
- https://friendsblog.example.com/feed.atom
- https://colleaguesblog.example.com/feed.atom
Guestbook
The guestbook (/guestbook) is a dedicated page that aggregates public interactions β Webmentions targeting the home page and Fediverse mentions of your blog actor that aren't replies to specific articles. Think of it as a public guest registry, or a lo-fi comment section for your blog as a whole. Visitors can leave a message by mentioning your Fediverse handle or sending a Webmention. It can be disabled via enable_guestbook=0.
View Modes
The home page supports three layouts:
cards(default) β a responsive grid of article cards with imageslistβ a compact list with titles and datesfullβ a scrollable, WordPress-like view with full article content inline
Set it in your config (view_mode: cards) or override at runtime with ?view=list.
Moderation
Madblog ships with a flexible moderation system that applies to both Webmentions and ActivityPub interactions. You can run in blocklist mode (reject specific actors) or allowlist mode (accept only specific actors), with pattern matching by domain, URL, ActivityPub handle, or regex:
blocked_actors:
- spammer.example.com
- "@troll@evil.social"
- /spam-ring\.example\..*/
Moderation rules also apply retroactively β interactions already stored are filtered at render time. Blocked ActivityPub followers are excluded from fan-out delivery and hidden from the public follower count, but their records are preserved so they can be automatically reinstated if you change your rules.
Email Notifications
Configure SMTP settings and Madblog will notify you by email whenever a new Webmention or ActivityPub interaction arrives β likes, boosts, replies, mentions, and quotes:
author_email: you@example.com
smtp_server: smtp.example.com
smtp_username: you@example.com
smtp_password: your-password
Progressive Web App
Madblog is installable as a PWA, with offline access and a native-like experience on supported devices. A service worker handles stale-while-revalidate caching with background sync for retries.
Raw Markdown Access
Append .md to any article URL to get the raw Markdown source:
https://myblog.example.com/article/my-post.md
Useful for readers who prefer plain text, or for tools that consume Markdown directly.
Reusable Libraries
Two key subsystems of Madblog have been extracted into standalone, reusable Python libraries. If you're building a Python web application and want to add decentralized federation support, you can use them directly β no need to adopt Madblog itself.
Webmentions
Webmentions is a general-purpose Python library for sending and receiving Webmentions. It comes with framework adapters for FastAPI, Flask, and Tornado, pluggable storage backends (SQLAlchemy or custom), filesystem monitoring for auto-sending mentions when files change, full microformats2 parsing, and built-in HTML rendering for displaying mentions on your pages.
Adding Webmentions to a FastAPI app:
from fastapi import FastAPI
from webmentions import WebmentionsHandler
from webmentions.storage.adapters.db import init_db_storage
from webmentions.server.adapters.fastapi import bind_webmentions
app = FastAPI()
storage = init_db_storage(engine="sqlite:////tmp/webmentions.db")
handler = WebmentionsHandler(storage=storage, base_url="https://example.com")
bind_webmentions(app, handler)
That's it β your app now has a /webmentions endpoint for receiving mentions,
a Link header advertising it on every response, and a storage layer for
persisting them. See the
full documentation
for details on sending mentions, custom storage, moderation, and rendering.
Pubby
Pubby is a general-purpose Python library for adding ActivityPub federation to any web application. It handles inbox processing, outbox delivery with concurrent fan-out, HTTP Signatures, WebFinger/NodeInfo discovery, interaction storage, a Mastodon-compatible API, and framework adapters for FastAPI, Flask, and Tornado.
Adding ActivityPub to a FastAPI app:
from fastapi import FastAPI
from pubby import ActivityPubHandler, Object
from pubby.crypto import generate_rsa_keypair
from pubby.storage.adapters.db import init_db_storage
from pubby.server.adapters.fastapi import bind_activitypub
app = FastAPI()
storage = init_db_storage("sqlite:////tmp/pubby.db")
private_key, _ = generate_rsa_keypair()
handler = ActivityPubHandler(
storage=storage,
actor_config={
"base_url": "https://example.com",
"username": "blog",
"name": "My Blog",
"summary": "A blog with ActivityPub support",
},
private_key=private_key,
)
bind_activitypub(app, handler)
# Publish a post to all followers
handler.publish_object(Object(
id="https://example.com/posts/hello",
type="Note",
content="<p>Hello from the Fediverse!</p>",
url="https://example.com/posts/hello",
attributed_to="https://example.com/ap/actor",
))
Optionally, you can also expose a Mastodon-compatible API so that Mastodon clients and crawlers can discover your instance and browse statuses:
from pubby.server.adapters.fastapi_mastodon import bind_mastodon_api
bind_mastodon_api(
app,
handler,
title="My Blog",
description="A blog with ActivityPub support",
)
Both libraries follow the same design philosophy: provide the protocol plumbing so you can wire it into your existing application with minimal ceremony. Storage is pluggable (SQLAlchemy, file-based, or bring-your-own), framework binding is a single function call, and the core logic is framework-agnostic. See the full documentation for Pubby and Webmentions.
Links
Madblog is open-source under the AGPL-3.0-only license. The source code, issue tracker, and full documentation are available at git.fabiomanganiello.com/madblog.
Reactions
How to interact with this page
Webmentions
To interact via Webmentions, send an activity that references this URL from a platform that supports Webmentions, such as Lemmy, WordPress with Webmention plugins, or any IndieWeb-compatible site.
ActivityPub
- Follow @fabio@manganiello.blog on your ActivityPub platform (e.g. Mastodon, Misskey, Pleroma, Lemmy).
- Mention @fabio@manganiello.blog in a post to feature on the Guestbook.
- Search for this URL on your instance to find and interact with the post.
- Like, boost, quote, or reply to the post to feature your activity here.
Madblog is founded on a simple principle: a blog is just a collection of #markdown files in a folder. No databases, no logins, no client-side bloat β just files.
The recently implemented support for both Webmentions and ActivityPub add an extra appeal to this approach: now those text files can federate, they can send mentions to Wordpress blogs or Mastodon accounts, and you can visualize mentions, comments and reactions from other corners of the Web directly under your articles.
But after receiving in the past few days a bunch of reactions on my blog that I couldn't interact with, which forced me to fall back on my standard Fediverse account to send replies and likes, I've decided to take the "everything is a file" philosophy a step further.
Now from #madblog you can also reply to comments and react to posts across the Fediverse - all from plain text files in your content folder.
Replying to Comments
When someone comments on your article from Mastodon or another ActivityPub-compatible services, their message appears on your blog.
Now you can also respond directly from your blog.
Or you can reply to any other post on the Fediverse or mention anyone, without those posts cluttering your blog's front page (I've learned to avoid this fatal design mistake made by e.g. Medium).
How it works
Create a Markdown file under replies/<article-slug>/:
---
reply-to: https://mastodon.social/@alice/123456789
---
Thanks for the kind words, Alice! I'm glad the tutorial helped.
@alice@mastodon.social
Save the file, and Madblog automatically:
- Publishes your reply to the Fediverse as a threaded response
- Notifies Alice on her Mastodon instance
- Displays the reply on your blog, nested under her original comment
Your reply lives in your content folder. Just like with your articles, you can version replies and reactions on git, synchronize them over SyncThing or Nextcloud Notes, or run some analysis scripts on them that would just operate on text files.
Replying to replies
Conversations can go as deep as you want. Reply to a reply by pointing reply-to at the previous message's URL:
---
reply-to: https://mastodon.social/@alice/123456790
---
Great question! I'll write a follow-up post about that.
@alice@mastodon.social
The threading is preserved both on your blog and across the Fediverse.

(I hope that @julian@fietkau.social and @liaizon@social.wake.st won't mind for using a screenshot from their conversation on my blog π)
Remember to mention your mentions
An important implementation note: if you're replying to someone else's ActivityPub post, it's important that you also mention them in the reply, otherwise your reply will be rendered under their comment but they may not be notified.
Usually you don't have to worry about this on Mastodon because the UI will automatically pre-fill the participating accounts in a sub-thread when you hit Reply.
But this is something to keep in mind when your posts are just text files.
Your replies are articles in their own right
Even though anything under replies/ won't appear on your blog's home page, it doesn't mean that it must be rendered just like a humble rectangle in a crowded comments section.
By clicking View full reply you get redirected to a separate page where the reply is rendered as a blog article, and its comments section consists in the sub-tree of the reactions that spawned from that specific reply.

Liking Posts
Sometimes a reply is too much β you just want to show appreciation. Now you can "like" any post on the Fediverse with a simple metadata header.
Standalone likes
Create a file under replies/ with just a like-of header:
---
like-of: https://mastodon.social/@bob/987654321
---
This publishes a Like activity to the Fediverse. Bob sees the notification,
and your blog records the interaction.
Like and comment
Want to like and say something? Combine both:
---
like-of: https://mastodon.social/@bob/987654321
reply-to: https://mastodon.social/@bob/987654321
---
This is such a great point! Bookmarking for later.
@bob@mastodon.social
Bob gets both the like and your reply as a threaded response.
Unlisted Posts
Not everything needs to appear on your blog's front page. Files under replies/ without reply-to and like-of headers become "unlisted" posts β they're published to the Fediverse but don't clutter your blog index.
Perfect for quick thoughts, threads, or conversations that don't warrant a full article.
---
title: Thoughts of the day
---
Quick thought: I've been experimenting with writing all my Fediverse posts
as Markdown files. It's oddly satisfying to `git log` my social media history.
Guestbook Replies
Your blog's guestbook works the same way. Reply to guestbook entries by placing files under replies/_guestbook/:
---
reply-to: https://someone.blog/mention/123
---
@alice@example.com welcome! Thanks for stopping by.
Editing and Deleting
Changed your mind? Edit the file and an Update activity is sent. Delete the file and your reply is removed from the Fediverse too.
Accidentally liked something? Remove the like-of line (or delete the file) and an Undo Like is published.
Your content, your rules.
Getting Started
- Enable ActivityPub in your
config.yaml:
link: https://blog.example.com
enable_activitypub: true
activitypub_username: blog
# Only specify these if you want your ActivityPub domain to be different from your blog domain
# activitypub_link: https://example.com
# activitypub_domain: example.com
-
Install Madblog
- From
pip:
- From
pip install madblog
- From Docker:
docker pull quay.io/blacklight/madblog
-
Run Madblog from your Markdown folder (it is recommended that your articles are stored under
<data-dir>/markdown):- From a
pipinstallation:
- From a
madblog /path/to/data
- From Docker:
docker run -it \
-p 8000:8000 \
-v "/path/to/config.yaml:/etc/madblog/config.yaml" \
-v "/path/to/data:/data" \
quay.io/blacklight/madblog
- Any text file you create under
markdown/becomes a blog article. Any text file you create underreplies/becomes an unlisted post, a reply or a like reaction.
Check the README for detailed configuration options.
Happy blogging!
Reasons for yet another ActivityPub server
The beginning β Mastodon
I've been running Mastodon-compatible services for a while, starting with my first now defunct Mastodon instance at social.platypush.tech.
Mastodon is a great gateway drug for the Fediverse, but it soon started to feel tight for me.
Features often land in Mastodon only when other federated platforms have already embraced them for a while (e.g. post edits), and they often land in ways that are incompatible with what other platforms have already implemented (e.g. quotes).
And many other features that I wanted for a rich social media experience (emoji reactions, Markdown support, configurable number of profile fields, configurable maximum number of characters, configurable number of media attachments, Webmentions, backfilling of statuses and other activities from remote instances, code blocks, inline images, custom frontends, LaTeX formulas, a simpler and more complete process for account migrations...) just never landed at all.
I ended up, like many others, maintaining my own fork of Mastodon, with all the patches for features I wanted and that would have probably never been merged upstream.
At some point I realized that keeping my own fork up-to-date with all the upstream changes wasn't worth the effort, and I started to look for a better way to run Mastodon-compatible services.
Another factor that influenced my decision was Mastodon's unjustifiably high resource footprint.
My old instance used to run on a dedicated VPS with 8 GB of RAM and 500 GB of disk space.
It only had me and another active user on it.
And yet all the federated load, with all of its eager operations managed by a bloated Ruby-on-Rails + Sidekiq stack, was sufficient to choke everything, even if I regularly ran cleanups.
Down the rabbit whole β Akkoma
At some point I started looking around for federated alternatives compatible with Mastodon that had a much lower resource footprint and provided most of the features I wanted.
I soon discovered Akkoma, and I've used it for a few years as my main driver - the last instance was manganiello.eu.
Akkoma filled many of Mastodon's gaps that mattered to me:
- Markdown posts
- Configurable number of post characters
- Configurable number of profile fields
- Code blocks (no syntax highlighting though)
- Emoji reactions
- Custom frontends (but not customizable on a user level)
It still left some gaps, especially some compatibility gaps with Mastodon (indexable flag on accounts, support for Mastodon quotes, remote profile badge verification...), but for a long while I was satisfied with what it provided.
Until recently I was also the maintainer of the AUR akkoma package (now looking for a new maintainer).
But after a while I also started to feel uncomfortable with Akkoma's limitations.
Mastodon-compatible quotes were a dealbreaker, and my implementation failed to get approved upstream - ending up on the fork I ran on my instance.
Other features, like full bidirectional verification for profile badges and support for the indexable flag, also ended up living only on my fork.
Other issues, like proper compatibility with Audio activities from e.g. Funkwhale or Songhive, also made the experience less pleasant.
Akkoma however proved to show much more clemency towards my hardware resources than Mastodon did.
But the price to pay was to implement the features I wanted in a language (Elixir) that was quite exotic and unfamiliar to me (even though I ended up learning a lot from it).
I also couldn't find much documentation about e.g. Akkoma jobs or configuration.
I found Akkoma's documentation to be quite minimal in terms of content.
Understanding some configuration options or what job to run for a particular task often required me to look at the code itself.
Another issue with Akkoma was with the frontend.
I know that the default pleroma-fe can be quite polarizing, and that people either love it or hate it.
I belonged to the category of those who, no matter what, never managed to like it.
Luckily Akkoma could be configured to use alternative frontends, and I ended up liking the style of Soapbox, and even more that of its fork Mangane.
But I still felt that those frontends weren't particularly rich in terms of features, nor particularly curated around the edges.
Plus, the admin panel was an afterthough provided as a separate frontend rather than a first-class citizen like in Mastodon, and the UX was also poorly curated.
Still, the Soapbox/Mangane style ended up heavily inspiring the design of the default Yonder frontend.
Building Yonder
I started building Yonder (source code, Github mirror) a while ago, as a minimal PoC for an ActivityPub server in Rust .
It's been on a back burner on my hard drive for a while, but now I feel that it's mature enough to be my main driver on the Fediverse.
Yonder is a self-hosted, Mastodon-compatible ActivityPub server. The entire service β HTTP API, federation, streaming, media, moderation, admin panel, background jobs β is one binary. The only services it needs are PostgreSQL and Redis.
It speaks the Mastodon client API (v1 and v2), so Tusky, Ivory, Elk, Phanpy, Mona and every other Mastodon app just works when pointed at your instance.
It also implements a good subset of the Pleroma/Akkoma API dialects, which means that clients like Moshidon and other Pleroma-compatible apps can also access those features (e.g. Markdown content type for posts and custom emojis).
It speaks ActivityPub, so your users federate with Mastodon, Akkoma, Pleroma, Misskey and the rest of the Fediverse.

Name and meaning
Yonder (adv. or adj., /ΛjaΚndΙ/) is an Old English term for "over there". Something distant but usually within sight.
I chose it as the name for this project because it relays, together with the logo (a large circle connected to three other circles), the idea of connecting things distant but within reach.
What you get
Posting & timelines
- Rich posts in plain text or Markdown, with content warnings, polls, media attachments with editable alt text, scheduled posts, editing and saved drafts.
- Quote posts with author authorization (FEP-044f-style, with fallback to FEP-e232 Pleroma/Akkoma/Misskey compatible quotes), custom emoji reactions, replies, boosts and likes.
- Every timeline Mastodon has: home, local, federated, hashtag timelines, user-defined lists β with real-time updates over the standard Mastodon streaming WebSocket.
- Hashtags you can follow into your home feed and server-side filters (
warn/hide/blur) that apply across every timeline.

Social & federated
- Full ActivityPub federation via Pubby, with durable at-least-once delivery. I built Pubby as a general-purpose ActivityPub library that takes care of the all the plumbing behind the scenes, initially with Python bindings to power Madblog and Songhive, and it gained Rust bindings with features parity with the Python SDK in order to power Yonder - available as
pubby-sdkcrate. - Notifications in-app over WebSocket, Web Push (VAPID) and email, with per-type preferences.
- A progressive Web app (PWA) optimized for mobile and with support for native notifications.
- The bundled Web UI ships in five languages including full RTL support, with light and dark themes and custom accent colors.
- Custom emojis β per-instance emoji and emoji packs.
- Custom number of characters, custom number of profile fields, custom number of media attachments and custom number of pinned posts.
- RSS and Atom feeds for profiles, tags and lists; oEmbed/embeddable status cards.
Moderation & administration
- User-side: mutes, blocks, reports (optionally forwarded to the remote instance via
Flag), server-side content filters. - Instance-side: user limiting and suspension, domain blocks, federation relays, and a comprehensive admin panel delivered as a first-class citizen.
- Every registration policy:
open,invite-only,approval-requiredorclosed.
Platform
- One single Rust binary β stack:
axum,sqlx,tokio. - OAuth2 provider with authorization-code + PKCE, device flow, and scoped revocable API tokens.
- Pluggable frontends: the bundled Vue 3 SPA is just the default; alternative frontends can be installed alongside it. Users can pick their favourite frontend, preferences are stored in the browser session.
- OpenAPI 3 spec at
/openapi.jsonwith bundled Swagger UI. - Safety defaults: argon2id passwords, SSRF-guarded remote fetches, Redis-backed rate limits, TOTP two-factor.
What's new
Account migration
Account migration is a first-class feature: moving an account to or from another server, followers and all, is a supported flow, compatible with Mastodon and Akkoma.
On top of that, Yonder supports importing activities from the old account in two ways:
- Standard CSV import/export (compatible with Mastodon/Pleroma/Akkoma)
- OAuth2-authenticated API fetches.

You login to your old account through Yonder's interface, you pick what you want to import from your old account (including private messages, likes, boosts, replies, etc.), click "Start remote import", and everything from your old account will be copied over - as a native activity that originated from the new account, with the original timestamps respected.
The user can also decide whether the imported activities will fan out to federated instances or only be stored on the local database - prevents avoidable federation noise over imports, the activities can be selectively federated by simply boosting them or editing an old post.
The only thing that Yonder doesn't support is importing received likes, boosts and replies - for the simple reason that it doesn't want to forge federated activities or rewire threads in ways that don't reflect what other instances see.
The UX of the account migration flow has also been re-thought as a step-by-step process (connecting the old account over OAuth2, importing the data over API crawlers or CSV backups, reviewing the import process, creating an alias and moving followers), making the process much more intuitive and mistakes harder.

See the full federated picture all the time
One of the most confusing (and often infuriating) things about the Fediverse is that what you see on your local instance is often a very small subset of what's actually available on the Fediverse (unless you are on a large instance like mastodon.social, and even in that case many activities from the fringes of the Fediverse are lost).
Your instance only receives what its peers send to it. And an instance's peers depend on who your users follow, which relays you wired your instance to, and who your users interact with.
This has an unintended consequence: that content that never reaches your instance is invisible to you. Unless you trigger an explicit fetch, e.g. through a search query or some import job. And even then, you probably won't see a lot of likes, boosts and replies a remote activity has received, nor the real number of followers of a user.
Yonder solves this problem by adding a couple of new endpoints to the standard Mastodon API, and slightly modifying how some of the existing endpoints behave in order to maintain back-compatibility with existing apps.
/api/v1/accounts/{id}/sync_remote. This allows users to explicitly sync the latest<n>activities from the account{id}from the remote instance to the local database. If your Mastodon instance sees an account for the first time, and no local users follow that account, their timeline will probably appear empty, and they will show as having zero followers/followed accounts. Yonder fixes this visibility gap by adding a "Sync with<remote-instance>" button next to remote profiles, which triggers a remote fetch for their next<n>activities.- Followers and followed accounts are also synchronized with the remote instance, so you see the actual numbers. Upon calls to the
/followersendpoint, the list is lazily fetched and you can navigate it from your local instance - without having to open the original profile URL to see the actual numbers. /api/v1/statuses/{id}/fetch_remote_context. This endpoint is called by the Yonder frontend whenever you expand a post that belongs to a remote thread. What it does is to fetch behind the scenes all the statuses that belong to the same parent line, with a default maximum depth of 20. This, in my opinion, matches the expected behavior from a social app user. If I see a comment from a friend on another thread and I click on it, the most relevant thing I want to see is the direct path of statuses from the root of the thread down to the status I clicked on, plus the next 2-3 direct children. The client ends up seeing exactly the same context as the instance of the post's author. This is back-compatible also with existing Mastodon apps - calls to the/contextendpoint will trigger/fetch_remote_contextbehind the scenes if needed, and a refresh of the status 2-3 seconds later should show all the expanded remote posts in that path. Siblings and descendants from other paths are not fetched by default, but they are fetched if the user expands statuses on those paths. This approach means that fetches of remote threads provide a much more complete picture than that provided by Mastodon by default (you get to see exactly the same view as the author of that post, not only the subset explicitly send to your instance), while simultaneously being more efficient than what e.g. Mastodon does (fetch overhead is capped by the depth of the path, set to 20 by default, instead of trying to eagerly fetch the whole tree with no boundaries).
Another handful of useful API extensions
POST/DELETE /api/v1/accounts/{id}/subscribe: subscribe/unsubscribe to an account's activities without publicly following them.GET /api/v1/trends/tags: browse global or local trending hashtags, with support for pagination and time ranges.POST /api/v1/admin/accounts/{id}/reset_password: programmatically send a user password reset link directly to their email.POST /api/v1/admin/statuses/{id}/action: apply granular moderation to individual statuses (delete, mark as sensitive, add content warning).
Trending hashtags
This is something that for some reason Mastodon removed at some point, but that I find very useful.

Yonder makes it easy not only to follow hashtags, but to have a view of all the hashtags that are trending over the local instance or over all the known Fediverse, over a given period of time, and with support for pagination.
Direct messages as real conversations
Direct messages in Yonder are real conversations, not just an ungrouped timeline of cards with a lock on them.

This is similar to what users expects by social networks like X, Facebook or Instagram - private messages are not a timeline, they are grouped conversations, and it should be easy to find a private message from a month ago even if you received hundreds of messages on a single unrelated conversation in the meantime.
Webmentions
Webmentions are first-class citizens supported in both directions.
What this means is that:
- If a blog or federated actor
example.blogthat supports Webmentions posts a link toexample.social/status/123,example.socialwill process the Webmention and render it as a normal reply or reaction. The Webmentions actor will also be transparently rendered as a virtual user on the platform. - If you link
example.blogin a post onexample.social, andexample.blogsupports Webmentions, then the target will receive a Webmention request, and your social activity may be natively rendered under the blog article.
Webmentions are powered by my webmentions library - which, just like Pubby, was initially built in Python to support Webmentions on Madblog and Songhive, and then ported to Rust with features parity with the Python SDK - available as webmentions-sdk crate.
LaTeX
Instances like mathstodon.xyz run their own forks of Mastodon with support for LaTeX formulas.
But they use MathJax, which means that formulas are only rendered on the frontend, and only if you see them from that instance.
Yonder goes one step further and it adds rendering of LaTeX formulas directly on the backend.
You can provide your rendering script, set math.enabled = true in your configuration, and set math.command to your LaTeX rendering command.
Any command that takes the LaTeX formula on the stdin and returns an image on stdout works.
The repository ships a latex-math-render.sh script that is already compatible with tectonic and pdflatex.

Being rendered on the backend, the formulas are also rendered on clients that don't support frontend rendering through MathJax.
If the server or the client support inline images (e.g. Phanpy), then formulas will be rendered inline.
If it supports math-type attachments, then the formulas will be rendered at the bottom of the post.
Otherwise, they will graciously fall back to image attachments, with LaTeX-style references ((1), (2)...) as links in the post.

Inline images
Yonder supports inline images via standard Markdown:


Embeddables
Embed your posts in blog, Websites and anywhere on the Web. Click on the context menu of a post, select "Embed", and copy the snippet:
<div class="yonder-embed" data-status="{status-id}">
<a href="https://{instance}/statuses/{status-id}/embed">Post by @{user}@{instance}</a>
</div>
<script async src="https://{instance}/embed.js" charset="utf-8"></script>
<noscript>
<iframe src="https://{instance}/statuses/{status-id}/embed" width="100%" height="400" frameborder="0" loading="lazy" title="Post by @{user}@{instance}" />
</noscript>
An example:
Reactions to the status are fetched from the instance, if the user updates their status the referring page will update as well. If the status is deleted, it will also be deleted from the referring page. And Webmentions towards the Yonder target will also be processed if supported by the referring page, so the referring page will also be shown under the thread as a federated reply.
How it compares
I want to be honest here rather than hype-y, because "yet another Mastodon-compatible server" deserves scrutiny.
A feature matrix would be the natural way to do this, but matrices are painful to read on a phone, so here's a plain-language summary of where each implementation actually stands (as of late 2026). All of them speak ActivityPub and the Mastodon client API (Yonder implements both the v1 and v2 dialects plus a subset of the Pleroma/Akkoma extensions).
| Yonder | Mastodon | Akkoma/Pleroma | |
|---|---|---|---|
| Language/runtime | Rust (single binary) | Ruby + Node + optional ES | Elixir |
| Required services | Postgres + Redis | Postgres + Redis (+ ES for search) | Postgres (+ ES optional) |
| Mastodon client API | β v1+v2 | β (it's the reference) | β |
| ActivityPub federation | β | β | β |
| Quote posts | β (both FEP-044f and FEP-e232) | β οΈ (limited to FEP-044f) | β οΈ (limited to FEP-e232) |
| Markdown posts | β | β | β |
| Emoji reactions | β | β | β |
| Webmentions | β both directions | β | β |
| LaTeX math | β server-side | β (only on custom forks, and only on the frontend) | β |
| Account/followers migration (both directions) | β | β | β |
| Data export/import | β both over CSV backups and API crawlers | β οΈ only CSV backups | β οΈ only CSV backups |
| Alternative frontends | β installable and configurable on a per-user basis | β | β οΈ installable on instance level, not customizable on a user level |
| RSS/Atom feeds | β | β | β |
| Embeddable status cards | β | β | β |
| On-demand fetch of remote content (followers, reactions, replies) | β | β | β |
| Admin panel | β (built-in) | β (built-in) | β οΈ (as a separate frontend) |
| Battle-testing | new (v1.0.x) | a decade | ~5 years |
Quickstart
Docker
Official Docker image provided on quay.io/yonder/yonder:
docker-compose setup (with Redis, Postgres and separate worker service):
git clone https://github.com/blacklight/yonder
cd yonder
cp .env.example .env # set PUID/PGID, domain
cp config.toml.example config.toml
docker compose up
Crate
Or grab the binary directly β it's on crates.io and in the GitHub releases:
cargo install yonder-server
# Copy and edit the configuration file
wget -O config.toml https://git.fabiomanganiello.comn/yonder/raw/branch/main/config.toml.example
yonder serve
# Separate process for workers (recommended)
yonder worker
Binary release download
VERSION="1.0.3" # IMPORTANT: Set to the version you want
wget -O yonder.tar.xz https://github.com/blacklight/yonder/releases/download/v${VERSION}/yonder-${VERSION}-x86_64-unknown-linux-gnu.tar.xz
tar -xf yonder.tar.xz && cd yonder-${VERSION}-x86_64-unknown-linux-gnu
cp config.toml.example config.toml
./yonder serve
# Separate process for workers (recommended)
./yonder worker
Setup
Config is a single config.toml (every key also settable via YONDER_* env vars or the admin panel). Federation is on by default, registration modes are configurable, and yonder config list dumps every knob.
Create your admin user:
yonder user create --username alice --admin
Or, from your docker-compose directory:
docker compose run --rm yonder user create --username alice --admin
Open the instance, log in, and verify federation works:
curl 'https://mastodon.social/.well-known/webfinger?resource=acct:you@your.instance'
Try it
- Source: github.com/blacklight/yonder (AGPL-3.0)
- Live instance: manganiello.tech β my own Yonder instance, federated with the wider Fediverse
- API docs:
/openapi.jsonand/swagger-uion any running instance - e.g. manganiello.tech/swagger-ui
AI usage disclosure
In the following table, ποΈ means "manual" and π€ means "aided by AI agents".
| Feature | ποΈ | π€ |
|---|---|---|
| Initial architecture | β | |
| Feature planning | β | |
| Coding | β | β |
| Testing | β | |
| Code reviews | β | β |
| Deployment | β | |
| User documentation | β | |
| Development documentation | β | β |
| Commit messages | β | β |
| Release notes | β | |
| Translations | β | |
| This blog article | β |
Appendix: My personal federated stack
Yonder is the latest product I've built for the Fediverse.
My journey with building products for the Fediverse from scratch rather than contributing only to established projects began around the beginning of this year, as I started growing dissatisfied with the features of many established products.
My main use cases for federated platforms are:
- π Blogging
- π΅ Music publishing and federation
- π’ General-purpose social media
And here's how my journey through self-hosted Fediverse platform went over the years.
Blogging
- Journey: WriteFreely β Madblog
- Blog article
- My instances:
Madblog was my starting point to start experimenting building software for the Fediverse.
The use-case was simple: a fully federated blogging platform that ran from a folder of Markdown files.
Single-actor instance, no support for following other users, no timelines, no admin panel, no login, no database, but full bidirectional federation based on text files and email notifications.
Music
- Journey: Funkwhale β Songhive
- Blog article
- My instance:
I built Songhive to cover many gaps I found in Funkwhale when it came to federation support, and many gaps in existing self-hosted music catalog solutions.
It's a hybrid between a music catalog with support for external sources, a platform for musicians to share and sell their content, and a music social network.
Federation-wise, it offers more features than Madblog (e.g. following users and managing timelines), but its main goal is not to provide all the features that Mastodon provides - just a sensible subset that makes it easy to share music and audio activities.
Social media
An Amazing find!
I've been looking for something to fit a niche and have tried or considered:
- WordPress w/ActivityPub plugin - It's too heavy, not a wordpress fan per se' for my personal publishing needs - I have infra that I wish to use and don't need yet another full-blown CMS to weigh things down, not to mention the attack surface and constant updates.
- Write.As / WriteFreely - An Excellent publishing platform but with shortcomings enumerated in the article I've quoted below.
- SilverBullet - A phenominal platform that I use as a daily driver for everything from thoughts & scribbles to organized wiki publications that I keep close and then copypasta into my published articles. Due to the lack of #ActivityPub integration and also because it's more Wiki that can be browsed than a publishing platform that restricts browsing, I eventually opted just for the local version which is perfect for much of my work flow, but not as a public facing publishing platform.
- Drupal - I had hopes for this a few years back, but it's fragmented into various pieces that I feel belong together, such as the Personal Reader module and one or two others to make it a complete package. There was #NLnet funding a couple of years back, but progress was so slow and uncertain that even though there appears to be serious movement on it a couple of months back I'm just not interested anymore and frankly, Drupal is another heavy object to lift in the same manner as WordPress.More info on that prior funding initiative here
- Hugo - This was a sem-complete, or depending how you look at it, incomplete solution a few years back in dog years. Here's a more recent implementation but even that is almost 3 years ago. I'm still big on rolling out Hugo, via Sveltia-CMS, as there's been a lot of great work in this area and a lot of support, w/impressively performant sites...
But Today I was checking out a new Fediverse Server, and in the process stumbled across this, MadBlog, from the developer of the popular Platypush which, along with **n8n are no-brainer alternatives to the proprietary Zapier.
The simplicity with which one can deploy and publish and in whatever manner once chooses is simply the most refreshing thing I've come across in.... Well, at least a few days ;)
Okay so here's the deal. I haven't installed it yet, but even if I had I wouldn't be able to provide the synopsis and insight into the simplistic power and myriad manners of deployment that are possible - it's just a file, wrap it and serve it how you like, basically, or provide your own framework, say, a headless CMS.
So without further ado I'm just going to encourage you to read on straight from the horses mouth, so to speak, as Fabio does such a fantastic job explaining the how's and why's that brought him to develop such a fine, lightweight Fediverse publishing solution.
By the way, he published this article just yesterday. Enjoy!
#tallship #FOSS #AGPL #Fediverse #MadBlog
β΅
@fabio
RE: https://manganiello.blog/article/Madblog-federated-blogging-from-markdown
RE: https://blog.fabiomanganiello.com/article/Madblog-federated-blogging-from-markdown
" Madblog: A Markdown Folder That Federates Everywhere. --A lightweight blogging engine based on text files, with native Fediverse and IndieWeb support " : -- https://manganiello.blog/article/Madblog-federated-blogging-from-markdown
-
Madblog: A Markdown Folder That Federates Everywhere (documentation)
A lightweight blogging engine based on text files, with native Fediverse and IndieWeb support
[ IndieNews ]
-
crosspost
A JavaScript utility for posting across multiple social networks at once
[ πangusm ]
-
writerdeckOS (about)
Convert any laptop and most chromebooks into a writer deck. A device designed solely for writing.
[ πbraveterry ]
-
Awesome Modern CLI
A curated list of modern alternatives to classic command-line tools. Faster, prettier, smarter replacements for the Unix utilities you use every day.
[ πtdjones ]
-
rssrssrssrss
Combine multiple RSS feeds into one unified feed
[ πcogdog ]
Weeknotes is back! Was busy and got bogged down by life in general last week, which meant I had to skip a week⦠Hope everyone is doing well.
Completed
- Finally caught up with my /Γ’ΒΒ changelog page. I havenβt updated it since February as I was busy working on the redesign branch; which I havenβt touched for two months!
- Made some stylistic improvements to the changelogΓ’ΒΒthe subheadings have a much smaller font-size now to improve readability (using a custom class name).
- The latest updates are code block styles (which I am quite pleased about, see it in the last post with code) and minor changes to the top of my home page.
- While working on the floating element (profile picture) I had trouble getting the heading below the picture to align properly to the left. Apparently, I needed to βclearβ the float!
- Two major Linux CVEs last week, CopyFail and DirtyFrag. The Raspberry Pi kernel still isnβt patched yet. Luckily the mitigations for both vulnerabilities was not that difficult.
- Published a new technical post last week about my Feather Wiki usage. I seemed to be quite a popular post and I even got to connect with Robbie (the dev behind the project) for a bit which was really cool. He also merged my PR of the pt-PT translation (with the help of Randal)!
New #blog on #BurgeonLab Γ’ΒΒΓ―ΒΈΒ
Γ’Β‘︠https://burgeonlab.com/blog/feather-wiki-brain-dump-app/
I wrote about a new app I'm using and my note-taking setup! It's a tool used for non-linear notebooks and #wikis called Feather Wiki @FeatherWiki.
This is post 38 of #100DaysToOffload
Γ°ΒΒΒ https://burgeonlab.com/tags/100daystooffload/
@tiddlywiki@a.gup.pe @TiddlyWiki
#blogging #blogs #guides #newpost #blogpost #smolweb #techblog #techguides #termux #android #obsidian #pkm #syncthing #httpd #busybox #braindump #privacy #wiki #featherwiki #tiddlywiki #selfhosting

Discover Feather Wiki, a FOSS lightweight and customizable personal private web notebook, with multi-device sync via Syncthing and Android support using Termux.
In Progress
- My Tuta account is due for renewal next month. Iβm thinking of migrating after being with them for a couple of years because the Android apps are still quite sluggish, and I am not getting notifications reliably for some reason despite usual troubleshooting. Inability to use third-party email clients and lack of PGP/GPG support is making me consider alternatives. Iβm looking at mailbox.org currently.
- Talking about my blog redesign, I made a big mistake of writing too many commits on this new branch when I beganΓ’ΒΒnew features, design changes, style updates. Being the Git newbie that I still am, I failed to do small feature branches to keep things tidy so I could merge/rebase back to Main bit by bit.
- Instead of doing a huge merge/rebase now (there will be so many conflicts that Iβm not confident of fixing), I am trying to learn how to use interactive rebase and cherry-pick. But I still need to understand more before I begin the βsurgeryβ to fix the Git mess Iβve created!
- I think Iβm leaning towards making small feature-branches from my current Main branch HEAD, then cherry-picking (with
-x) the relevant commits from Redesign branch, ΓΒ± squash if necessary, merge/rebase into Main. - To see what remaining unpicked commits, something like this can be run (I think?):
git log redesign-branch ^main --onelinewhich can help track my progress. - Still uncertain if rebase or merge is cleaner in the long run for a single user project⦠leaning towards rebasing for a cleaner history.
- My M1 Mac Mini (2020) started crashing the Dictionary app (I go into more details here). Adam (from Adamβs Desk) kindly sent over a few extra troubleshooting links like this Apple Discussions thread about the
xattrerror message I also have. I think a reinstallation of the system is requiredβ¦
Motherβs Day
I am lucky to still have my mom with me. We did her favourite things today and celebrated Motherβs Day together. I want to take this moment to express my gratitude for everything sheβs done and sacrificed for me, in order to give me the best of everything. Sheβs the bestΓ’ΒΒmy constant supporter, teacher of many things, and my rock. To all mothers out there, including my awesome mom, I hope you feel appreciated, celebrated, and loved as you deserve to be; every single day.
Link Roundup
Here are some links I found interesting in the last two weeks.
Small Web
- Start writing | Robert Birming Γ’ΒΒ I should learn from Robert.
- The internet used to be fun | Kwon Γ’ΒΒ Found this great post by Kwon that is a directory of articles that cover the question βWhy have a personal website?β Definitely worth checking out.
- IndieWebCamp DΓΒΌsseldorf 2026 | James Γ’ΒΒ I have been busy and unfortunately still havenβt written up my summary/thought post on IWC: DUS 2026, but check out Jamesβs post if you want to see what he did!
- Webmentions for your Static Site | Rowan Manning Γ’ΒΒ One day, I want to have a page or section on my site to show who and what was mentioned from my site. I tried manually including some in a weeknote a few weeks ago but I realized a problemΓ’ΒΒif I set up auto webmention sending one day, that will result in duplicate/looped mentions which I donβt want.
- The webmention storage part is what confused me when I first got into all this. I should investigate this more thoroughlyβ¦
- IndieWeb Directories | Paul Tibbetts Γ’ΒΒ A great resource by Paul on where to find good Internet content.
- Unfriending Facebook, Instagram and Goodreads | Angelique Weger Γ’ΒΒ An older article but still stands.
- Speed! Formula 1 Feed | Tekphloyd Γ’ΒΒ I follow @tekphloyd on Mastodon and recently found out heβs into F1 like me! He has this feed all about F1, and itβs quite nice to get all the news during race weekends in one central place. Itβs created using surf.social, which allows users to combine various sources into one feed.
- Journaling Slump | Coriander in Pho Γ’ΒΒ I used to have slumps in journalling too (also used the Hobonichi). Unused pages ended being βdate freeβ note pages or mental scratch pads for the day, so I never felt like I βwastedβ pages.
- Scroll quadrΓΒgintΓΒ | Shellsharks Γ’ΒΒ Mike has gathered a group of female Fediverse and IndieWeb authors and creators for last weekβs Scrolls newsletter. I am honoured to be included, and this is certainly appreciated as the gender skew on the blogs I follow is quite severe!
Corporate
- Google Just Patented The End Of Your Website | Forbes Γ’ΒΒ What a horrible time it is for Internet users. I suggest using alternative search engines.
- SXSW Used AI-Powered Trademark Tool To Censor Dissent on Instagram | 404 Media Γ’ΒΒ Another example of censorship on the rotten platform that is Instagram.
- Ask.com, aka Ask Jeeves, has officially shut down after nearly 30 years online | AlternativeTo Γ’ΒΒ Wow, an end of an eraβ¦ still remember using it as a kid.
- Copy Fail | xint.io Γ’ΒΒ I took the chance to update my Macbook Air 2012 running Linux Mint from 21.3 to the latest 22.3 Zena following the Copy Fail CVE. Unfortunately, Raspberry Piβs kernel is still not updated so Iβm using the temporary mitigation for now.
- Popular WordPress redirect plugin hid dormant backdoor for years | Bleeping Computer Γ’ΒΒ WordPress news like these just make me feel like WP sites are a ticking time bomb! I will be converting mine to a static version soon, like what Dave has written here.
- Novel Campaign Abuses Obsidian Note-Taking App to Target Finance and Crypto Professionals with PHANTOMPULSE RAT | Netsecops Γ’ΒΒ Dangers of pluginsβ¦
- The 2026 CP+ Photo Expo Solidified Its Importance to the Industry | PetaPixel Γ’ΒΒ I havenβt been paying attention to the photography sceneβ¦ I actually didnβt know Photokina dissolved in 2020. I hope the CP+ Show will be more international-friendly in the future!
- Study Finds A Third of New Websites are AI-Generated | 404 Media Γ’ΒΒ I just want to read some human content. Thatβs allβ¦
Projects
- We Love 88x31 Γ’ΒΒReally cute and retro page counter with no cookies, JavaScript or tracking. Will probably add one to my site soon!
- Madblog: A Markdown Folder That Federates Everywhere | Fabio Manganiello Γ’ΒΒ For those interested in creating site with Markdown + Federation + IndieWeb support.
- Bad Website Club Γ’ΒΒ Really awesome boot-camp for those who want to learn responsive web design for free, taught by Carmen, Eda, and Jess.
- Little Pixel Library Γ’ΒΒ Are you into pixel art and books? Check this out! I came across it via Chrisβs site.
- Taken Since You Arrived Γ’ΒΒ A good wake-up call.
- Is the project still alive? ΓΒ· terrastruct/d2 | GitHub Γ’ΒΒ Iβm more than thrilled that the creator of D2 Lang (the diagram tool I rely on heavily) is moving the project to the Non-Profit, Hack Club (similar to what Ghostty did).
- ai.robots | GitHub Γ’ΒΒ I updated my
robots.txtlast week, maybe you should have a look too? Hope to get Anubis or some bot/scraper checker in the future, but this will do for now. - Introducing Zapp | ZSA Γ’ΒΒ Flashing ZSA keyboards now supported over the terminal instead of your browser or ZSA Keymapp.
@fabio also sorry, I'm having another issue π
I have made several replies from this account but for some reason on my madblog I see only the last one, even though there seem to be the corresponding entries in .madblog/activitypub/state/interactions/_object_ids for all the replies
Upd: ironically, I can't see the other reply to this post I just sent from Mastodon (https://mastodon.social/@uityui/116374955021105009) on your madblog either
@fabio I've looked into the code and it seems the line 214 in reactions.py (https://git.fabiomanganiello.com/blacklight/madblog/src/commit/72853b277997ad76bc650c8486c37a04b5e509af/madblog/reactions.py#L214) causes only one post from each user (alias) to be displayed
@fabio This is amazing. It checks all the boxes for me. I'd have used it if I didn't have an existing SSG, but I'm going to recommend it to everyone.
Here is a collection of things I liked and bookmarked during March 2026:
@fabio This is super cool. I'm self-hosting WriteFreely at the moment and I'm disappointed in the federation implementation so Madblog looks like it's right up my alley.
@fabio @liaizon New quote test, wooo!
https://blog.fabiomanganiello.com/article/Madblog-federated-blogging-from-markdown
@fabio yay it looks like it works now!
another tiny bug I will note: the way you are adding my mention in your reply is causing mastodon to make a link preview for it. while I don't know what you need to do technically to disable it, I know its able to be done since they only show up like this for certain server softwares
@liaizon @fabio That one's a microformat mismatch, Mastodon looks for the class "mention" to skip the link preview and open the profile locally. https://docs.joinmastodon.org/spec/microformats/#mastodon
@fabio this is getting annoying, every time you save your site you are sending a new version of all your likes so this thread gets bumped to the top of my feed
@fabio why reinventing the wheel in such a complicate way?
Software like GtS allows domain splitting. My GtS, by example, runs under x.keinpfusch.net, but it responds for keinpfusch.net, which is my blog. Wvertyhing you need is to forward the traffic for the Webfinger, when it reaches the blog, to the AP backend, meaning GtS itself.
So basically you can have ablog on yourdomain.tld, and in the same time make the domain be recognized as an activitypub node with the first level domain.
you can find me in the fedivers using uriel@keinpfusch.net , despite of the fact the GtS is running on the x.keinpfusch.net . So LITERALLY EVERYTHING can be "federated" , the same way.
I mean, WebFinger protocol has the feature anyways. In the past I was doing the same also #snac2, using another feature, "path".
There are many ways to do this, why reinventing the wheel, precisely?