Feature modules

Synaplan's core — chat, documents and RAG, assistants, the widget, the API — runs on every installation. Around that core sit optional features: sidecar services, extra AI providers, payment channels and messaging channels that an installation may or may not have. Each of those is a feature module.

A module is switched on by its configuration, never by a build flag: set the environment variable (or paste the key in the admin UI) and the feature exists; leave it empty and the platform behaves as if the feature was never written. The Docker image, the API surface and the documentation are the same everywhere — what differs is which modules an operator has configured.

This section has one page per module. Every page answers the same four questions: what the module adds, what happens without it, how to enable it, and how to check that it works.


The modules

Module Id What it adds Switched on by
Apache Tika tika Text extraction from PDFs and Office files TIKA_BASE_URL
Docling docling Layout-aware document conversion (tables, headings) DOCLING_BASE_URL
Office conversion office_convert PDF export, thumbnails, previews, combine-as-PDF via Collabora OFFICE_CONVERT_URL
SearXNG web search searxng Self-hosted web search — no query leaves your network SEARXNG_BASE_URL
Piper text-to-speech piper_tts Spoken answers from a local voice service SYNAPLAN_TTS_URL
Local AI (Ollama) local_ai Chat and embedding models on your own hardware OLLAMA_BASE_URL
Higgsfield higgsfield Cinematic image and video generation HIGGSFIELD_API_KEY + HIGGSFIELD_API_SECRET
Google AI google_ai Gemini chat and vision, Imagen, Veo, transcription Google API key (env or admin UI)
TheHive thehive Flux and SDXL image generation THEHIVE_API_KEY
Stripe billing stripe_billing Paid tiers, checkout, top-ups, billing portal Real Stripe keys and price ids
Mobile in-app purchases mobile_iap Apple / Google subscriptions for your own app build IAP_PRODUCT_*
WhatsApp channel whatsapp The assistant answers on WhatsApp WHATSAPP_ENABLED + access token

Everything not in this table — widgets, OIDC/SSO, e-mail channels, MCP, Synaplan Desktop — is core or has its own switch and is documented on its own page.


Where you see them

Operate → Feature Status (/admin/features, admin only) lists every module with a state badge, the one-line status message, and which keys configure it — key names only, never values. Each row links to its page here.

The same information is available on the command line, which is what you want on a server without a browser:

docker compose exec backend php bin/console app:modules:list          # table
docker compose exec backend php bin/console app:modules:list --json   # same shape as the API below

And in the API:

  • GET /api/v1/config/features (admin) — a modules array with id, state, configured, healthy, message, details, configured_by, capabilities, docs_anchor.
  • GET /api/v1/config/runtime (every user) — modules: { "<id>": { "configured": bool, "gated": bool } }, which the web app uses to hide surfaces of absent modules.

The three states

Badge Meaning Typical cause
Not installed The module's configuration is empty. Nothing is probed. The variable is unset, or set to disabled.
Needs setup Configured, but the service did not answer its health check. Sidecar not started, wrong URL, network policy, container still warming up.
Available Configured and the health check passed.

Configured is decided from the configuration alone and costs nothing; only configured modules are probed, and each probe has a short timeout. A key you paste into the admin UI counts within five minutes at most — no restart.


What happens without a module

The rule is degrade, never break:

  • Sidecars fall back. A missing Docling hands the document to Tika; a missing Collabora leaves Office files searchable but without thumbnails or PDF export; a missing SearXNG means chat searches through the cloud provider you selected instead.
  • Providers hide their models. Without a Google key the Gemini rows simply are not offered.
  • Commerce stays off. Without Stripe the install runs in open-source mode: no plans, no quotas, no upgrade prompts.
  • Channels show a notice. The WhatsApp card on Channels becomes a short "WhatsApp channel is not available on this installation" notice with a How to enable it link to the module's page; admins additionally get Open feature status.

The feature_not_configured answer

An API request that only makes sense for an absent module can answer

HTTP 404
{ "error": "feature_not_configured", "module": "whatsapp", "docs": "modules/whatsapp" }

instead of a generic error. The web app turns this into the same notice. Which routes belong to a module is declared by the module itself; health, runtime config, API docs, the routes an admin uses to configure a module, and the store / Meta webhooks that must keep their own status codes are never in that list.

Gates are opt-in

That 404 is only sent while the module's gate is on. Gates are per-module BCONFIG rows, group MODULES, setting GATE_<ID> (upper-case module id: GATE_WHATSAPP, GATE_STRIPE_BILLING, …). They are seeded off, so an existing installation keeps answering exactly as it did before modules existed. A configured module is never gated regardless of the flag.

Turn a gate on under Operate → System configuration (group MODULES), or in SQL:

INSERT INTO BCONFIG (BOWNERID, BGROUP, BSETTING, BVALUE)
VALUES (0, 'MODULES', 'GATE_WHATSAPP', '1')
ON DUPLICATE KEY UPDATE BVALUE = '1';

No restart is required; the next request reads the new value.


Minimal installations

A stack with no module configured is a supported target, not an accident. The production deploy/compose.yaml starts with Tika only; every other module waits for you to set its variable or add its Compose profile. The developer compose files are wired differently: they pre-fill the sidecar URLs (http://docling:5001, http://collabora:9980, …) so that starting a profile is enough — which is why a fresh dev stack shows those modules as Needs setup rather than Not installed until the container is up. The CI lane that proves the core carries no optional feature uses:

docker compose exec backend php bin/console app:modules:list --assert-none-configured   # exit 1 if any module is configured

Related pages