wiki-plugin-agora
v0.0.59
Published
Multi-tenant digital goods agora for federated wiki, powered by Sanora
Maintainers
Readme
Agora
In Ancient Athens, the Agora was not just a marketplace, but a place for meeting friends and family, for socializing, for contemplating the world's problems, and should one be bold enough, attempting to solve them. The world of Amazon and Google may be called a marketplace, but it is anything but. More accurately it's a trap, one that, like the web itself, collects the unsuspecting, and sticks them in a matrix of low-invention, low-competition, and no-connection.
Agora is an attempt to unwind this.
Overview
In 2026, eCommerce is a well-known and well-established entity. You put some digital representations of goods and services online, connect them to a payment processor, do some post-purchase stuff like shipping and receipts, and you're done. This is why most eCommerce offerings: Wordpress (still the largest platform on the web), Shopify, Wix, Gumroad, etc. start with a free offering.
But no one's going to find your well-honed eCommerce site amongst the 1.34 billion websites on the internet. That part's called Discovery. To become discoverable, you've got to market.
And marketing is how they get ya.
In the very early days of the internet, I'm talking before the web, you had the same problem, not because there were too many sites, but because there just wasn't a way to find them period. I remember a friend handing me a scrap of paper with some sixty character incomprehensible URL on it to type into my prehistoric AOL "browser."
But at that site, oh! Imagine, if you will, some gorgeously curated set of links to the cultural motherlode of your heart. Imagine the love and care that went into some single treasure hunter putting together this site, with no mind towards recompense, just so that their fellow metal-, romance-, astrology-, dnd-lovers could find their people and content online. For a brief glorious moment in history, this is how finding things online worked.
Then the "engines" showed up, and the John Henries of the early internet faded into lore.
But the engines are run by men, and men are mired in hubris. Over time they've found it's cheaper to tell you what you want to find, rather than finding for you what you want. And Dodge v Ford has ensured that that erosion of user experience just gets a constant fuel injection.
In the early days, to help with discovery, sites would band together into "web rings." They'd link to each other, and you could browse them one by one. It was primitive, but these were the earliest federations.
Our technology has come a looooong way since those days. Our discovery has not.
That is the mission of Agora. To leverage the federation for discovery, and have it be so easy that you don't even notice.
Archive Format
An agora is published by dragging a ZIP file onto the plugin widget. The ZIP must contain a manifest.json at the root, plus any content subfolders.
my-agora.zip
manifest.json
books/
music/
posts/
photos/
products/
appointments/
subscriptions/
bio/manifest.json Reference
Required fields
| Field | Type | Description |
|-------|------|-------------|
| uuid | string | Your tenant UUID, issued at registration |
| emojicode | string | Your 8-emoji identifier, issued at registration |
| name | string | Display name shown in the page title and emails |
Identity & SEO
| Field | Type | Description |
|-------|------|-------------|
| description | string | One-sentence description used in og:description and <meta name="description">. Auto-generated from available sections if omitted. |
| keywords | string[] | Stored as product tags and rendered as <meta name="keywords"> |
| email | string | Tenant notification address. Receives an email for every purchase, booking, subscription, newsletter signup, and contact form submission. |
Appearance
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| lightMode | boolean | false | Switch the entire page to light mode (white cards, #f5f5f7 background). The music player bar is always dark regardless. |
| sections | string[] | all | Controls which tabs appear and in what order. Valid values: "books", "music", "posts", "photos", "products", "appointments", "subscriptions". |
Creator profile
| Field | Type | Description |
|-------|------|-------------|
| bio.name | string | Creator name shown above the home grid |
| bio.title | string | Role or tagline beneath the name |
| bio.description | string | Short bio text (max 2048 characters) |
The bio photo is read from a bio/ subfolder in the archive (first image found, up to 1024×1024 px).
Home tab extras
| Field | Type | Description |
|-------|------|-------------|
| newsletter | boolean | Adds a "Stay in the loop" email signup panel to the home tab. Subscribers are stored in ~/.agora/newsletter.json. |
| contact | boolean | Adds a "Get in touch" contact form (name, email, message) to the home tab. Submissions are forwarded to the tenant's notification email via Minnie. |
Music
| Field | Type | Description |
|-------|------|-------------|
| mirloUrl | string | A Mirlo artist page URL (e.g. https://mirlo.space/your-name). On every upload the server fetches and merges the artist's published albums and tracks into the Canimus feed. |
Shows
Adds a 🎤 Shows tab populated from any public .ics calendar feed (Google Calendar, iCal export, Calendly, etc.). Events are fetched on each page load, filtered to upcoming dates only, and cached for one hour.
| Field | Type | Description |
|-------|------|-------------|
| shows.icsUrl | string | Public .ics URL |
| shows.title | string | Tab/section label (default: "Upcoming Shows") |
Events with a URL field in the .ics get a "Tickets →" button.
Social links
Renders a row of circular brand-colored platform icon links at the bottom of every page. Provide a key-to-URL mapping. Unrecognised keys are silently ignored.
Supported platforms: instagram, youtube, tiktok, facebook, twitter, bandcamp, spotify, soundcloud, patreon, mastodon, bluesky, linkedin, threads
Redirects
Override the default click behaviour for an entire content category. Visitors clicking any card in that category are sent to an external URL instead of the built-in pages.
"redirects": {
"music": "https://yourname.bandcamp.com",
"subscriptions": "https://patreon.com/yourname"
}Valid keys: books, music, posts, photos, products, appointments, subscriptions
Affiliate commission
| Field | Type | Description |
|-------|------|-------------|
| affiliateCommission | number | Fraction of the sale price paid to affiliates (0–0.50). Requires the affiliate program to be configured. |
Content folder reference
music/*/info.json
{
"title": "Album Title",
"description": "Debut record",
"price": 0,
"cover": "artwork.jpg",
"tracks": ["Intro", "Track Two", "Outro"],
"streamingUrl": "https://yourname.bandcamp.com/album/title",
"keywords": ["folk", "ambient"]
}streamingUrl renders as a "Listen →" link on the album card and in the track list, opening in a new tab. Also works in standalone track sidecar .json files.
subscriptions/tip-jar.json
A flat file (not a subfolder) placed directly in the subscriptions/ directory. Renders as a styled tip card at the top of the Infuse tab.
{
"title": "Leave a tip!",
"description": "Every contribution helps keep the music going.",
"venmo": "https://venmo.com/YourHandle",
"paypal": "https://paypal.me/YourHandle",
"cashapp": "https://cash.app/$YourHandle",
"kofi": "https://ko-fi.com/YourHandle",
"buymeacoffee": "https://buymeacoffee.com/YourHandle",
"patreon": "https://patreon.com/YourName",
"gofundme": "https://gofundme.com/f/your-campaign",
"liberapay": "https://liberapay.com/YourHandle",
"githubsponsors": "https://github.com/sponsors/YourHandle",
"stripe": "https://buy.stripe.com/your-link"
}title and description are optional. Only platforms with a URL provided are shown.
Full manifest.json example
{
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"emojicode": "🛍️🎨🎁🌟💎🐉📚🔥",
"name": "Tree Temple Music",
"description": "Piano, folk metal, and sonic adventures from Troll Hart.",
"keywords": ["folk metal", "piano", "progressive", "indie"],
"email": "[email protected]",
"lightMode": false,
"sections": ["music", "posts", "products", "appointments", "subscriptions"],
"bio": {
"name": "Troll Hart",
"title": "Pianist, composer, producer",
"description": "A musical expression of love for Mother Earth and the journey to peace for all her children."
},
"newsletter": true,
"contact": true,
"shows": {
"icsUrl": "https://calendar.google.com/calendar/ical/your_id/public/basic.ics",
"title": "Upcoming Shows"
},
"mirloUrl": "https://mirlo.space/troll-hart",
"socials": {
"bandcamp": "https://silenttemple.bandcamp.com",
"instagram": "https://instagram.com/treetemplemusic",
"youtube": "https://youtube.com/@treetemplemusic",
"tiktok": "https://tiktok.com/@treetemplemusic",
"patreon": "https://patreon.com/trollhart",
"facebook": "https://facebook.com/treetemplemusic"
},
"redirects": {
"products": "https://silenttemple.bandcamp.com/merch"
},
"affiliateCommission": 0.10
}