semantic-delivery — one piece of content, eleven distributors.
Schema.org enrichment and multichannel distribution for TYPO3 14. Six native platform adapters (LinkedIn, X/Twitter, Instagram, Facebook, Bluesky, Dev.to) plus five proxy adapters (Ayrshare, Buffer, n8n, Late.dev, Webhook). Per-page platform selection, backend module, CLI commands. MIT licence.
Multichannel distribution usually ends in a copy-paste loop.
With semantic-delivery
- Auto-generation of Schema.org JSON-LD from content models
- Channel transformer per channel (Web/AI/Voice/Social) with character-limit awareness
- Direct distribution on 6 platforms, proxy distribution on 5 more
- OAuth tokens AES-256-CBC encrypted in the backend, with refresh flow
- Dev.to cross-posting with canonical URL attribution
- Podcast episode detection with automatic job creation
- Per-page platform selection in the backend — only configured platforms visible
Until now
- Manual adjustment per channel, each with its own character limits
- JSON-LD writing in the template
- No channel detection in the frontend (Web vs AI Agent vs Voice)
- OAuth token management as a side project with plain-text storage
- Cross-posting in blog platforms without canonical attribution
- Podcast episode detection as a cron-job hack
Four core building blocks
Channel detection middleware
Detects from headers / user-agent / Accept whether the request is coming from an AI agent, voice assistant, social crawler, or browser — and serves the appropriate format.
Distributor architecture
Auto-discovery via Symfony DI. Custom distributors implement DistributorInterface and appear automatically in the page editor as soon as the related site credentials are configured.
Channel transformer
One transformer per channel: Web/AI Agent/Voice/Social Media. Trim to platform limits (e.g. 280 characters X, 300 graphemes Bluesky), tonality adjustment, asset selection.
Schema.org enrichment
JSON-LD is generated automatically from the content model: Article, BlogPosting, NewsArticle, FAQPage, Product, HowTo, Organization, LocalBusiness. Auto-detect with manual override per page.
Eleven distributors in three categories
Six platforms are served directly through their native APIs (direct distribution); one of these is a long-form blog platform with canonical attribution. Five more run via established proxy services — useful if, for example, you already use Buffer or Ayrshare.
Proxy services
- Ayrshare — API Key
- Buffer — Access Token
- n8n — Webhook URL
- Late.dev — API Key
- Generic Webhook — Custom URL
Long-form blog
- Dev.to — API Key · Markdown format
Automatically sets a canonical URL back to the original TYPO3 page — no SEO penalty for cross-posting.
Social Media (short-form)
- Bluesky — App Password · 300 graphemes
- LinkedIn — OAuth 2.0 · 3,000 characters
- X / Twitter — Bearer Token · 280 characters
- Instagram — Page Access Token · 2,200 characters
- Facebook — Page Access Token · 63,000 characters
Backend, CLI and operations
semantic-delivery does not ship with backend extensions that nobody uses — the backend module is editor-ready from the start, the CLI commands are cron-friendly, and the OAuth service stores tokens AES-256-CBC encrypted.
DDD + tests
4-layer DDD (Domain / Application / Infrastructure / Presentation), strictly enforced via deptrac. PHPStan Level 8, PER-CS3x0, PHPUnit unit + functional tests. Four database tables (channel_content, distribution_job, schema_cache, oauth_token).
OAuth token service
For platforms with OAuth 2.0 + refresh: tokens are stored AES-256-CBC encrypted in the backend (TYPO3 encryption key). API for storage, lookup, refresh, and expiry check is in the service container.
CLI commands
semantic-delivery:detect-episodes detects new podcast episodes and creates distribution jobs (with --dry-run and --auto-publish). semantic-delivery:process-jobs works the queue.
Backend module
Under Content → Semantic Delivery (admin access): per-platform preview before publish, job queue management, log with external URLs of successful distributions. Per-page "Semantic Delivery" tab with platform checkbox list.
Database and page fields
Tables
| Table | Purpose |
|---|---|
tx_semanticdelivery_channel_content | Channel-specific content variants |
tx_semanticdelivery_distribution_job | Distribution job queue |
tx_semanticdelivery_schema_cache | Cached Schema.org data |
tx_semanticdelivery_oauth_token | Encrypted platform OAuth tokens |
Page fields
| Field | Type | Description |
|---|---|---|
tx_semanticdelivery_schema_type | Select | Schema.org type override (auto-detect by default) |
tx_semanticdelivery_channels | CheckBox | Delivery channels (Website, AI Agent, Voice, Social Media) |
tx_semanticdelivery_distribution_enabled | Check | Enable distribution for this page |
tx_semanticdelivery_distribution_platforms | CheckBox | Target platforms (dynamically populated) |
The platform selector only shows platforms with credentials configured for the current site. This stops editors from picking targets that would fail.
Supported platforms
Social media (short-form)
| Platform | Distributor | Auth | Limit |
|---|---|---|---|
| Bluesky | BlueskyDistributor | App Password | 300 graphemes |
LinkedInDistributor | OAuth 2.0 Access Token | 3,000 chars | |
| X/Twitter | TwitterXDistributor | Bearer Token | 280 chars |
InstagramDistributor | Page Access Token | 2,200 chars | |
FacebookDistributor | Page Access Token | 63,000 chars |
Blog platforms (long-form)
| Platform | Distributor | Auth | Format |
|---|---|---|---|
| Dev.to | DevToDistributor | API Key | Markdown |
Blog distributors automatically set a canonical URL back to the original TYPO3 page. Note: Medium has discontinued issuing new API tokens; the MediumDistributor has been removed.
Proxy services
| Platform | Distributor | Auth |
|---|---|---|
| Ayrshare | AyrshareDistributor | API Key |
| Buffer | BufferDistributor | Access Token |
| n8n | N8nDistributor | Webhook URL |
| Late.dev | LateDevDistributor | API Key |
| Generic Webhook | WebhookDistributor | Custom URL |
Setup
1. Enable distribution in site settings
semanticDelivery:
channels:
socialMedia:
enabled: true
distribution:
enabled: true
defaultDistributor: 'bluesky'
2. Configure platform credentials
Credentials sit per site in config/sites/<name>/config.yaml. Sensitive tokens use the %secret()% syntax (see moselwal/secret-resolver); public identifiers go directly into the YAML.
Only platforms with a non-empty primary credential appear in the backend editor. Platforms without credentials are hidden, so editors cannot select targets that would fail.
3. Run the database schema update
vendor/bin/typo3 database:updateschema
4. Per-page platform selection
In the TYPO3 backend, every page has a Semantic Delivery tab:
- Enable Distribution
- Pick the target platforms (only configured ones appear)
- Save and publish
The distribution system honours this choice — pages are only sent to the platforms you ticked.
CLI, backend module and extension
CLI commands
# Detect new podcast episodes
vendor/bin/typo3 semantic-delivery:detect-episodes --dry-run
vendor/bin/typo3 semantic-delivery:detect-episodes
vendor/bin/typo3 semantic-delivery:detect-episodes --auto-publish
# Process pending jobs
vendor/bin/typo3 semantic-delivery:process-jobs
Recommended cron
*/15 * * * * cd /app && vendor/bin/typo3 semantic-delivery:detect-episodes
*/5 * * * * cd /app && vendor/bin/typo3 semantic-delivery:process-jobs
Backend module
Available under Content → Semantic Delivery (admin access):
- Preview — view transformed content per platform before publishing
- Queue — manage pending distribution jobs
- Log — inspect completed and failed distributions with external URLs
Adding a distributor
- Create a class implementing
DistributorInterfaceinClasses/Infrastructure/Distribution/ - Optionally add a
TransformerInterfaceinClasses/Infrastructure/Transformer/ - Register the credential mapping in
DistributionPlatformItemsProcFunc::CREDENTIAL_KEYS - Add the corresponding site setting in
settings.definitions.yamlandsettings.yaml
Once credentials are configured, the platform automatically appears in the page editor. OAuth tokens flow through the OAuthTokenService and are encrypted at rest with AES-256-CBC using the TYPO3 encryption key.
Source code & docs
TYPO3 Extension Repository
Not in the official TER — install via Composer only. Extension key: semantic_delivery.
Composer package
moselwal/semantic-delivery via the Moselwal Composer repo. MIT licence, freely usable.
GitLab (source of truth)
Primary repository including CI/CD, tests, and Composer package registry.
Your platform missing?
Auto-discovery turns adding a new distributor into a question of two classes — implement DistributorInterface, optionally a transformer, add credential mapping in DistributionPlatformItemsProcFunc::CREDENTIAL_KEYS, done. If you want to do it yourself: docs in the repo. If you want us to build it: get in touch.
Oder direkt schreiben: kontakt@moselwal.de