Installation
Requirements
| Requirement | Notes |
|---|---|
| PHP | ^8. |
| TYPO3 | ^14. (v14.3 LTS only) |
| netresearch/nr-llm | ^0. — AI access (completion, TTS,
image), budget enforcement and one-click configuration presets. |
| netresearch/nr-vault | ^1. — holds the provider keys nr-llm reads; its
technical-actor API lets the worker read them (see
Extension settings). |
PHP extension curl (recommended) | Fetching url and pdf_ sources. With it the time limit covers
the whole transfer including the response headers; without it a server
that sends its headers very slowly can hold the worker. |
poppler- | pdftoppm / pdftotext for PDF ingestion (Vision OCR and layout
tiers). |
ffmpeg / ffprobe | Concatenate the podcast MP3 segments and measure segment durations for the WebVTT cue timing. |
chromium | Headless browser the Node renderer drives to turn HTML into PNGs. |
| Node.js | >=22. to run the bundled render. (uses
playwright-). |
The version ranges are the ones composer. requires; that file is
authoritative.
Note
The system binaries (poppler-, ffmpeg, chromium) are not
PHP dependencies — they must be present on the host (and on the worker host).
In the bundled DDEV environment they are baked into the web image.
Composer installation
composer require netresearch/nr-repurpose
This pulls in nr-llm and its own dependencies. After installation, set up the extension's database tables and activate it:
vendor/bin/typo3 extension:setup nr_repurpose
vendor/bin/typo3 cache:flush
The extension creates two tables:
| Table | Purpose |
|---|---|
tx_ | One row per generation run (source, selected artifacts, theme, status, progress). |
tx_ | One row per produced artifact (type, variant, FAL file references, transcript, metadata, status). |
Classic mode (TER) is not supported
Warning
nr_repurpose requires a Composer-based TYPO3 installation. Installing it through the Extension Manager (classic mode) is not supported.
The extension needs code that only a Composer installation provides:
- A PHP library. PDF ingestion uses
smalot/pdfparser
, which
composer.requires. The TER package contains nojson vendor/directory, so the library is missing in classic mode. - The Node renderer's dependencies. The TER package ships only
Resources/, without thePrivate/ Node Renderer/ render. cjs package.andjson package-that Install the Node renderer installslock. json playwright-from. Without them the Schaubild, story, slide deck and handout cannot be rendered.core
The extension is listed in the TYPO3 Extension Repository as nr_repurpose so it can be found there. Install it with Composer as described in Composer installation.
Install the Node renderer
The image renderer is a small Node script under
Resources/. Install its single dependency
(playwright-) and rely on the system chromium instead of letting
Playwright download its own browser:
cd Resources/Private/NodeRenderer
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm ci
The renderer starts the Chromium binary at /usr/. For another
path, see Renderer environment.
Hand the provider key to nr-llm
nr_repurpose never reads an API key — it owns no provider credentials at all. Give the key (the examples use OpenAI, the tested default) to nr-llm, which stores it and hands back the identifier its records reference.
The normal route is nr-llm's setup wizard in the TYPO3 backend: enter the key, and nr-llm stores it securely and generates the key identifier for you. How it keeps the secret is nr-llm's business and documented there.
Two places then refer to that identifier, both of them nr-llm's: the Provider
record carries it for the chat and vision completions, and nr-llm's extension
configuration carries it as providers. for the
specialized text-to-speech and image services. The Configuration records
nr_repurpose ships as presets bake in no provider, model or key at all. See
nr-llm wiring: providers, models, Configurations.
Note
For scripted installs where no one can operate the wizard, nr-llm's storage
backend can also be filled from the command line — that is what the bundled
DDEV setup does, seeding the identifier nr_. See
Local development with DDEV.
Run the generation worker
Generation runs asynchronously: job submission only dispatches a message, and a Symfony Messenger worker does the actual work. Run a long-lived consumer on a host that has the system binaries and the Node renderer installed:
php -d memory_limit=1G vendor/bin/typo3 messenger:consume doctrine --time-limit=3600 --memory-limit=512M
Restart the consumer in a loop (systemd, a container restart policy, or a supervisor) so it survives the deliberate time/memory limits that recycle the process. The transport routing is configured in Messenger routing.
Important
The PHP memory_ must exceed Messenger's -- soft
restart threshold, with headroom for GD image compositing — otherwise PHP
fatals before Messenger can recycle the process, and the unacknowledged
message is redelivered into the same crash (re-running paid AI calls). The
compositor pre-flights its memory need and fails the single artifact
gracefully, but only within the limit PHP actually has.
Note
The worker host runs chromium and ffmpeg and reaches the configured
AI providers — bound the outbound HTTP timeout (see HTTP timeouts)
so a stalled provider response cannot hang the worker indefinitely.
Local development with DDEV
The repository ships a DDEV setup whose web image already contains
poppler-, ffmpeg and chromium, and a sidecar worker container:
cp .ddev/.env.dist .ddev/.env # then set OPENAI_API_KEY=sk-…
ddev start # builds the web image
ddev setup # composer install + TYPO3 setup into .Build/Web
ddev setup installs TYPO3 v14.3 into .Build/, seeds the OpenAI
key into nr-vault under nr_, wires the nr-llm provider and
the messenger routing in config/, and installs the
Node renderer. The backend is then at https://.