Skip to content

F.2: WriteFreely bundle (federated long-form blog)#11

Open
kh0pper wants to merge 1 commit intof1-gotosocial-bundlefrom
f2-writefreely-bundle
Open

F.2: WriteFreely bundle (federated long-form blog)#11
kh0pper wants to merge 1 commit intof1-gotosocial-bundlefrom
f2-writefreely-bundle

Conversation

@kh0pper
Copy link
Copy Markdown
Owner

@kh0pper kh0pper commented Apr 12, 2026

Summary

Second federated app, stacked on F.1. WriteFreely is the minimalist publish-oriented ActivityPub server — single-binary, single-SQLite footprint, no comment system, no likes, no moderation queue. Ideal for long-form writing that federates to Mastodon / GoToSocial followers. Complements GoToSocial (microblog) and Crow's own private `crow-blog` (non-federated).

Stacked on #10 (F.1). Merge order: #9#10 → this.

What ships

Bundle (`bundles/writefreely/`)

  • `manifest.json` — `consent_required` with EN/ES (narrower blast radius than GTS because WF doesn't moderate remote content). `min_ram_mb: 256`, `recommended: 512` — the lightest federated bundle; Pi-eligible on every tier. `requires.bundles: ["caddy"]`
  • `docker-compose.yml` — pinned `writeas/writefreely:0.15`, joins `crow-federation`, no host port publish, SQLite default. Entrypoint seeds `config.ini` on first boot + runs `--init-db` / `--gen-keys` once so the container boots clean from a fresh volume
  • `server/server.js` — 10 MCP tools: `wf_status`, `wf_list_collections`, `wf_create_post`, `wf_update_post`, `wf_publish_post`, `wf_unpublish_post`, `wf_delete_post`, `wf_list_posts`, `wf_get_post`, `wf_export_posts`. Content + publish verbs wrapped with the F.0 shared rate limiter (same installed-mode fallback as GTS)
  • `skills/writefreely.md` — triggers, draft→publish workflow, single-user mode shortcut, Caddy expose recipe, explicit "what WriteFreely doesn't do" section (no comments / likes / moderation) to prevent tool confusion
  • `panel/` — status + collections chip list + recent posts preview, XSS-safe
  • `scripts/` — `backup.sh` (online sqlite backup + keys tar, with warning that actor keys don't transfer across domains), `post-install.sh` (next-step output)

Platform wiring

  • `registry/add-ons.json` — writefreely entry under `federated-social` category (introduced in F.1)
  • `skills/superpowers.md` — EN/ES trigger row
  • `CLAUDE.md` — Skills Reference entry

Design notes

  • No moderation queue — intentional. WriteFreely publishes outbound; inbound federation is limited to follow events. The plan's full moderation taxonomy (`block_domain` / `defederate` / `import_blocklist`) doesn't fit WF. The skill explicitly calls this out so the AI doesn't reach for tools that don't exist
  • First-run admin account is web-only — WriteFreely has no CLI bootstrap for the initial admin. `post-install.sh` calls this out in the next-step output. The operator creates the account via the first-run web form, then generates an API token via `POST /api/auth/login` and pastes into `.env`
  • Actor signing keys are per-domain — backup warns that restoring to a new domain breaks federation identity. Remote servers identify by `{host, actor_key}` and treat a changed host as a different actor

Test plan

  • `node --check` on all changed files
  • MCP server boots via `createWritefreelyServer()` with lazy shared-dep fallback
  • `docker compose -f bundles/writefreely/docker-compose.yml config` parses
  • `registry/add-ons.json` is valid JSON (gotosocial + writefreely both present)
  • Live: install WriteFreely after F.1 is merged → `caddy_add_federation_site` → web first-run creates admin → API token → `wf_create_post` + `wf_publish_post` → post appears on the collection page at `https://blog.example.com//`
  • Live: follow the blog from a Mastodon account → publish a post → verify it arrives on the Mastodon timeline
  • Live: rate-limit check — `wf_create_post` 11× rapidly, 11th returns `rate_limited`

Second federated app, stacked on F.1 (GoToSocial). WriteFreely is the
minimalist publish-oriented ActivityPub server — single-binary,
single-SQLite-file, no comment system, no likes, no moderation queue.
Ideal for long-form writing that federates to Mastodon / GoToSocial
followers. Complements GoToSocial (microblog) and Crow's own private
crow-blog (non-federated).

Bundle (bundles/writefreely/):

- manifest.json  consent_required: true with EN/ES blast-radius text
                 (narrower than GTS because WF doesn't moderate remote
                 content). min_ram_mb=256, recommended=512. Lightest of
                 the federated bundles; Pi-eligible on any tier
- docker-compose.yml  pinned writeas/writefreely:0.15, joins crow-
                 federation, no host port publish, SQLite default.
                 Entrypoint seeds config.ini on first boot + runs
                 --init-db / --gen-keys once so the container boots
                 clean from a fresh volume
- server/server.js  10 MCP tools:
                   wf_status, wf_list_collections,
                   wf_create_post, wf_update_post, wf_publish_post,
                   wf_unpublish_post, wf_delete_post,
                   wf_list_posts, wf_get_post, wf_export_posts
                 Content + publish verbs wrapped with the shared rate
                 limiter (same try/catch fallback for installed-mode
                 as the GTS bundle). No moderation queue — WF doesn't
                 moderate remote content; that's intentional per the
                 upstream design and the plan's "not every bundle
                 needs the full moderation taxonomy" note
- skills/writefreely.md  triggers, draft→publish workflow, single-
                 user mode shortcut, Caddy expose recipe, explicit
                 "what WriteFreely doesn't do" section to avoid tool
                 confusion (no comments, no likes, no moderation)
- panel/  status (instance, auth, collections chip list) + recent
                 posts from the default collection. XSS-safe (text
                 Content / createElement only)
- scripts/  backup.sh (online sqlite-backup + keys+config tar with
                 warning that actor keys don't transfer across
                 domains), post-install.sh (next-step output)

Platform wiring:

- registry/add-ons.json  writefreely entry, federated-social category
- skills/superpowers.md  EN/ES trigger row
- CLAUDE.md  Skills Reference entry

Verified:

- node --check on all changed files
- MCP server boots via createWritefreelyServer()
- docker compose config parses
- registry JSON validates
- Branch stacked correctly on f1-gotosocial-bundle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant