Configuration
LLM provider setup
The Cowriter extension uses the nr-llm extension for LLM provider configuration. Configure your preferred provider in the nr-llm backend module.
Supported providers
- OpenAI - GPT-5.x series, o-series reasoning models
- Anthropic Claude - Claude 4.5 Opus, Sonnet, Haiku
- Google Gemini - Gemini 3 Pro, Flash
- OpenRouter - Access to 100+ models from multiple providers
- Mistral - Mistral Large, Medium, and open models
- Groq - Ultra-fast inference with Llama, Mixtral
Configuration steps
- Navigate to Admin Tools > LLM Management
- Add a provider (e.g., OpenAI with your API key)
- Create a model configuration
- Create an LLM configuration and set it as default
Tip
See the nr-llm provider configuration for detailed provider configuration options.
RTE configuration
There are two ways to configure the CKEditor integration:
Option 1: Using the shipped preset
If you don't have a custom RTE configuration, point the RTE at the preset this extension registers:
- Go to your root page
- Open Page Properties > Page TSconfig
-
Add this line:
RTE.default.preset = cowriterCopied!
The preset is inherited by every page below, and brings all four toolbar items with it.
The Page TSconfig field with RTE..
Option 2: Custom RTE configuration
If you have your own RTE configuration file
(your_), add the Cowriter module:
editor:
config:
importModules:
- { module: '@netresearch/t3_cowriter/cowriter', exports: ['Cowriter'] }
toolbar:
items:
- cowriter
- cowriterVision
- cowriterTranslate
- cowriterTemplates
The four toolbar items are:
cowriter- Main dialog — task-based content generation with preview
cowriterVision - Generate image alt text via LLM vision analysis
cowriterTranslate - Inline translation dropdown with the languages of the record's site, see Translation languages and formality
cowriterTemplates - Open the Cowriter dialog with a task pre-selected
Tip
You can include only the toolbar items you need. For example, if you
only want the main dialog and translation, omit cowriter
and cowriter.
Warning
An explicit toolbar. list REPLACES the toolbar, it does not add
to it. Importing the module and then listing only cowriter gives you
exactly one button — the other three are registered but have nowhere to
appear. If buttons are missing, check this list before suspecting the
extension.
Translation languages and formality
The Translate dropdown offers the languages of the site the edited
record belongs to: every language of the site configuration, labelled with
its title. Languages hidden from the frontend (enabled: false) are
included, so editors can translate into a language before it goes live.
When the record belongs to no
site (a record on the root page, pid 0, or in a folder outside every site),
the dropdown keeps its fixed list: German, English, French, Spanish,
Italian, Dutch, Portuguese, Polish, Japanese and Chinese. The same list
appears when none of the site's languages has a target code (for example a
site whose only language is fil_, see below).
The target language is taken from the language's locale:
- The two-letter language code is used, the region is dropped:
de_andDE. UTF- 8 de_both translate intoCH. UTF- 8 de. - English and Portuguese keep the region, because DeepL translates into
their regional variants:
en_givesGB en-,GB en_givesUS en-,US pt_givesBR pt-,BR pt_givesPT pt-. Other regions of these languages (PT en_) giveAU enorpt. - Chinese gives
zh. DeepL translateszhinto Simplified Chinese; the language model receives only "Chinese" and chooses the script itself. The regions that write Traditional Chinese keep their region:zh_givesTW zh-,TW zh_givesHK zh-,HK zh_givesMO zh-; a locale with the scriptMO Hantand no region giveszh-, one with the scriptTW Hansgiveszh. DeepL has no target for these codes, so nr-llm translates them with the language model. - A language without a two-letter code (
fil_) is not offered, nor is thePH CorPOSIXlocale.
Formality
Each site language can set the formality of translations into it with the
key cowriter:
default- No preference (the default when the key is missing).
formal- Formal address, for German the "Sie" form.
informal- Informal address, for German the "du" form.
Any other value counts as default. DeepL applies the formality for the
languages it supports it for (with nr-llm 0.41: German, French, Italian,
Spanish, Dutch, Polish, Portuguese, Russian, Japanese) and ignores it for
the others; with
a language model as translator it becomes an instruction to keep that tone.
Set the key in the Sites module (Site Management > Sites, the language's field Cowriter: formality of translations) or directly in the site configuration:
languages:
- languageId: 0
title: English
locale: en_US.UTF-8
base: /
- languageId: 1
title: Deutsch
locale: de_DE.UTF-8
base: /de/
cowriterFormality: formal
With this configuration the dropdown offers "English" (en-) and
"Deutsch" (de), and German translations use the formal address.
Note
Saving a site in the Sites module keeps only the language keys that
have a field in the module. The extension adds a field for
cowriter, so the setting survives an edit there.
Task configuration
The Cowriter dialog shows tasks from
the nr-llm extension with category = 'content'. Default tasks
(Improve, Summarize, Extend, Fix Grammar, Translate EN/DE) are seeded
during installation.
Adding custom tasks
- Navigate to Admin Tools > LLM Management
- Create a new task record with
category = 'content' - Set a descriptive name and identifier
- Write a prompt template using
{as the placeholder for user content{input}}
Rewrite the following text in a more engaging tone, suitable for
a marketing audience. Output ONLY the rewritten text without
explanations.
{{input}}
Tip
Tasks can have their own LLM configuration. If a task has no configuration assigned, the request's configuration or the default configuration is used as fallback.
Field suggestions
The fields that get the Suggest values with AI
button are set in the extension configuration
(Admin Tools > Settings >
Extension Configuration > t3_):
-
- Type
- string
- Default
pages.seo_ title,pages. description,pages. keywords,pages. slug
Comma-separated list of
table.. Only single-line text fields, plain-text areas (no rich text) and slug fields are supported. A field that does not exist is skipped, sofield pages.only gets the button when the system extensionseo_ title seois installed. An empty value switches the button off.
-
- Type
- int
- Default
3
How many suggestions the button asks for, from 1 to 5. The server treats it as the upper bound: a request for more is answered with this many.
The list is extension configuration rather than page TSconfig because the button is added to the TCA, which is the same for the whole installation. After changing either setting, flush the caches so the TCA is rebuilt.
Saved prompts
Editors save prompts from the Cowriter dialog
(usage). The records are stored in the table
tx_ on the root level (page 0), one owner each; an
editor can have up to 100. Only the owner sees an unshared prompt and
only the owner deletes one in the dialog.
Hiding or deleting the record in the List module takes a prompt away from every editor, its owner included.
Alt text
The Generate alt text button sends the selected image with an instruction to the vision model. The instruction is set in the extension configuration:
-
- Type
- string
- Default
- empty (
Generate a concise, descriptive alt text for this image.)
The instruction for alt texts. An empty value uses the built-in instruction shown as the default.
Example: `
Write an alt text of at most 120 characters for a screen reader. Describe what the image shows, not how it looks. Do not start with "Image of".`
The Cowriter adds the language of the edited record to the instruction, for
example Answer in German . The language comes from the
record's language field and the locale of that language in the site
configuration, and is resolved on the server. There is no language hint
when the record has not been saved yet, has no language field, belongs to
no site, is set to "all languages", or when the editor may not read the
record, its page or its language.
A request to the AJAX route may still send its own instruction in the
prompt field; it replaces the configured one, as it did before the
setting existed. The button in the editor sends none. The language hint is
added in both cases.
Audience, tone and target length
The Audience and Tone of voice selectors in the
Cowriter dialog list the active nr-llm prompt snippets tagged audience
and tone_. Maintain them in the nr-llm backend module, prompt
snippets; the same snippets steer nr_repurpose. A selector without snippets
is not shown.
The length step is relative to the input, or to a target length per content type set in page TSconfig:
tx_cowriter.targetLength {
text = 150
textmedia = 120
}
-
- Type
- int (words)
- Default
- none
The number of words a content element of this type should have. The page of the element decides, so subpages inherit it. With a target, the length steps ask for 50, 75, 100, 125 or 150 per cent of it, and the dialog shows the word count of the answer next to the target.
Rate limiting
The Cowriter enforces a rate limit of 20 requests per minute per
backend user. When the limit is exceeded, the API returns HTTP 429
with a Retry- header.
Security considerations
The Cowriter extension routes all LLM requests through the TYPO3 backend, ensuring that:
- API keys are never exposed to the frontend
- All requests are authenticated via TYPO3's backend session
- Error conditions are logged for debugging
Warning
Always configure your LLM provider's API key in the backend. Never expose API keys in frontend JavaScript or client-accessible files.
Troubleshooting
Translation not working
If the translate button shows "Translation failed", check:
- An LLM provider is configured and marked as default in Admin Tools > LLM Management
- The provider's API key is valid and not expired
- The provider supports the
translationfeature - Check the TYPO3 system log for detailed error messages
No tasks in dropdown
If the Tasks dropdown shows "No tasks configured":
- Navigate to Admin Tools > LLM Management > Tasks
- Create at least one task with
category = 'content' - Make sure the task record is not hidden or deleted
- Reload the page in the browser to refresh the task list
API key rejected
If you see "The LLM provider rejected the API key":
- Check the provider configuration in the LLM module
- Verify the API key is correct and has not been revoked
- Some providers require specific permissions or billing setup
Rate limit exceeded
The Cowriter allows 20 requests per minute per backend user. If you
hit the limit, wait a moment and try again. The Retry-
response header indicates when the limit resets.