The Programmer’s Fulcrum 17 July, 2026
This post originally appeared on The Fulcrum. Welcome to this week's The Programmer's Fulcrum. It's your weekly curation of the essential news in the Open Media Network and Open Social development communities with a focus on devastating big tech via Techno Anarchism. As usual, we aim to provide actionable content you can use to destroy...
his post originally appeared on The Fulcrum.
Welcome to this week’s The Programmer’s Fulcrum.
It’s your weekly curation of the essential news in the Open Media Network and Open Social development communities with a focus on devastating big tech via Techno Anarchism.
As usual, we aim to provide actionable content you can use to destroy Techno Feudalism each week. It has the additional benefit of weakening authoritarianism.
IMHO, the best way to do that is to use tools from the Techno Anarchist Manifesto to build your own site(s) to participate in the Open Media Network. Then you should share it (them) via Real Simple Syndication (RSS), the Fediverse, and possibly a newsletter or podcast. This approach is similar to what some call the IndieWeb and its POSSE philosophy.
The second best strategy is to have accounts on the Fediverse and use the hell out of them. And do the same with a RSS feed reader.
We publish TPF on Fridays so you can enjoy it over your weekend.
There’s good stuff in all of our categories, so please take the time to enjoy and bookmark the items most relevant to your goals. We hope you are inspired to create new ones.
Or you can scroll down to your favorite section.
FYI, my opinions will be in bold. And may involve cursing. Because humans. Especially tech bros. And fascists. Fuck´em.
A quick aside as you can now add Fediverse polls to WordPress posts, here’s a test.
<div class="polls-for-activitypub-poll__footer">
<div class="polls-for-activitypub-polls__actions">
<!-- Fediverse vote button (modal) -->
<div class="polls-for-activitypub-remote-profile">
<div class="polls-for-activitypub-remote-profile__inner" hidden data-wp-bind--hidden="!context.hasRemoteUser">
<a
class="polls-for-activitypub-remote-profile__link wp-element-button wp-block-button__link"
data-wp-bind--href="state.remoteProfileUrl"
>
Vote as <span data-wp-text="context.profileURL"></span> </a>
<button
type="button"
class="polls-for-activitypub-remote-profile__delete"
data-wp-on--click="actions.deleteRemoteUser"
title="Delete Remote Profile"
aria-label="Delete cookie that remembered your remote Fediverse profile used for interactions"
>
<svg fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="22" height="22" role="img" aria-hidden="true" focusable="false">
<path d="M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"></path>
</svg>
</button>
</div>
<button
class="polls-for-activitypub-poll__button wp-element-button wp-block-button__link"
data-wp-on-async--click="actions.toggleModal"
data-wp-on-async--keydown="actions.onReplyLinkKeydown"
data-wp-bind--hidden="context.hasRemoteUser"
data-wp-bind--aria-expanded="context.modal.isOpen"
aria-label="Vote via Fediverse"
aria-haspopup="dialog"
aria-controls="modal-heading"
role="button"
tabindex="0"
hidden
>
Vote via Fediverse </button>
<div
class="activitypub-modal__overlay"
data-wp-bind--hidden="!context.modal.isOpen"
data-wp-watch="callbacks.handleModalEffects"
role="dialog"
aria-modal="true"
hidden
>
<div class="activitypub-modal__frame">
<div class="activitypub-modal__header">
<h2
class="activitypub-modal__title"
>Remote Vote</h2>
<button
type="button"
class="activitypub-modal__close wp-element-button"
data-wp-on--click="actions.closeModal"
aria-label="Close dialog"
>
<svg fill="currentColor" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
<path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path>
</svg>
</button>
</div>
<div class="activitypub-modal__content">
Original Poll URL (ActivityPub ID)
Your Profile
<div class="polls-for-activitypub-polls__status">
<!-- Voters count -->
<nobr data-wp-text="context.uniqueVotersCountText">
0 votes </nobr>
<span>
·
</span>
<!-- Expiry of poll -->
<time datetime="2026-07-25T07:41:17+00:00" title="2026-07-25T07:41:17+00:00">
<nobr>
6 days left </nobr>
</time>
</div>
</div>
</form>
<!-- Show results – Poll has ended or user has voted -->
<div
hidden data-wp-bind--hidden="context.showVoteForm"
class="polls-for-activitypub-poll__results"
tabindex="-1"
data-wp-ref="results"
aria-labelledby="pfap-results-heading-polls-for-activitypub-poll-2"
>
<div
id="pfap-results-heading-polls-for-activitypub-poll-2"
class="polls-for-activitypub-poll__question"
>
<span class="screen-reader-text">
Poll results for: </span>
Which tool did you use to find this post on the Fediverse? </div>
<ul class="polls-for-activitypub-poll__options">
<!-- Template for rendering of the options -->
<template data-wp-each--option="context.options">
<li class="polls-for-activitypub-poll__option">
<div class="polls-for-activitypub-poll__option-result" aria-hidden="true">
<div class="polls-for-activitypub-poll__option-result-text" >
<span data-wp-bind--hidden="!context.option.voted" class="polls-for-activitypub-poll__voted"><svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" class="icon icon-check polls-for-activitypub-poll__voted__mark" title="You voted for this option" aria-label="You voted for this option" role="img"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"></path></svg></span>
<span data-wp-text="context.option.text" class="polls-for-activitypub-poll__option_text"></span>
<span data-wp-text="context.option.percentage" class="polls-for-activitypub-poll__option-percentage"></span>
</div>
<div class="polls-for-activitypub-poll__tally-bar-cell">
<div class="polls-for-activitypub-poll__tally-bar-bg">
<div data-wp-style--width="context.option.percentage" class="polls-for-activitypub-poll__tally-bar-fg"></div>
</div>
</div>
</div>
<span class="screen-reader-text"
data-wp-text="context.option.accessibleResult">
</span>
</li>
</template>
<!-- Do a server side rendering of the options -->
<li data-wp-each-child class="polls-for-activitypub-poll__option">
<!-- Poll results: tallies for option -->
<div hidden class="polls-for-activitypub-poll__option-result" aria-hidden="true">
<div class="polls-for-activitypub-poll__option-result-text">
<span hidden class="polls-for-activitypub-poll__voted">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" class="icon icon-check polls-for-activitypub-poll__voted__mark" title="You voted for this option" aria-label="You voted for this option" role="img"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"></path></svg>
</span>
<span class="polls-for-activitypub-poll__option_text">Mastodon</span>
<span class="polls-for-activitypub-poll__option-percentage">
0% </span>
</div>
<div class="polls-for-activitypub-poll__tally-bar-cell">
<div class="polls-for-activitypub-poll__tally-bar-bg">
<div class="polls-for-activitypub-poll__tally-bar-fg" style="width:0%;"></div>
</div>
</div>
</div>
<span class="screen-reader-text">
Mastodon, , 0 votes, 0 ^ percent </span>
</li>
<li data-wp-each-child class="polls-for-activitypub-poll__option">
<!-- Poll results: tallies for option -->
<div hidden class="polls-for-activitypub-poll__option-result" aria-hidden="true">
<div class="polls-for-activitypub-poll__option-result-text">
<span hidden class="polls-for-activitypub-poll__voted">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" class="icon icon-check polls-for-activitypub-poll__voted__mark" title="You voted for this option" aria-label="You voted for this option" role="img"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"></path></svg>
</span>
<span class="polls-for-activitypub-poll__option_text">WordPress</span>
<span class="polls-for-activitypub-poll__option-percentage">
0% </span>
</div>
<div class="polls-for-activitypub-poll__tally-bar-cell">
<div class="polls-for-activitypub-poll__tally-bar-bg">
<div class="polls-for-activitypub-poll__tally-bar-fg" style="width:0%;"></div>
</div>
</div>
</div>
<span class="screen-reader-text">
WordPress, , 0 votes, 0 ^ percent </span>
</li>
<li data-wp-each-child class="polls-for-activitypub-poll__option">
<!-- Poll results: tallies for option -->
<div hidden class="polls-for-activitypub-poll__option-result" aria-hidden="true">
<div class="polls-for-activitypub-poll__option-result-text">
<span hidden class="polls-for-activitypub-poll__voted">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" class="icon icon-check polls-for-activitypub-poll__voted__mark" title="You voted for this option" aria-label="You voted for this option" role="img"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"></path></svg>
</span>
<span class="polls-for-activitypub-poll__option_text">Ghost</span>
<span class="polls-for-activitypub-poll__option-percentage">
0% </span>
</div>
<div class="polls-for-activitypub-poll__tally-bar-cell">
<div class="polls-for-activitypub-poll__tally-bar-bg">
<div class="polls-for-activitypub-poll__tally-bar-fg" style="width:0%;"></div>
</div>
</div>
</div>
<span class="screen-reader-text">
Ghost, , 0 votes, 0 ^ percent </span>
</li>
<li data-wp-each-child class="polls-for-activitypub-poll__option">
<!-- Poll results: tallies for option -->
<div hidden class="polls-for-activitypub-poll__option-result" aria-hidden="true">
<div class="polls-for-activitypub-poll__option-result-text">
<span hidden class="polls-for-activitypub-poll__voted">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" class="icon icon-check polls-for-activitypub-poll__voted__mark" title="You voted for this option" aria-label="You voted for this option" role="img"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"></path></svg>
</span>
<span class="polls-for-activitypub-poll__option_text">Self-Hosted Account</span>
<span class="polls-for-activitypub-poll__option-percentage">
0% </span>
</div>
<div class="polls-for-activitypub-poll__tally-bar-cell">
<div class="polls-for-activitypub-poll__tally-bar-bg">
<div class="polls-for-activitypub-poll__tally-bar-fg" style="width:0%;"></div>
</div>
</div>
</div>
<span class="screen-reader-text">
Self-Hosted Account, , 0 votes, 0 ^ percent </span>
</li>
<li data-wp-each-child class="polls-for-activitypub-poll__option">
<!-- Poll results: tallies for option -->
<div hidden class="polls-for-activitypub-poll__option-result" aria-hidden="true">
<div class="polls-for-activitypub-poll__option-result-text">
<span hidden class="polls-for-activitypub-poll__voted">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" class="icon icon-check polls-for-activitypub-poll__voted__mark" title="You voted for this option" aria-label="You voted for this option" role="img"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"></path></svg>
</span>
<span class="polls-for-activitypub-poll__option_text">Friendica</span>
<span class="polls-for-activitypub-poll__option-percentage">
0% </span>
</div>
<div class="polls-for-activitypub-poll__tally-bar-cell">
<div class="polls-for-activitypub-poll__tally-bar-bg">
<div class="polls-for-activitypub-poll__tally-bar-fg" style="width:0%;"></div>
</div>
</div>
</div>
<span class="screen-reader-text">
Friendica, , 0 votes, 0 ^ percent </span>
</li>
<li data-wp-each-child class="polls-for-activitypub-poll__option">
<!-- Poll results: tallies for option -->
<div hidden class="polls-for-activitypub-poll__option-result" aria-hidden="true">
<div class="polls-for-activitypub-poll__option-result-text">
<span hidden class="polls-for-activitypub-poll__voted">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" class="icon icon-check polls-for-activitypub-poll__voted__mark" title="You voted for this option" aria-label="You voted for this option" role="img"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"></path></svg>
</span>
<span class="polls-for-activitypub-poll__option_text">Other</span>
<span class="polls-for-activitypub-poll__option-percentage">
0% </span>
</div>
<div class="polls-for-activitypub-poll__tally-bar-cell">
<div class="polls-for-activitypub-poll__tally-bar-bg">
<div class="polls-for-activitypub-poll__tally-bar-fg" style="width:0%;"></div>
</div>
</div>
</div>
<span class="screen-reader-text">
Other, , 0 votes, 0 ^ percent </span>
</li>
</ul>
<div class="polls-for-activitypub-poll__footer">
<!-- Refresh button -->
<div class="polls-for-activitypub-poll__button-container" data-wp-bind--hidden="context.showVoteForm">
<button
class="polls-for-activitypub-poll__button wp-element-button wp-block-button__link"
data-wp-on-async--click="actions.refresh"
>
Refresh </button>
</div>
<div class="polls-for-activitypub-polls__status">
<!-- Voters count -->
<nobr data-wp-text="context.uniqueVotersCountText">
0 votes </nobr>
<span>
·
</span>
<!-- Expiry of poll -->
<time datetime="2026-07-25T07:41:17+00:00" title="2026-07-25T07:41:17+00:00">
<nobr>
6 days left </nobr>
</time>
</div>
</div>
</div>
Featured Item(s)
The Grumpy Welshman writes:
Gareth’s been in a mood all week.
Turns out it started with a hosting bill. Not his own, mind. He doesn’t have a website. Gareth thinks websites are for people who’ve run out of pub to shout in. But he heard about someone switching platforms, and it set him off on one of his tangents, the kind that starts with “you know what really gets me” and ends forty minutes later with him accusing a cookie banner of moral cowardice.
Apparently someone had moved from a platform that wanted to squeeze money out of their audience to one that just let them publish words on a page, and Gareth treated this as evidence that civilisation might not be completely dead after all.
So here’s Gareth, unedited, more or less.
The Internet Doesn’t Want Readers. It Wants Livestock.
My name is not Gareth, BTW. 😉
The 19th reports:
After losing their jobs at NOAA, Rebecca Lindsey, her sister and another colleague teamed up to rebuild a pivotal resource the Trump administration took offline.
Trump dismantled a federal climate website. These women rebuilt it.
Now this is building something for a community.
Here’s another one:
CMSs
Faircamp announces:
Faircamp 2.0 is now feature complete
Ver Vert demonstrates:
Publishing a Zola Blog to AT Protocol with Sequoia and wisp.place
Opus explores:
Blogging with Bluesky The Atmosphere and ATProtocol
I fixed their headline.
Leaflet
Leaflet Lab Notes announces:
Publication pages and nav, for Leaflet as…website builder?
Ghost
Ghost says:
Optimize your site for AI search
Um. Fuck no.
Subaud shows us what’s involved with:
Making a Ghost Blog a Valid standard.site Publication
So, definitelty not KISS. You could more easily re-post to a ATProto blog and list the Ghost URL as canonical. That’s what we do.
Magic Pages announces:
Staging Sites: Test Big Changes Before They Go Live
Its owner, Jannis Fedoruk-Betschki shares:
The Cost of Copying Things That Haven’t Changed
Spectral Web Services announces:
Institutional access to Ghost now included with SWS Tools!
Build Awesome
Build Awesome announces:
A new Build Awesome (Eleventy) alpha is available for testing
Tools
Tuta shares the:
Best Amazon alternatives in 2026
Lauti shows us:
BTW, Lauti is built into Bonfire.
Speaking of community tech, I found out about Karrot this week:
OMN says:
Online Chat is a social problem, not just a technical one
Signal announces:
Signal is now available on Android tablets
Signal allows Android phones to be linked as secondary devices (beta)
Browsers
Betweeen Two Firewalls explores:
Manifest v3: Why It Is Time To Leave Chromium/Chrome/Edge
The time was years ago. But better late than never.
Creative
Simple Tech Guides shows us how to:
Self-host Immich for photo backup: migrating off Google Photos
Linux / Open Android
Linux Magazine starts a series:
Changing the Chip Industry: How Public Investment Has Grown Open Silicon
This week’s featured OMN tool
GIMP
Say bye to Photoshop with GIMP, an open source image editor.
Programming
Evangelos Paterakis shares:
Democratizing Abandonware; I’m not digging through this cemetery
Git
Forgejo announces:
Forgejo 15.0.5 was just released!
How to Geek explores:
Why developers are ditching GitHub for Codeberg and self-hosting alternatives
CSS
Master.dev examines:
In-N-Out Animation using sibling-index()
W3C announces:
CSS Linked Parameters Module Level 1
Carmen Ansio demonstrates:
Setting type like a printed page
AI
Samir Talwar has:
No shit, but this is a great article.
The Freedom of the Press Foundation reports:
The ‘s’ in LLM stands for ‘security’
Smashing Frames says:
Unfortunately, most programmers are amoral shits.
Other
OpenProject explores:
From Jira to OpenProject: choosing the right migration strategy for your organization
This week’s featured programming tool
HTMX
Access to AJAX, CSS Transitions, WebSockets and SSE directly in HTML.
ActivityPub
Robin Berjon ponders running:
This may be somewhat similar to what holos.social is attempting.
Fabio Manganiello announces a:
Dhole Moments explains:
The Long Tail of Work Left Until ActivityPub Has E2EE
This week’s featured ActivityPub featured tool
Holos Discover
HolosDiscover is a search engine dedicated to the Fediverse.
Permanent aside here (unfortunately)
This is a perpetual pet peeve because many people aren’t able to comprehend ⬇️:
- The Fediverse is for communities (private, semi-private, formal, informal, or otherwise)
- and the Atmosphere is for the masses (unwashed, washed, or otherwise).
- And Corporate social media is for naive fools and intentional cunts.
Also, you can avoid surveillance on the Fediverse with some effort (and choosing the correct tools) but not on the Atmosphere (permissioned spaces not withstanding).
So, recognize their natures and don’t ask the two protocols to go against them. This is also why we have accounts on both platforms and use them differently.
Fediverse
Arxiv looks at:
The Politics Attention Makes: Platform Media Logic and the Mediatization of Politics
Per Axom notes:
It’s hard to search and find messages across the Fediverse. This is a good thing.
It is. See the second point directly above.
Tuiter Rocks explains:
Cómo funciona la moderación en Mastodon: qué ve un admin y qué herramientas tiene
Federated Minds concludes a series:
Forums, Reading, and Music on the Fediverse
Eilertsens Kodenknekkeri announces a:
Superblock v3.1 addon for Hubzilla
Framasoft announces:
We just released version 2.2.0 of the PeerTube app!
FitPub announces:
Bonfire
The Phoenix Framework shares:
A deep dive into HEEx compilation from LiveView 1.2
More
Protocols for Publishers says:
“Build protocols, not platforms”
SneakerWeb explains:
The sneakerweb is a peer-to-peer protocol for web publishing without permission
Quite interesting, but probably not easy.
Hamish Campbell has:
Matrix
Matrix shares:
This Week in Matrix 2026-07-10
Continuwuity announces:
Continuwuity 26.6.0, the lightweight Matrix chat server, is finally out!
RSS
Coywolf reports:
XMPP
Movim announces:
Other Federated Social Media
ATProto shares:
Hmmm.
The Tropopause pontificates:
On Atproto and Atmospheric Groups
Steve Klabnik has:
Bluesky announces:
Creating an Independent Public Ledger of Credentials (PLC) Directory Organization
This is a rare non-techbro-ish move by Bluesky.
The Digital Renaissance opines:
Bluesky Is Not The Center of The Atmosphere
Actually, it’s not the center of ATProto tools, but still 80+% of the Atmosphere.
Tech Policy Press reports:
Europe’s W Social Bet Tests its Vision of Digital Sovereignty
Looks like Dubya was not only birthed by clueless shits but for them as well. Fuck politicians.
Here’s example number 416 of why:
IYKYK.
Meanwhile, Eurosky announces:
Eurosky is collaborating with SPRIND to test a non-toxic algorithm for the first time
Next shares:
Un réseau social européen ? On est passé de Bluesky à Mu.social, et on vous explique
Augment explores:
Jeremy Herve asks:
Is my ATProto app actually decentralized?
Inputs and Outputs has a journalists on the Atmosphere list for you:
You are what you read, watch, and listen to ..
CTAs
- That’s it for this week. Please share The Programmer’s Fulcrum.
- Follow us on Surf or at @thefulcrum@thefulcrum.dev on the Fediverse or at @thefulcrum.eurosky.social on ATProto for daily coverage.
- Read, live, and share The Techno Anarchist Manifesto!
And please build something for a community! We’re nurturing Manade.
Blasts from the past
Did you enjoy this article?
Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.