Kai Ole Hartwig
Sechs gebürstete Aluminium-Tags hängen an einem Stahldraht über Eichentisch, jeder Tag mit eigenem geätztem Muster, weiches Tageslicht.
Extension · koh/structured-content

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.

Das Problem

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.

Available on Packagist — MIT, source on GitHub

composer require koh/structured-content. For help integrating it into your TYPO3 platform, use the contact form.

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

TablePurpose
tx_structuredcontent_relationContent 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).

GeneratorPriority@typeTrigger
BreadcrumbListSchemaGenerator90BreadcrumbListEvery page with a rootline
ProfilePageSchemaGenerator75ProfilePage + Person + hasPart/autor/{slug} routing argument resolved
ReviewSchemaGenerator68ReviewPages with the Testimonials CB
PodcastEpisodeSchemaGenerator65PodcastEpisodePodcast plugin detail view (with actor[] for hosts and guests)
PodcastSeriesSchemaGenerator60PodcastSeriesPodcast plugin list view
SoftwareApplicationSchemaGenerator55SoftwareApplicationPages with is_software_application
ArticleSchemaGenerator50Article / BlogPostingArticle pages (with articleSection from sys_category)
FaqSchemaGenerator45FAQPagePages with the FAQ CB
HowToSchemaGenerator45HowToPages with the Steps CB
WebPageSchemaGenerator40WebPageFallback for all pages
WebSiteSchemaGenerator30WebSiteSite root and sub-sites
OrganizationSchemaGenerator25OrganizationSite-wide from settings
ServiceSchemaGenerator20ServicePages with the Service CB (skipped when a SoftwareApplication owns it)
ProfessionalServiceSchemaGenerator20ProfessionalServiceService pages with a provider organisation
PackagesGridEnterpriseServiceSchemaGenerator18Service variantsPackages-grid CB
PackagesGridProductSchemaGenerator18ProductPackages-grid CB
ProductSchemaGenerator15ProductPages with the Product CB
PersonSchemaGenerator10PersonAuthor embedding inside Article
AutoDetectSchemaGenerator5dynamicTCA-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 koh/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)

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

Optional dependencies

PackageTypePurpose
koh/content-provenanceOptionalContent integrity verification
koh/business-agentOptionalAI agent content access
koh/devDevShared QA tooling

The codebase follows a strict DDD 4-layer separation; layer violations are blocked in CI via deptrac.

Source code & docs

Composer package

composer require koh/structured-content – on Packagist, source on GitHub.

On GitHub
Composer package

Repository

Source code and issues on GitHub. Pull requests are welcome.

ohartwig/structured-content
Repository

Mirror

Development happens on a private GitLab instance. GitHub is the public mirror: every release appears there with its tag, and Packagist reads it from there.

Next step

Help with the integration?

structured-content is open source and intended for self-integrators. For AI readiness as an end-to-end package, just get in touch.

Discuss AI readiness →

Or email me directly: mail@ole-hartwig.eu