Search by

web-nomads / wn-ai-bridge

marcelmarty

TYPO3 extension for generating llms.txt links based on the llmstxt.org specification and an on-site AI search assistant that helps visitors find information via ke_search and indexed_search.

Package info

github.com/web-nomads/wn-ai-bridge

Type:typo3-cms-extension

pkg:composer/web-nomads/wn-ai-bridge

Statistics

Installs: 53

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.32.0 2026-09-17 13:32 UTC

This package is auto-updated.

Last update: 2026-09-17 13:33:36 UTC


README

TYPO3 13 & 14 PHP 8.2+ License: GPL v2+

Makes a TYPO3 site readable for AI systems, and gives its visitors a search assistant that answers from the site's own content.

Two halves that work independently:

  • Machine-readable content — an llms.txt file following the llmstxt.org specification in its v2 revision of August 2026, an optional llms-full.txt carrying the content of every page in one document, and a Markdown representation of every page that agents find through the v2 link relations. Free, no key needed.
  • AI search assistant — a chat widget that answers visitor questions from your search index, with links to the pages it used. Requires a subscription key.

Requirements

TYPO3 13.4 LTS or 14.x
PHP 8.2, 8.3 or 8.4
PHP extensions sodium (subscription key verification)
Optional ke_search or indexed_search as the assistant's index

Installation

composer require web-nomads/wn-ai-bridge

Then activate the extension and flush caches.

Nice URLs

Without route enhancers the endpoints are reachable by page type only. To get readable URLs, import the shipped route configuration:

# config/sites/<identifier>/config.yaml
imports:
  -
    resource: 'EXT:wn_ai_bridge/Configuration/Routes/RouterEnhancer.yaml'
Without enhancer With enhancer
llms.txt /?type=1699 /.well-known/llms.txt and /llms.txt
llms-full.txt /?type=1702 /.well-known/llms-full.txt and /llms-full.txt
Markdown /?type=1701 append .md to any page URL

llms-full.txt is off by default; switch on llmsFullTxt in the extension configuration to serve it.

So https://example.com/about also exists as https://example.com/about.md. A URL without a file name — a home page, a language root — gets the index one: https://example.com/ becomes https://example.com/index.md.

What llms.txt is for

llms.txt sits at a well-known location and tells language models what a site is about: a short description, its structure, and links to machine-readable versions of the content. The place is the same idea as robots.txt, the purpose is not — it describes content rather than restricting access. This extension generates it from your actual page tree, so it stays correct without anyone maintaining it by hand.

Configure the metadata (topics, contact, description) per site on the AI Bridge tab of the site configuration.

Structuring the link list

A long list of links tells an agent little about which one it wants. To group them, put a Menu separator into the page tree — the page type TYPO3 already ships for exactly this purpose. Its title becomes an ## H2 heading, and every page after it belongs to that section until the next separator:

Page tree                    llms.txt
─────────────                ────────────────────────────────
▸ Services      (separator)  ## Services
  About                      - [About](/about.md): What we do.
  Pricing                    - [Pricing](/pricing.md): What it costs.
▸ Legal         (separator)  ## Legal
  Imprint                    - [Imprint](/imprint.md): Who runs this.

Pages standing above the first separator keep the default ## Main Page Structure heading. A separator whose title is decoration rather than words — ---, , empty — is skipped, so separators already used purely visually in a menu do not turn into headings.

Separators are translated like any other page, so each language gets its headings in its own words. Only separators at the top level of the navigation become headings; deeper down an H2 would cut the list in two.

Whether a separator shows up in the rendered menu is up to your templates, not to this extension — TYPO3 leaves them out unless an HMENU sets SPC or a MenuProcessor sets includeSpacer = 1. Where your menu does render them and this one should not appear, tick Hide in menu on the separator: it keeps its heading in llms.txt. That setting hides the divider, not the group it opens. A page marked the same way does stay out, because the file follows the navigation.

Link relations

An agent that holds a page should not have to guess where its machine-readable companions are, so v2 asks for two standard link relations. Both are served without any configuration, as <link> elements in the page head and as an HTTP Link: response header — the header form also reaches the .md documents and answers a plain HEAD request:

Link: </about.md>; rel="alternate"; type="text/markdown", </llms.txt>; rel="describedby"

describedby points at the llms.txt of the page's own language, so a page below /en/ is described by /en/llms.txt rather than the root file.

AI search assistant

A floating chat widget. Switch it on in the extension configuration (assistantEnabled) and per site in the site configuration.

Search-only (no API key) returns ranked matching pages as suggestions with links. Fast, free, and nothing leaves your server.

Hybrid (with an LLM API key in assistantApiKey) additionally lets the model compose a short answer from the retrieved pages and cite them. Any failure — quota, timeout, malformed response — falls back to search-only rather than showing an error.

The temperature and the agent instructions are set per site, on the AI Assistant tab of the site configuration: they are answers a website gives, not an installation. So is the subscription key, so two sites in one TYPO3 can be licensed separately. Installations upgrading from 1.28 or earlier find all three in the extension configuration; the upgrade wizard "AI Bridge: move the subscription key, temperature and instructions into the site configuration" copies them into every site. Until it has run, the old values keep being used.

The assistant reads ke_search and indexed_search when they are installed, and always keeps a dependency-free pages/tt_content fallback so it returns something even without a search index. It only ever answers with pages of the site the question was asked on — the search indexes hold the whole installation and know nothing about sites, so the boundary is drawn on the results.

Backend modules

Module What it is for
Enquiries Every question asked, the answer given, the provider, token usage and cost. Filterable
Answers Question/answer pairs the assistant uses as its own knowledge
Bot Access Log Which AI crawlers requested llms.txt and the Markdown endpoints

Answers is the local learning source. An entry is played back verbatim when a new question matches it in meaning — term overlap plus string similarity, not exact wording. Weaker matches are handed to the model as binding hints. Entries come from three places: written by an editor, taken over from a logged answer in Enquiries, or captured from a correction a visitor made in the chat, which arrives as "pending" and is only used once approved.

Subscription

The assistant and its two modules are subscription features. Enter the key in the Subscription key field on the AI Assistant tab of the site configuration — each website runs on its own licence, and an installation with one licence for everything can keep it in the extension configuration instead. The key is encrypted and signed; it carries the domains it is valid for, an expiry date and the enabled features.

Functions Needs a key
Chat widget, Enquiries, Answers yes
llms.txt, Markdown endpoints, Bot Access Log no

Important:
Without a valid key the widget stays hidden and the two modules disappear. Everything else keeps working.

Order your subscription key:
DE: https://www.marcelmarty.ch/#extensions
EN: https://www.marcelmarty.ch/en/#extensions

Order your 14 days free trial key here:
DE: https://www.marcelmarty.ch/ai-bridge-trial
EN: https://www.marcelmarty.ch/en/ai-bridge-trial

Once the trial key has expired, nothing will be automatically renewed or charged

What the licence check sends

Once a day the extension asks the issuing server whether the subscription is still active, sending the subscription id, this installation's hostname and a random nonce. No visitor data is involved — no IP addresses, no questions, no page content. The signed answer is what carries a renewal to the installation, so a renewed subscription takes effect without anyone pasting a new key, and a revoked one stops working without waiting for its expiry date.

The same answer carries the domains the subscription currently covers. A licence can therefore grow: ask the issuer to add a domain, and the site running on it works within a day — the key in your configuration keeps the list it was issued with and does not have to be replaced. This is what makes a second website in the same TYPO3 possible without a second key.

An unreachable server changes nothing: the date and the domains inside the key decide, and only an explicitly signed "revoked" switches the features off. A server that stays silent can therefore never extend a licence either.

Leave the subscription key empty and nothing is ever sent.

See Documentation/Administrator for the full description, including what is reported when an installation looks manipulated.

Configuration

Extension configuration (Admin Tools → Settings → Extension Configuration) covers the assistant, the LLM provider, rate limiting and the subscription key. Per-site settings live on the AI Bridge and AI Search Assistant tabs of the site configuration.

Two things worth setting before going live with the assistant:

  • Enable the rate limiter (rateLimiterEnabled). The assistant endpoint is reachable without authentication and every request can cost money.
  • Set a spending limit in your LLM provider account as an independent second net.

Documentation

The full manual is rendered at docs.typo3.org, and its source lives in Documentation/.

Development

composer install

composer test        # unit tests
composer stan        # PHPStan level 6
composer cs:check    # coding standards, --dry-run
composer cs:fix      # apply them
composer ci          # all of the above

composer release     # build the TER archive

composer release writes wn_ai_bridge_<version>.zip next to the extension folder and refuses to build if the version in ext_emconf.php and composer.json disagree, if ext_emconf.php would not land at the archive root, or if anything generated would be packed.

Contributing

Issues and pull requests are welcome at github.com/web-nomads/wn-ai-bridge.

For a pull request: follow the TYPO3 coding standards (composer cs:fix), add tests for behaviour you change, and keep composer ci green.

Credits

This extension started as a fork of web-vision/ai-llms-txt by web-vision, which provides the llms.txt generation according to the llmstxt.org specification. The AI search assistant, the Markdown endpoints and the subscription handling were added here.

Licence

GPL-2.0-or-later, the same licence as the original — see LICENSE.