Adds IndieWeb support to any Qbix app. Depends only on Q core. Optional hooks for Streams/Users/Communities when available.
📁 Zero database — all data stored as JSON files under files/IndieWeb/.
- 🔗 Webmention (Jan 2017) — send and receive cross-site mentions
- ✏️ Micropub (May 2017) — create/edit content via API (fires Q event)
- 📡 WebSub (Jan 2018) — real-time feed update notifications
- 🏷️ microformats2 — h-card, h-entry, h-feed, rel-me
- 🔑 IndieAuth — decentralized identity/auth
- 📰 RSS/Atom feed generation — automatically derived from h-entry HTML using Q_Snapshot for change detection (no parallel content model)
- 🔁 POSSE helpers — syndication URL tracking, backfeed via Bridgy
┌─────────────────────────┐
│ Q (core) │
│ routes, events, views, │
│ tools, Q_Snapshot │
└──────────┬──────────────┘
│ depends on
┌──────────┴──────────────┐
│ IndieWeb plugin │
│ │
│ 🔗 Webmention send/recv │
│ 🏷️ microformats2 helpers│
│ 📰 Feed generation │
│ 🔑 IndieAuth server │
│ ✏️ Micropub server │
│ 📡 WebSub notification │
│ 📁 File-based storage │
└──────────┬──────────────┘
│ optional hooks
┌────────────────┼────────────────┐
│ │ │
┌─────┴─────┐ ┌──────┴──────┐ ┌──────┴───────┐
│ Streams │ │ Users │ │ Communities │
│ mentions │ │ IndieAuth │ │ h-card from │
│ → messages│ │ identity │ │ profile │
└────────────┘ └─────────────┘ └──────────────┘
All data stored as JSON files under files/IndieWeb/:
files/IndieWeb/
📥 webmentions/ ← received webmentions
{target-hash}/
{source-hash}.json ← one file per mention
📤 outbox/ ← queued outbound mentions
{hash}.json
✅ sent/ ← completed sends
{hash}.json
🔍 endpoints/ ← cached endpoint discovery
{domain-hash}.json
Why files instead of MySQL? IndieWeb traffic is low-volume — a personal
site receives a few dozen webmentions a day. glob() on a directory of
JSON files is as fast as a database query at this scale, and eliminates
the MySQL/SQLite dependency entirely.
IndieWeb/
📦 classes/
IndieWeb.php ← main class (hCard, hEntry, contentChanged)
IndieWeb/
Feed.php ← RSS 2.0 / Atom 1.0 generator
Http.php ← synchronous curl client
Parse.php ← mf2 microformats parser wrapper
Store.php ← file-based JSON storage
⚙️ config/
plugin.json ← routes, events, dependencies
🎯 handlers/
IndieWeb/
before/Q_response.php ← injects <link> headers on every page
webmention/post.php ← receives webmentions
feed/response/content.php ← serves RSS/Atom feeds
📜 scripts/
IndieWeb/
feeds.php ← rebuild feed cache (uses Q_Snapshot)
🚀 deploy/
Caddyfile, nginx.conf, .htaccess ← server configs
DEPLOYMENT.md ← deployment guide
📝 Content published (or static.php runs)
│
▼
IndieWeb::contentChanged($url, $html)
│
├── 🔍 Q_Snapshot::update($url, $hash)
│ └── stores hash, detects change
│
├── 📤 IndieWeb::queueMentions($url, $html)
│ └── scans for external links
│ discovers endpoints
│ queues in files/IndieWeb/outbox/
│
└── 📡 IndieWeb_WebSub::notifyHub()
└── POST to configured hub URL
GET /feed/rss or /feed/atom
│
▼
include(APP_CONFIG_DIR/IndieWeb/feeds.php)
│ (instant — cached by Q_Snapshot)
▼
flatten entries, sort by published
│
▼
📰 IndieWeb_Feed::rss() or ::atom()
│
▼
XML output
{
"Q": {
"plugins": ["IndieWeb"],
"routes": {
"feed/:format": { "module": "IndieWeb", "action": "feed" },
"feed/rss": { "module": "IndieWeb", "action": "feed", "format": "rss" },
"feed/atom": { "module": "IndieWeb", "action": "feed", "format": "atom" },
"webmention": { "module": "IndieWeb", "action": "webmention" }
},
"handlersBeforeEvent": {
"Q/response": ["IndieWeb/before/Q_response"]
}
},
"IndieWeb": {
"identity": {
"name": "Your Name",
"url": "https://yourdomain.com",
"photo": "/img/avatar.jpg"
},
"webmention": {
"endpoint": "/webmention"
},
"feeds": {
"htmlDir": null
},
"hub": null
}
}When the Streams plugin is available, the IndieWeb plugin can hook into stream events to automatically send webmentions when content is published:
// In handlers/Streams/after/Streams_save.php
function IndieWeb_after_Streams_save($params)
{
$stream = $params['stream'];
$url = $stream->url();
$html = $stream->renderForIndieWeb();
IndieWeb::contentChanged($url, $html);
}| Feature | Q only | + Streams | + Users | + Communities |
|---|---|---|---|---|
| 🏷️ h-card markup helper | ✓ manual | ✓ auto | ✓ auto | ✓ auto + social |
| 📝 h-entry markup helper | ✓ manual | ✓ auto | ✓ auto | ✓ auto |
| 📥 Webmention receive | ✓ JSON files | ✓ → messages | ✓ | ✓ |
| 📤 Webmention send | ✓ | ✓ on save | ✓ | ✓ |
| 📰 RSS/Atom feeds | ✓ | ✓ auto | ✓ | ✓ |
| 🔗 rel-me links | ✓ config | ✓ | ✓ | ✓ from profiles |
| 🔑 IndieAuth | ✓ single | ✓ | ✓ multi | ✓ |
| ✏️ Micropub | ✓ fires event | ✓ creates stream | ✓ | ✓ |
| 📡 WebSub | ✓ | ✓ | ✓ | ✓ |
- 🧩 mf2/mf2 (MIT) — PHP microformats2 parser, ~300KB, no dependencies beyond ext-dom. Used for both inbound (parsing webmentions) and outbound (parsing own HTML for feed generation).
- 🔄 Q_Snapshot (Q core) — the unified hash/snapshot/diff engine, shared with urls.php