
structured-content — semantic metadata that is inherited.
AI context annotations (audience, tone, channels) at page and content level that cascade through the page hierarchy — with typed content relationships, confidence scoring and JSON-LD generation as output. The foundation for semantically clean TYPO3 platforms.
Without context, content is only half there for AI.
With structured-content
- AI context fields directly in the page and content element backend
- Inheritance through the hierarchy — setting on a parent page cascades down
- Typed content relationships with confidence score
- JSON-LD generation automatic in the frontend
- Channel-aware field restrictions
- CLI tools for bulk annotation
Until now
- Audience and tone live in brand guidelines, not in the CMS
- JSON-LD is sprinkled into templates by hand
- Channel awareness is missing — the same content goes unfiltered into every channel
- Content relationships only via loose linking
Four building blocks
JSON-LD in the frontend
Schema.org markup is generated automatically from the annotations — nothing has to be sprinkled into the template.
Typed content relationships
Relationships between content elements are typed (e.g. "explains", "extends", "contradicts") with a confidence score — AI systems use this for more coherent answers.
Hierarchical inheritance
An annotation on a parent page applies automatically to all children unless overridden there. The effort per piece of content drops drastically.
AI context fields
Audience (Customer/Partner/Internal/Developer), Tone (Informational/Promotional/Technical/Legal), Channels (Web/AI-Agent/Voice/Social) — as standard TCA fields.
Architecture
Classes/
├── Domain/ # Annotation models, relationship types, contracts
├── Application/ # Context resolution, relationship services
├── Infrastructure/ # Repositories, JSON-LD builders, context resolvers
└── Presentation/ # Controllers, event listeners
Database tables
| Table | Purpose |
|---|---|
tx_structuredcontent_relation | Content relationships |
pages (extended) | ai_context_* fields for audience, tone, channels |
tt_content (extended) | ai_context_* fields for element-level metadata |
Schema.org generator stack
All generators in Classes/Infrastructure/SchemaOrg/ implement SchemaGeneratorInterface, are registered via the structured_content.schema_generator service tag and rendered in priority order (higher = earlier in the JSON-LD block).
| Generator | Priority | @type | Trigger |
|---|---|---|---|
BreadcrumbListSchemaGenerator | 90 | BreadcrumbList | Every page with a rootline |
ProfilePageSchemaGenerator | 75 | ProfilePage + Person + hasPart | /autor/{slug} routing argument resolved |
ReviewSchemaGenerator | 68 | Review | Pages with the Testimonials CB |
PodcastEpisodeSchemaGenerator | 65 | PodcastEpisode | Podcast plugin detail view (with actor[] for hosts and guests) |
PodcastSeriesSchemaGenerator | 60 | PodcastSeries | Podcast plugin list view |
SoftwareApplicationSchemaGenerator | 55 | SoftwareApplication | Pages with is_software_application |
ArticleSchemaGenerator | 50 | Article / BlogPosting | Article pages (with articleSection from sys_category) |
FaqSchemaGenerator | 45 | FAQPage | Pages with the FAQ CB |
HowToSchemaGenerator | 45 | HowTo | Pages with the Steps CB |
WebPageSchemaGenerator | 40 | WebPage | Fallback for all pages |
WebSiteSchemaGenerator | 30 | WebSite | Site root and sub-sites |
OrganizationSchemaGenerator | 25 | Organization | Site-wide from settings |
ServiceSchemaGenerator | 20 | Service | Pages with the Service CB (skipped when a SoftwareApplication owns it) |
ProfessionalServiceSchemaGenerator | 20 | ProfessionalService | Service pages with a provider organisation |
PackagesGridEnterpriseServiceSchemaGenerator | 18 | Service variants | Packages-grid CB |
PackagesGridProductSchemaGenerator | 18 | Product | Packages-grid CB |
ProductSchemaGenerator | 15 | Product | Pages with the Product CB |
PersonSchemaGenerator | 10 | Person | Author embedding inside Article |
AutoDetectSchemaGenerator | 5 | dynamic | TCA-driven mapping |
Builders and traits
Application/Service/PersonSchemaBuilder.buildFromRow($personRow) emits Person with worksFor[], sameAs[] (with a Label|URL pipe format), knowsAbout, knowsLanguage and image. PersonRoutingArgumentTrait resolves the person slug from the _routingArguments of the Person plugin detail view. PodcastFeedCacheReaderTrait reads cached feed items for podcast schemas without a re-fetch. SanitizesSchemaTrait strips empty and non-JSON-conformant values. ContextAndRelationshipsTrait attaches AI context and relationships to the schema output.
Repositories
AuthoredPagesRepository.findByPersonUid finds pages that link to a person via tx_structuredcontent_author_records (for Person.hasPart). CategoryRepository.findByPageUid reads sys_category records via sys_category_record_mm (for Article.articleSection). EpisodeGuestsRepository serves bulk episode_slug → Person[] for PodcastEpisode.actor.
Article schema extensions (AI Disclosure, Reading Time, Language Fallback)
AI Content Disclosure (v1.5.10+)
For AI-tagged hero images, the Article schema contains image: {creator: {SoftwareApplication, name}, creditText: "AI-generated"}. The EU AI Act Article 50 disclosure is therefore anchored directly in the JSON-LD. Edited through the TCA fields from moselwal/content-provenance (tx_provenance_origin, tx_provenance_ai_system).
Reading Time (v1.5.9+)
The Article schema carries wordCount and timeRequired (ISO-8601 PT*M) — byte-identical to the frontend reading-time badge (200 words per minute). Unifies the reading-time display between markup and user view.
Language fallback in schema generators (v1.5.7+)
Translation-aware: default-language records are loaded and EN translations are overlaid. The schema output keeps working under fallbackType: fallback without gaps — incomplete localisations no longer cause missing schema markup.
Relationship type mappings (Schema.org)
replaces→isBasedOnbelongs_to→isPartOfrelated_to→relatedLinkexplains→about
sys_category mapping
Extends sys_category with a slug field (auto-generated from the title) for filter URLs and an RTE description for category hero blocks. The Article JSON-LD emits the category as articleSection.
CLI commands
vendor/bin/typo3 structured-content:missing-context # Find pages missing AI context
vendor/bin/typo3 structured-content:export-relations # Export relationships as JSON
vendor/bin/typo3 structured-content:validate-channels # Validate channel configurations
Configuration
AI context fields are added to the TYPO3 page and content element forms. Configure default context values and inheritance behaviour through site settings.
Requirements
- PHP 8.3+
- TYPO3 14.0
Optional dependencies
| Package | Type | Purpose |
|---|---|---|
moselwal/content-provenance | Optional | Content integrity verification |
moselwal/business-agent | Optional | AI agent content access |
moselwal/dev | Dev | Shared QA tooling |
The codebase follows a strict DDD 4-layer separation; layer violations are blocked in CI via deptrac.
Source code & docs
TYPO3 Extension Repository
Not in the official TER — public Composer distribution is being prepared (coming soon).
Composer package
Public release as moselwal/structured-content in preparation. Coming soon.
Repository
Source code and issue tracker will be opened with the public release. Coming soon.
Mirror
Public mirror and pull-request workflow follow with the release. Coming soon.
Help with the integration?
structured-content is open source and intended for self-integrators. For AI readiness as an end-to-end package, take a look at our AI-Ready CMS as a Service.
Oder direkt schreiben: kontakt@moselwal.de
Where we use this …
This package is part of the platform line for AI-Ready CMS and AI-Ready Commerce — as the semantic layer that makes content readable for retrieval systems and agents. Managed variant: AI-Ready CMS as a Service.