Skip to content

Building a Custom Engine ​

An engine is a manifest that names a core version and a set of question components, built into one self-contained HTML file. You build a custom engine when you need question types Medipal does not ship, a different look and feel for a programme, or behaviour tailored to a device or population.

There are two ways to build one, and they share the same manifest format:

MethodBest for
Engine Editor in the admin web appEditing components in the browser with a live preview, and publishing to the instance's engine store with one click. See Engine Editor.
Engine builder tool (command line)Working in your own repository with your own editor, tests and CI; building bundles for hosting elsewhere.

Prerequisites ​

  • A current Node.js LTS runtime, for the builder tool.
  • Access to a published questionnaire core (the manifest of the core you are building against). Cores are listed in the Engine Editor and registered on folders.
  • Familiarity with Vue 3 single-file components. Question components are Vue components.
  • A place to host the result: the instance's engine store (via the Engine Editor) or any static file host you control.

The engine manifest ​

The manifest is the single source of truth for an engine. It carries the metadata, the core reference and the full source of every component and shared file as strings, which is what lets the web app edit and rebuild an engine without a repository.

json
{
  "id": "clinic-engine",
  "name": "Clinic Engine",
  "icon": "lucide:stethoscope",
  "description": "Question set for the outpatient PROM programme",
  "version": "1.0.0",
  "core": {
    "id": "questionnaire-core",
    "version": "<core version>",
    "baseUrl": "<where the core is published>",
    "packageName": "questionnaire-core-<core version>",
    "main": "<core script file>",
    "style": "<core stylesheet file>",
    "files": ["<core script file>", "<core stylesheet file>"]
  },
  "components": [
    {
      "name": "numeric",
      "label": "Numeric",
      "icon": "lucide:hash",
      "mainFile": "NumericRenderer",
      "files": {
        "NumericRenderer.vue": "…component source…",
        "Schema.json": "…settings schema…",
        "UISchema.json": "…settings form layout…"
      }
    }
  ],
  "sharedFiles": {
    "BaseAnswer.vue": "…",
    "i18n.ts": "…"
  }
}
FieldPurpose
id, versionTogether they form the package name of the built bundle. Increase the version for every published change; hosts and questionnaires bind to a specific version.
name, icon, descriptionShown in the Engine Editor list and on the questionnaire's configuration page.
coreWhich core to build against. Copy this block from the core's published manifest; do not hand-edit individual entries.
componentsOne entry per question type. name is the question type identifier used in questionnaires; label and icon appear in the designer's question palette; mainFile is the component file (without extension).
components[].filesThe component's source files. Schema.json and UISchema.json describe the type's settings form in the designer (see Custom Question Components).
sharedFilesFiles every component can import: base UI pieces, translation helpers, utilities.

Built-in question types ​

The default engine ships these components. A custom engine can reuse them as-is, modify them or drop them.

TypeWhat it renders
numericNumber input with unit, minimum/maximum, step and locale-aware formatting
singleChoiceOne option from a list
multipleChoiceSeveral options from a list
sliderVertical slider with labelled ends and optional tooltip
dateCalendar: single date, several dates or a range, with past/future restrictions
textFree text with length limits

A page type (text only) is always available and needs no component.

Build with the builder tool ​

The builder generates the engine's entry files from the manifest, downloads the referenced core, and bundles everything into a single HTML file.

  1. Create a project from the engine builder template and place your manifest in it.
  2. Generate the sources from the manifest. This downloads the core and writes the component files to disk. Repeat after every manifest change.
  3. Run the dev server. Two pages are served: the engine itself (blank until a host initialises it) and a preview harness that loads the engine in an iframe, lets you paste a questionnaire, choose the language and sections, toggle a phone-sized frame, and shows the submission payload as it comes back.
  4. Build the bundle. The output is a folder named after id and version containing index.html and a generated manifest.json that adds the question type definitions (name, label, icon, settings schema and form layout) read by the designer.
  5. Publish the folder to the location referenced by your engine's base URL, keeping the folder name unchanged.

Helper commands exist to switch the engine to a newer core (fetch a core manifest and patch the core block) and to load an existing engine manifest from a URL so you can fork a published engine.

Register and use the engine ​

  1. Open the folder in which the engine should be available and add the engine's URL (the folder containing manifest.json) to the folder's list of questionnaire engines. Nested folders inherit the list; see Folders & Configuration.
  2. Create a questionnaire in that folder; the create dialog offers the folder's engines.
  3. For an existing questionnaire, open its configuration and choose Change Engine, entering the engine URL. The designer palette updates to the engine's question types.
  4. Publish the questionnaire. Its definition now carries the engine identity, and every host loads that bundle.

Upgrading the core ​

  1. Fetch the new core's manifest and replace the core block of your engine manifest (the builder has a command for this).
  2. Regenerate, run the preview, and check each component against the core's changelog, which is included in the core manifest.
  3. Increase the engine version, build and publish.
  4. Move questionnaires to the new engine version from their configuration page when you are ready; already published questionnaires keep the version they were published with.

Checklist before publishing ​

  • Every question type used by your questionnaires has a component in the manifest.
  • Each component has a Schema.json and UISchema.json, or the type has no settings.
  • All translations you rely on exist for every language the folder allows.
  • The bundle renders correctly in the preview harness in both colour modes and at 120% zoom.
  • Validation blocks Next for required questions and clears when fixed.
  • The submission payload contains a value and value_type for every answer.
  • The version number is new.