Building forms
Themes
Give forms your brand colors and spacing. Themes are managed by admins and applied per form.
Theme properties#
| Property | Default | Styles |
|---|---|---|
primary_color | #2551ed | Submit and sign-in buttons, primary buttons and row actions, input focus ring, links, file drop zone hover. |
secondary_color | #6b7280 | Secondary buttons and row actions. |
danger_color | #ef4444 | Danger buttons and row actions. |
text_color | #111827 | Title, labels, subtitles, display values, table headers. |
background_color | #ffffff | Form background (and the hosted page background). |
column_gap, row_gap | 1 (rem) | Spacing of the field grid. |
is_default | — | Pre-selected for new forms in the editor. One per organization. |
Button text turns black or white automatically for contrast.
Applying a theme#
A form uses a theme when its config has theme_id. The editor sets this when you pick a theme; through the API or MCP, set it inside config:
{ "theme_id": "8d2e…", "showTitle": true, "fields": [ … ] }
Forms without theme_id use the built-in colors (and legacy buttonColor if set).
Creating a theme with an agent#
MCP: create_theme
{ "name": "Brand", "primary_color": "#0f766e", "secondary_color": "#64748b",
"danger_color": "#dc2626", "text_color": "#0f172a", "background_color": "#ffffff", "is_default": true }Deleting a theme doesn't check forms that reference it in config.theme_id; those forms silently fall back to the built-in colors. Reassign forms before deleting a theme.
Custom CSS#
For styling beyond themes, pass disableStyles: true to f2wf.load() and style the widget's classes yourself (theme colors are still injected). See Embedding.