No description
  • PHP 87.3%
  • JavaScript 6.8%
  • CSS 4.5%
  • Makefile 1.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Steffen Rörtgen 70fa601ee5 docs: add a README, and relicense to AGPL-3.0-or-later
The repo had no front page and no LICENSE file, only a licence line in each
plugin header. The README covers what the four plugins do, installing and
configuring them from a release zip, the shortcodes and blocks, how the
caching behaves, and the monorepo's build/test/release workflow.

The licence moves from GPL-2.0-or-later to AGPL-3.0-or-later: the full text
is now in LICENSE, and the plugin headers and composer.json files declare it
so the terms are explicit rather than implied.

Also corrects the command list in CLAUDE.md, which named a 'make install'
and 'make composer' that do not exist; the real entry points are 'make dev'
and 'make vendor', and Composer runs on the host, not in the container.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PUfRERPMzfFbD5ytdEUcja
2026-09-18 14:24:43 +02:00
amb-nostr docs: add a README, and relicense to AGPL-3.0-or-later 2026-09-18 14:24:43 +02:00
demo chore(dev): make demo — local ALPIKA showcase with the new blocks 2026-09-14 08:17:15 +02:00
docs fix(shared): salt block output caches with the community definition + roster version 2026-09-17 08:32:37 +02:00
longform-nostr docs: add a README, and relicense to AGPL-3.0-or-later 2026-09-18 14:24:43 +02:00
nostr-calendar docs: add a README, and relicense to AGPL-3.0-or-later 2026-09-18 14:24:43 +02:00
nostr-publish docs: add a README, and relicense to AGPL-3.0-or-later 2026-09-18 14:24:43 +02:00
shared docs: add a README, and relicense to AGPL-3.0-or-later 2026-09-18 14:24:43 +02:00
.gitignore build: make dist packages self-contained plugin zips; version 0.2.0 2026-09-14 15:27:00 +02:00
CLAUDE.md docs: add a README, and relicense to AGPL-3.0-or-later 2026-09-18 14:24:43 +02:00
docker-compose.yml refactor: split single plugin into a 5-module monorepo 2026-07-29 12:48:18 +02:00
LICENSE docs: add a README, and relicense to AGPL-3.0-or-later 2026-09-18 14:24:43 +02:00
Makefile build: make dist packages self-contained plugin zips; version 0.2.0 2026-09-14 15:27:00 +02:00
README.md docs: add a README, and relicense to AGPL-3.0-or-later 2026-09-18 14:24:43 +02:00

WordPress Nostr plugins

Four WordPress plugins for the Nostr protocol. Three of them pull educational content from relays and render it on a site: learning resources, long-form articles and calendar events. The fourth publishes WordPress posts back to a relay.

They were built for the ALPIKA working groups and the edufeed ecosystem, but nothing in them is site-specific. Point them at a relay and they work.

Plugin What it shows Nostr kinds
amb-nostr Educational resources described with AMB metadata, with search and faceted filters 30142
longform-nostr Long-form articles with tag and article routes 30023 (NIP-23)
nostr-calendar Calendar events as a list, cards or a month grid 31922 / 31923 (NIP-52)
nostr-publish Publishes WordPress posts as Nostr events —

shared/ is a small library the four depend on: relay communication, caching, NIP-19 encoding, community access rules, Markdown and template lookup.

Installing

Download the zips from the latest release and install each one through Plugins → Add New → Upload Plugin. The zips are self-contained: they carry their dependencies and compiled block assets, so a git checkout is not installable on its own.

To update later, upload the new zip for a plugin that is already installed and choose "Replace current with uploaded". Settings and content are kept. With WP-CLI:

wp plugin install amb-nostr-0.2.5.zip --force

Install nostr-publish only where writing to a relay is actually wanted.

After a first install

  1. Settings → Permalinks → Save once, so the detail routes work.
  2. Settings → Nostr Relays: the relay list, cache behaviour and the relays used for profiles and communities. This page is shared by all four plugins.
  3. Each plugin adds its own settings page (AMB Nostr, Longform Nostr, Nostr Calendar, Nostr Publish) for display defaults and its route slug.

Detail pages live under /materialien/, /articles/ and /veranstaltungen/ by default; each slug is configurable.

Requirements

  • PHP 8.2 or newer with gmp, mbstring, openssl and sockets
  • WordPress 6.8 or newer
  • Outbound WebSocket connections from PHP to the relays (wss://…:443)

Search, community filters and date filters need a relay that understands them. The default, wss://amb-relay.edufeed.org, does; plain strfry relays reject those queries and will simply return nothing.

Using the plugins

Every list is available both as a block (category "Widgets", all prefixed edufeed/) and as a shortcode:

[amb_nostr limit="6" search="Frieden"]
[amb_nostr_search filters="resourceType,level" button="Suche"]
[longform_nostr limit="3" tags="ki,unterricht"]
[nostr_calendar view="month"]

The attributes are shared across the plugins wherever they mean the same thing: community, authors, tags, search, since, until, relays, limit and cache. community takes one or more npubs, comma-separated, and shows the content of all of them together.

Every template under a plugin's templates/ directory can be overridden from a theme by copying it to your-theme/<plugin-name>/<template>.php.

A German guide for editors building topic pages is in docs/editor-guide-themen.md.

Caching

Relay responses are cached, because querying a relay on every page view is slow. Two settings under Settings → Nostr Relays control this:

  • Cache TTL is how long a cached block may be used at all.
  • Aktualisierungsintervall is the shorter interval after which a block is still served instantly but refreshed in the background, so new relay content appears without anyone waiting for it.

The background refresh runs through WP-Cron, which needs site traffic to fire. On a quiet site the first visitor after a pause still sees the previous state and the next one sees the new. Cache leeren on the same settings page, or wp nostr cache-flush, clears everything immediately.

Developing

The repository is a monorepo. Each plugin depends on shared/ through a Composer path repository, so vendor/ and build/ are gitignored and a checkout has to be built before it will run.

make dev           # everything: dependencies, containers, WordPress, demo pages
make npm-install   # node dependencies for the block builds
make build         # compile the Gutenberg blocks
make test          # PHPUnit across all packages

make dev is idempotent and safe to re-run. It leaves a WordPress at localhost:8080 with the plugins active and a few demo pages, and prints the credentials at the end. It does not touch the block assets, so run make npm-install and make build as well before using the block editor. Without them the shortcodes still work and the blocks quietly do not register.

The pieces are available on their own too: make vendor (Composer for every package), make up / make down / make logs (containers), make wp CMD="..." (WP-CLI), and make watch to rebuild blocks on change (PKG=<plugin>, default amb-nostr). Composer runs on the host through nix-shell, not in the container, because the WordPress image ships neither Composer nor the gmp extension that the Nostr library needs.

make demo rebuilds a fuller showcase site, which is the quickest way to see every block at once.

Layout

Each plugin follows the same shape:

<plugin>/
  <plugin>.php      bootstrap: constants, autoloader, component registration
  src/              PSR-4 classes: Settings, Shortcode, Block, Parser, Renderer
  src/blocks/       Gutenberg block sources (JSX)
  build/blocks/     compiled block assets (gitignored)
  templates/        PHP templates, overridable by themes
  assets/           frontend CSS and JS

Hooks are registered on plugins_loaded. All relay traffic goes through Edufeed\WpNostrShared\NostrFetcher, and all block caching through Edufeed\WpNostrShared\BlockCache.

Releasing

make dist

builds one self-contained zip per plugin into dist/, with production dependencies, a real copy of shared/ and the compiled blocks. Bump the version in the plugin header and the matching *_VERSION constant first, then tag v<version> and attach the zips to a release. The full procedure, including deployment to a live site, is in docs/deploy.md.

Behaviour changes that are easy to miss when upgrading an existing site are recorded in docs/upgrade-notes.md.

Licence

AGPL-3.0-or-later. See LICENSE.