Voxta docs
DevelopersModules

Configuration UI

Declare the settings page users see when they install your module.

Every module needs settings: API keys, endpoint URLs, model choices, toggles, sliders. Voxta renders the settings UI for you — you declare the fields, Voxta handles persistence, validation, and rendering.

The pattern

There are three pieces:

  1. A typed settings record (Models/MySettings.cs) — your in-code representation, plain init-only properties.
  2. A ModuleConfigurationProvider (Configuration/ModuleConfigurationProvider.cs) — declares the form fields the UI renders, and maps form data into your typed record.
  3. The registration in VoxtaModule.cs — points the framework at your provider.
builder.Register(new ServiceDefinition
{
    // ...
    ModuleConfigurationProviderType = typeof(ModuleConfigurationProvider),
    ModuleConfigurationFieldsRequiringReload = ModuleConfigurationProvider.FieldsRequiringReload
});

The settings record

public record MySettings
{
    public string ApiKey { get; init; } = "";
    public string Endpoint { get; init; } = "https://api.example.com";
    public bool EnableFeatureX { get; init; } = true;
    public int MaxRetries { get; init; } = 3;
}

This is the only type your business logic should see. Don't pass ISettingsSource around — convert it once, then work with the typed record.

The provider

public class ModuleConfigurationProvider : ModuleConfigurationProviderBase, IModuleConfigurationProvider
{
    public static readonly FormPasswordField ApiKeyField = new()
    {
        Name = "ApiKey",
        Label = "API key",
        Text = "Get yours at https://example.com/account."
    };

    public static readonly FormTextField EndpointField = new()
    {
        Name = "Endpoint",
        Label = "Endpoint URL",
        DefaultValue = "https://api.example.com"
    };

    public static readonly FormBooleanField EnableFeatureXField = new()
    {
        Name = "EnableFeatureX",
        Label = "Enable feature X",
        DefaultValue = true
    };

    public static readonly FormIntField MaxRetriesField = new()
    {
        Name = "MaxRetries",
        Label = "Max retries",
        DefaultValue = 3,
        Minimum = 0,
        Maximum = 10
    };

    public static MySettings ToSettings(ISettingsSource settings) => new()
    {
        ApiKey = settings.GetRequired(ApiKeyField),
        Endpoint = settings.GetRequired(EndpointField),
        EnableFeatureX = settings.GetRequired(EnableFeatureXField),
        MaxRetries = settings.GetRequired(MaxRetriesField)
    };

    public static readonly string[] FieldsRequiringReload =
    [
        ApiKeyField.Name,
        EndpointField.Name
    ];

    public Form GetForm() => new Form
    {
        Fields =
        [
            ApiKeyField,
            EndpointField,
            EnableFeatureXField,
            MaxRetriesField
        ]
    };
}

Form field catalog

The framework provides typed field classes for every common UI input. Pick the one that matches your data:

Field typeUIUse for
FormTextFieldSingle-line textURLs, names, free text
FormPasswordFieldMasked inputAPI keys, secrets
FormMultilineFieldMulti-line text areaPrompts, long config
FormBooleanFieldToggle / checkboxOn/off toggles
FormIntFieldNumber inputInteger counts, ports
FormDoubleFieldNumber inputDecimal values (temperature, scales)
FormChoicesFieldDropdown (single select)Fixed list of options
FormMultipleChoicesFieldMulti-selectCheckbox list
FormEnumFieldDropdown from a C# enumWhen the values are an enum
FormMultipleEnumFieldMulti-select from a C# enumFlag-like enum selections
FormModelFieldModel pickerLLM / TTS / vision model selection
FormAssetFieldAsset pickerFile reference (character image, voice sample)
FormStringListFieldEditable string listURLs, keyword lists
FormIntListFieldEditable int listPort ranges, IDs
FormArrayOfObjectsFieldRepeatable nested objectList of configured items, each with multiple fields
FormTitleFieldSection headingVisual grouping in the UI
FormDocumentationFieldMarkdown blockInline help text, links, warnings
FormInvokeActionFieldButtonTriggers a server-side action (test connection, refresh model list)
FormConnectionFieldConnection pickerReuses a saved connection (e.g. a shared API key)
FormHiddenField(hidden)Persisted state not shown to the user
FormAuthorizeFieldOAuth flowBrowser-redirect-style authorization
FormLoraListFieldLoRA selectorStable Diffusion LoRA configuration

Every field has at minimum Name (must match a setting in your record) and Label. Most support Text (help text), DefaultValue, and validation properties (Minimum, Maximum, Required, etc.).

Required vs optional

ApiKey = settings.GetRequired(ApiKeyField);     // throws if not set
Endpoint = settings.GetOptional(EndpointField); // returns null if not set

GetRequired is checked at form-validation time — users can't save without a value. Use it for anything your code can't run without. GetOptional is for genuinely optional fields.

FieldsRequiringReload

If a user changes a value in a field listed here, Voxta tears down your service and re-initializes it. Use it for anything that affects long-lived state the service set up at init:

  • API endpoints or keys (the HTTP client is rebuilt)
  • File paths the service watches
  • Anything passed to a singleton dependency

Don't include fields whose values are read fresh on every chat instance — those don't need a reload.

Reference

The voxta-module-elite-dangerous source declares over 70 fields across booleans, sliders, dropdowns, scan-code mappings, and section titles. Read it as a worked example covering most field types.

On this page