Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

TEDY.18 — Configuration & environment variables

State: Built — env surface implemented. Prefixes VITE_/TX_/TEDY_/OAUTH_ are allow-listed in vite.config.ts; all vars are read + defaulted in src/config/tx.ts. Wired features consume them now; not-yet-ported services read the var but carry a TODO(TEDY.18) until the feature lands. Template: tool-feature. Prefix: TEDY.

Why

The reference editor’s web app is configured entirely through a runtime web.env (Docker env), and its API through a server.env. TEDY, by contrast, is a federated module hosted inside the EMR shell, so most of the reference’s frontend configuration is either (a) already covered by a small set of VITE_* build/runtime vars, (b) owned by the host shell (auth, UI language, theming, branding), or (c) out of scope because the corresponding feature (FML editor, PlantUML, FSH/SUSHI “chef”, FHIR→UML, Swagger UI) is not ported.

This spec is the single place that:

  1. lists the full reference frontend config surface and what each var does;
  2. maps each var to its TEDY equivalent, or records why it is host-owned / out-of-scope;
  3. defines the recommended TEDY env list and neutral .env.example entries.

Source of truth: the reference project’s public installation guide plus a live reference dev deployment’s web.env / server.env. Per repository policy, no real hostnames, secrets, or brand strings are reproduced here — example values use neutral *.example placeholders, real values live only in the gitignored local .env, and reference env-var names are shown with their brand prefix normalized to TX_ (e.g. the reference’s server-API var appears as TX_API).

Why TEDY vars carry a VITE_ prefix

Vite only exposes env vars prefixed with VITE_ to client code through import.meta.env; every other var in the environment is deliberately withheld from the browser bundle so co-located server secrets (DB passwords, API keys) can’t leak into shipped JS. Any value the frontend must read therefore has to start with VITE_ (or a configured envPrefix). The reference web.env vars need no such prefix because they are not read by Vite — the reference container injects them into a generated runtime config at startup, whereas TEDY reads its config at build/serve time through Vite.

1. Reference frontend config (web.env) — full surface

VarPurposeExample valueTEDY disposition
BASE_HREFApp mount path for relative URLs/ or /tedyBuild-time — host mounts TEDY under its route
TX_APITerminology-server API base/apiPortedVITE_TX_TARGET
SWAGGER_URLSwagger UI path/swagger/❌ Out of scope (no Swagger UI in TEDY)
DEFAULT_LANGUAGEFallback UI languageen⚠️ Host-owned (@helex/i18n)
UI_LANGUAGESSelectable UI languages (JSON array)["en","et","lt","cs"]⚠️ Host-owned
CONTENT_LANGUAGESMultilingual content input languages (JSON array)["en","et","lt","ru","de","fr"]🟡 Candidate — drives TEDY’s localized-name editors
EXTRA_LANGUAGESDisplay-name overrides for extra content langs (JSON object){"cs":{"en":"Czech"}}🟡 Candidate (only with extra content langs)
OAUTH_ISSUEROIDC realm / issuer URLdummy or realm URL⚠️ Host-owned auth
OAUTH_CLIENT_IDOAuth2 client iddummy⚠️ Host-owned auth
OAUTH_SCOPEOAuth2 scopes at loginopenid⚠️ Host-owned auth
GUEST_DISABLEDDisable anonymous accessfalse⚠️ Host-owned auth
SNOWSTORM_URLSNOMED (Snowstorm) API basehttps://snowstorm.example/🟡 Candidate (TEDY reads SNOMED via backend /snomed; direct base only if deep-calling)
SNOMED_BROWSER_URLSNOMED browser deep-link basehttps://snomed.example/🟡 Candidate — TEDY has SNOMED search/global-search
SNOMED_BROWSER_DAILY_BUILD_URLSNOMED daily-build browser basehttps://snomed.example/🟡 Candidate (optional variant)
FML_EDITORFHIR Mapping-Language editor service/fml-editor❌ Out of scope (not ported)
PLANT_UML_URLPlantUML diagram service/plantuml❌ Out of scope
CHEF_URLFSH/SUSHI/GoFSH compiler service/chef❌ Out of scope (IG authoring)
CHEF_FHIR_VERSIONFHIR version for the compiler service4.3.0❌ Out of scope
FHIR_UML_CONVERTER_APIFHIR→UML converter servicehttps://svc.example/fhir2uml/api❌ Out of scope
SKIN / SKIN_URLNamed theme / external stylesheet(named theme)⚠️ Host-owned theming
BRANDINGProduct name in header(product name)⚠️ Host-owned (header is the EMR shell)

Legend: ✅ ported · 🟡 candidate to add · ⚠️ host-owned (inherited) · ❌ out of scope (feature not ported).

2. TEDY’s implemented env surface

All client-exposed vars are read once in modules/tedy/frontend/src/config/tx.ts. The proxy target and base are read Node-side in vite.config.ts. Prefixes: VITE_ (kept for backward compatibility + language vars), TX_ (terminology-server side integrations), TEDY_ (the app itself), OAUTH_ (auth).

App (TEDY_ prefix)

VarPurposeDefaultConsumedLegacy fallback
TEDY_TARGETTerminology-server API base (incl. api segment; differs per deployment, e.g. /api vs /lmb-api). Proxied /txapi → {target}.https://tx.example/api✅ vite proxyVITE_TX_TARGET
TEDY_BASE_HREFApp mount path (Vite base)./tedy/✅ vite base
TEDY_BRANDINGProduct name in TEDY-owned chrome.TEDY✅ document title (standalone)
TEDY_MSDEVOPS_ENABLEDOffer the Azure DevOps git integration on a Space’s Metadata + Repository tabs. Unset/0 hides it.0MSDEVOPS_ENABLEDVITE_TX_MSDEVOPS_ENABLED

Terminology-server integrations (TX_ prefix)

VarPurposeConsumedLegacy fallback
TX_PUBLISHER_VS_URLPublisher ValueSet canonical — resolves publisher display names.VITE_TX_PUBLISHER_VS_URL
TX_PUBLISHER_CS_URLPublisher CodeSystem canonical.VITE_TX_PUBLISHER_CS_URL
TX_VIEWER_TARGETTerminology eXplorer base — opens a resource’s web page + FHIR API from Servers → Resources.VITE_TX_VIEWER_URL
TX_SNOWSTORM_TARGETSnowstorm API base (direct calls; TEDY normally reads SNOMED via backend /snomed).🟡 exported; TODO
TX_SNOWSTORM_BROWSERSNOMED browser deep-link base.✅ Global Search SNOMED group
TX_SNOWSTORM_DAILY_BROWSERSNOMED daily-build browser base.🟡 exported; TODO
TX_CHEF_TARGET / TX_CHEF_FHIR_VERSIONFSH/SUSHI compiler (not ported).TODO
TX_PLANTUML_TARGETPlantUML service (not ported).TODO
TX_FHIR2UML_TARGETFHIR→UML converter (not ported).TODO
TX_SWAGGER_TARGETSwagger UI (not ported).TODO

Content / UI languages (VITE_ prefix, JSON-encoded)

VarPurposeDefault
VITE_DEFAULT_LANGUAGEFallback content language.en
VITE_UI_LANGUAGESSelectable UI languages.["en"]
VITE_CONTENT_LANGUAGESLanguages offered in localized-name editors.["en"]
VITE_EXTRA_LANGUAGESDisplay-name overrides for extra content languages.{}

VITE_CONTENT_LANGUAGES (+ VITE_EXTRA_LANGUAGES display names) feed every multilingual editor via components/TxLocalizedName (a thin AppLocalizedName wrapper injecting config/tx.ts’s CONTENT_LANGUAGE_OPTIONS). When the var is unset the editors keep their built-in default, so this is opt-in.

Auth (OAUTH_ prefix — host-owned in a deployment)

OAUTH_ISSUER, OAUTH_CLIENT_ID (exported for parity/dev), OAUTH_GUEST_DISABLED (false). ⚠️ Because OAUTH_ is allow-listed for the client bundle, never place OAUTH_CLIENT_SECRET (or any secret) in the frontend build environment — it would be exposed.

Legend: ✅ wired now · 🟡 read+exported, consumer wiring is a TODO(TEDY.18) · ⏸ feature not ported (config reserved).

3. Why the prefixes (and why not drop VITE_)

Vite exposes to the client only env vars matching envPrefix; everything else is withheld so co-located secrets can’t leak. We allow-list ['VITE_','TX_','TEDY_','OAUTH_']:

  • VITE_ is retained so pre-existing local envs and the language vars keep working — the rename is non-breaking.
  • TX_/TEDY_/OAUTH_ are TEDY’s own, human-readable prefixes.
  • An empty prefix ('') is forbidden — it would expose every var. Vite’s built-ins (import.meta.env.MODE/DEV/PROD/BASE_URL) are always present regardless of prefix.

4. Migration

Legacy names are still honored (via the VITE_ fallbacks in config/tx.ts and the Node-side proxy fallback), so nothing breaks on upgrade. To move an env file to the current names, use the copy-migrator (never mutates the source):

scripts/migrate-tedy-env.sh path/to/old.env            # → old.env.migrated
scripts/migrate-tedy-env.sh path/to/old.env new.env    # → new.env
scripts/migrate-tedy-env.sh path/to/old.env -          # → stdout

Old → new mapping applied by the script:

Legacy / reference nameCurrent name
VITE_TX_TARGETTEDY_TARGET
BASE_HREFTEDY_BASE_HREF
BRANDINGTEDY_BRANDING
VITE_TX_MSDEVOPS_ENABLEDTEDY_MSDEVOPS_ENABLED
DEFAULT_LANGUAGEVITE_DEFAULT_LANGUAGE
UI_LANGUAGESVITE_UI_LANGUAGES
CONTENT_LANGUAGESVITE_CONTENT_LANGUAGES
EXTRA_LANGUAGESVITE_EXTRA_LANGUAGES
VITE_TX_PUBLISHER_VS_URLTX_PUBLISHER_VS_URL
VITE_TX_PUBLISHER_CS_URLTX_PUBLISHER_CS_URL
VITE_TX_VIEWER_URLTX_VIEWER_TARGET
SNOWSTORM_URLTX_SNOWSTORM_TARGET
SNOMED_BROWSER_URLTX_SNOWSTORM_BROWSER
SNOMED_BROWSER_DAILY_BUILD_URLTX_SNOWSTORM_DAILY_BROWSER
CHEF_URLTX_CHEF_TARGET
CHEF_FHIR_VERSIONTX_CHEF_FHIR_VERSION
PLANT_UML_URLTX_PLANTUML_TARGET
FHIR_UML_CONVERTER_APITX_FHIR2UML_TARGET
SWAGGER_URLTX_SWAGGER_TARGET
GUEST_DISABLEDOAUTH_GUEST_DISABLED

The full neutral template lives in modules/tedy/frontend/.env.example; real values live only in the gitignored local .env.

Host-owned / out-of-scope (not TEDY vars)

Theming (SKIN, SKIN_URL) and UI shell are the EMR host’s; OAUTH_SCOPE and the SSO realm/client are host auth. FML_EDITOR has no TEDY consumer and is intentionally omitted.

5. Backend config (context only — not owned by TEDY)

The reference API (server.env) is a separate deployment concern; TEDY only talks to it through VITE_TX_TARGET. For orientation, its surface covers: PostgreSQL connection + pooling (DB_URL, DB_*_PASSWORD, DB_POOL_SIZE), CORS/JVM options, web/API self-URLs (TX_WEB_URL, TX_API_URL), OAuth JWKS validation, Snowstorm base + branch (SNOWSTORM_URL, SNOWSTORM_BRANCH), object storage (MinIO BOB_MINIO_*), the compiler service URL, a GitHub App (id/name/client id/secret) for content publishing, SMTP for notifications, and a conformance-validator target. Secrets (DB/object-store passwords, GitHub client secret, SMTP credentials) and real hostnames are intentionally not reproduced. These are provisioned per deployment by whoever operates the terminology server; nothing here is a TEDY frontend build input.

Open items (TODOs the vars are reserved for)

Wired: SNOMED browser deep-link (Global Search), content languages (all editors via TxLocalizedName), branding (document title). Remaining:

  • SNOMED daily-build browser (TX_SNOWSTORM_DAILY_BROWSER) and direct Snowstorm (TX_SNOWSTORM_TARGET) — no consumer yet (TEDY reads SNOMED via the backend /snomed).
  • Not-ported services (TX_CHEF_*, TX_PLANTUML_TARGET, TX_FHIR2UML_TARGET, TX_SWAGGER_TARGET) — consume when/if those features are ported.