← Media Hub

Media Hub Operator Guide

Sovereign social media publication — platform admin manual. Last updated 2026-04-14.

Contents

What the Media Hub is for

A single sovereign control surface for publishing company-authored content across every channel where Village can reach new audiences. The hub turns one long-form article into many platform-native posts, holds them behind a Tractatus Guardian review, and lets you publish to real platforms — Mastodon, Village Federation, Substack, Facebook, X, LinkedIn, Reddit, HN, Medium, Threads — from one place.

Not this: A scheduler that automates your voice away.
But this: An inbox of drafts waiting for your approval, a Guardian protecting your brand voice, and a ledger proving every post.

The 6-step core loop

1. INGEST    → pull new publications from platform sources
2. EXTRACT   → AI extracts ranked topic candidates from each publication
3. PROMOTE   → you click a topic, generator produces platform variants
4. REVIEW    → Guardian flags concerns, you approve / reject / edit
5. PUBLISH   → API for sovereign/capable platforms, copy-assist for the rest
6. RECORD    → for copy-assist posts, paste the final URL back so the ledger is accurate

Step-by-step first run

1. Open the hub

Navigate to https://mdsl.mysovereignty.digital/media-hub.html and sign in as platform admin. You'll see a three-zone layout:

ZonePurpose
Zone 1 — BriefingPlain-language AI summary of what's in the queue. 2-min cache.
Zone 2 — Action QueueDrafts pending review, failed publishes, expiring credentials, connector errors.
Zone 3 — Watch GridTop topics, recent publishes, enabled connectors, stats.

2. Ingest a source

Click Ingest sources (or press i). The hub reads from platform content only:

NEVER tenant content — this is a hard guarantee enforced at startup.

3. Extract topics

Click Extract topics (or press x). The hub calls the sovereign InferenceRouter on the home eGPU. For each new publication, the AI returns 3–8 topic candidates. A deterministic ranker scores each on 5 dimensions (novelty, strategic importance, audience fit, timeliness, controversy sensitivity) and produces a 0–1 composite. Top topics appear in Zone 3.

4. Promote a topic

In Zone 3, click Promote next to a topic. The generator creates platform variants for every enabled platform (Mastodon + Village Federation + Substack by default). Each variant passes through MediaPostSafetyChecker. ~30–60 seconds end-to-end.

5. Review + approve

In Zone 2 you'll see the new draft as a card. The card surfaces everything you need to know before clicking in:

Hover the card — it tints teal to confirm it's clickable. Click anywhere on the card (or press Enter when focused) to open the review modal.

The review modal shows:

Guardian verdicts:

VerdictMeaningAction
passedNo rule violationsApprove + publish
flaggedConcerns noted, not blockingRead flags, decide
criticalBanned claim / char overflow — blocksRegenerate or edit

6. Publish

Click Publish now (or schedule).

Worked example: Substack → Facebook cross-post chain

Cross-posting is the single highest-ROI outreach pattern for Village. Long-form on Substack drives engaged readers back to mysovereignty.digital; a short teaser on your Facebook personal profile (1.5K followers) amplifies reach to people who wouldn't find the Substack organically.

Why this works: Facebook's algorithm treats personal-profile link-shares better than Page posts. The sovereign content (the essay) never leaves Village's infrastructure; Substack holds a mirror; Facebook holds a teaser card. Each layer amplifies the next.
  1. Ingest + extract + promote a topic from an article. The generator produces Substack long-form + Facebook teaser (with a {{SOURCE_URL}} placeholder).
  2. Approve the package.
  3. Publish Substack first. Copy title/subtitle/body/tags, paste into ridingthetiger.substack.com/publish/home, hit Publish, copy the resulting URL, paste back into the hub's Record URL input.
  4. Publish Facebook teaser. The hub offers you a choice of URL: canonical Village article, or the Substack URL you just recorded. Choose Substack. The hub substitutes the placeholder and copies the full teaser. Paste into Facebook's status box — Facebook auto-generates a rich preview card. Click Post. Record the resulting FB URL back in the hub.
  5. Ledger shows both publishes linked to the same source topic.

Developer account setup

Each API-based connector needs a one-time developer app registration on the target platform. You only do this once per platform.

Mastodon (easiest — 5 min)

  1. Create a Mastodon account on mastodon.social (German-hosted, largest instance, best EU reach, verified live) or eupolicy.social (community-run "EU bubble" instance, active as of 2026-04-14, Mastodon 4.5.8, best reach for Brussels-policy audience)
  2. Correction: An earlier version of this guide recommended social.network.europa.eu as an EU Commission Mastodon option. That was wrong — the EDPS EU Voice pilot was officially closed on 18 May 2024. No EU-institution Mastodon currently exists. Use eupolicy.social for the EU policy audience.
  3. Settings → Development → New application
  4. Scopes: write:statuses, read:statuses
  5. Copy the access token — this goes into MediaHubSocialAccount via the account setup page (when built)

Facebook Page API

  1. Go to developers.facebook.com
  2. Create App → Business → name "Village Media Hub"
  3. Add Facebook Login for Business + Pages API products
  4. Copy App ID + App Secret → env vars MEDIA_HUB_FB_APP_ID / MEDIA_HUB_FB_APP_SECRET
  5. Graph API Explorer → generate a long-lived Page Access Token with pages_manage_posts
  6. Store the token in MediaHubSocialAccount
Meta's App Review is only needed if you post to pages other than your own. For Village's use case (posting only to your own page), Development mode is sufficient indefinitely.

X / Twitter API v2

  1. Apply for a developer account at developer.x.com
  2. Free tier ($0/mo, 1,500 tweets/mo) is enough for Village's volume
  3. Create Project + App → enable OAuth 2.0 with PKCE
  4. Scopes: tweet.read, tweet.write, users.read, offline.access
  5. Callback: https://mdsl.mysovereignty.digital/api/media-hub/oauth/twitter/callback
  6. Copy Client ID + Secret → env vars MEDIA_HUB_X_CLIENT_ID / MEDIA_HUB_X_CLIENT_SECRET

LinkedIn Share API

  1. Go to developer.linkedin.com
  2. Create App, associate with your LinkedIn Page
  3. Products: Sign In with LinkedIn + Share on LinkedIn (both free + instant)
  4. Callback: https://mdsl.mysovereignty.digital/api/media-hub/oauth/linkedin/callback
  5. Scopes: w_member_social for personal sharing (starts immediately), or w_organization_social for Page sharing (needs Marketing Developer Platform review, ~2 weeks)
  6. Copy Client ID + Secret → env vars MEDIA_HUB_LI_CLIENT_ID / MEDIA_HUB_LI_CLIENT_SECRET
Start with personal sharing (w_member_social). It's instant, no review needed, and reaches your LinkedIn network directly.

Substack / Medium / Reddit / Hacker News

No dev account setup — these are copy-assist. The hub generates content, you paste manually.

The Guardian — rules and verdicts

MediaPostSafetyChecker runs 8 deterministic rules on every generated variant.

RuleSeverityWhat triggers it
banned_claimcritical"HIPAA compliant", "military-grade encryption", "unhackable", etc.
brand_voice_violationflagged"revolutionary", "game-changing", "10x", "potentially", etc.
banned_vendor_unflaggedflaggedMentioning Google/AWS/FB/Stripe without sovereignty framing
sensitive_topicflaggedTe Tiriti, WAI 262, security incident, etc.
character_overflowcriticalDraft exceeds platform char limit
intensity_limitflaggedExclamation marks, ALL-CAPS, emoji density
voice_marker_missingflaggedLong draft without "Village" / "sovereignty" voice markers
duplicate_hookflaggedSame opening 10 words as a recent post

Fail-open: if the Guardian errors internally, it treats the check as passed so a broken rule engine can't block legitimate content.

Keyboard shortcuts

KeyAction
rRefresh the hub
iTrigger ingest
xTrigger topic extraction
sTrigger scheduler tick
EscClose draft modal

Feature flags

FlagDefaultEffect
MEDIA_HUB_ENABLEDtrueMaster switch
MEDIA_HUB_AUTO_PUBLISH_ENABLEDfalseLeave false — human-gated is the safer default
MEDIA_HUB_MASTODONfalseEnable once OAuth wired
MEDIA_HUB_VILLAGE_FEDtrueSovereign, always on
MEDIA_HUB_FBfalseEnable after dev account setup
MEDIA_HUB_XfalseEnable after dev account setup
MEDIA_HUB_LIfalseEnable after dev account setup

Troubleshooting

"SyntaxError: Unexpected token '<'" in the console

API returned HTML (maintenance page) instead of JSON. The hub now detects this and shows "Server is in maintenance mode — try again in a minute". Reload after maintenance ends.

Substack variant has 50,000+ chars — is that normal?

Yes. Substack is long-form; the body is the entire source article pasted between the generated hook and outro. That's by design.

Guardian flagged my post with "potentially"

That's the hedging-word rule firing. Either edit the word out before publishing, or accept the flag if the hedge is intentional. Flagged (not critical) is advisory.

I pressed Publish Now but nothing appeared on Substack

Substack is copy-assist. Publish Now records intent and creates a FederatedPost with status=pending_external_publish, but does NOT push to Substack. You have to open Substack, paste the fields, click Publish there, and record the URL back in the hub.

Where does content from the Media Hub actually live?

If any external mirror goes away, the canonical source and the sovereign mirror are unaffected. Village owns the content; external platforms are amplifiers.

Full markdown version at docs/MEDIA_HUB_OPERATOR_GUIDE.md. Last updated 2026-04-14.