Skip to content

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.

Which tool did you use to find this post on the Fediverse?
Mastodon WordPress Ghost Self-Hosted Account Friendica Other
<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)

Copy and paste the ActivityPub ID of this poll into the search field of your favorite fediverse app or server.

Your Profile

Or, if you know your own profile, we can start things that way!
Vote Loading…
Save my profile for future interactions.
<div class="polls-for-activitypub-polls__status"> <!-- Voters count --> <nobr data-wp-text="context.uniqueVotersCountText"> 0 votes </nobr> <span> &middot; </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> &middot; </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:

GainForest App


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

Back to top 👆🏼


Tools

Tuta shares the:

Best Amazon alternatives in 2026

Lauti shows us:

How to Community Calendar!?!

BTW, Lauti is built into Bonfire.

Speaking of community tech, I found out about Karrot this week:

Karrot

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.

GIMP

Back to top 👆🏼


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:

LLMs can’t program

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:

“Useful” is not sufficient

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.

HTMX

Back to top 👆🏼


ActivityPub

Robin Berjon ponders running:

ActivityPub Over ATProto

This may be somewhat similar to what holos.social is attempting.

Fabio Manganiello announces a:

New Akkoma feature

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.

Holos Discover

Back to top 👆🏼


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:

FitPub 1.2.0 is here!

Bonfire

The Phoenix Framework shares:

A deep dive into HEEx compilation from LiveView 1.2

Back to top 👆🏼


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:

A hybrid p2p look at the OMN

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:

You can now chat using RSS

XMPP

Movim announces:

The next Movim release comes with a special surprise: a fully integrated SFU service, powered by Galene

Other Federated Social Media

ATProto shares:

AT Protocol Trademark

Hmmm.

The Tropopause pontificates:

On Atproto and Atmospheric Groups

Steve Klabnik has:

Too many words about DIDs

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:

Hi Eugen

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:

Moats & Drawbridges

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

And please build something for a community! We’re nurturing Manade.


Blasts from the past

Previous Battalion Posts

Previous Symfony Station Posts

Did you enjoy this article?

Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.

Across the AtmosphereDiscussions