Form Forge: Visual Form Builder for ODK

I've made this visual form builder for xforms/xlsforms that is fully client based (data never leaves the browser) and will really appreciate some feedback :heart_eyes:

Demo: https://punkch.github.io/form-forge
Code: https://github.com/punkch/form-forge
Features: https://github.com/punkch/form-forge#features
Change Log: https://github.com/punkch/form-forge/blob/main/CHANGELOG.md

Highlights:

  • Visual editor ~40 question types, drag-and-drop question tree with keyboard commands, property panel, undo/redo, autosave, crash snapshots, form template library
  • Multi-select & clipboard — Ctrl/Shift-click (and Ctrl+A) selection in the canvas with cut/copy/paste/delete acting on the whole selection, one undo step per action; paste works across forms and browser tabs (names de-duplicated, choice lists brought along, translations matched to the target's languages with anything dropped reported); the selection moves together by drag or Alt+Arrows, including into groups. A canvas toolbar hosts undo/redo, the clipboard actions, a selection counter and the form menu — including "Insert from template", which appends a template's questions to the open form
  • Real preview, not a mock — the same engine ODK Central serves renders your form as you build it, including relevance logic, constraints, cascading selects, external datasets, entities and translations. The preview follows the question you're editing, switches between device presets, and lets you test-fill and inspect the submission XML without anything leaving the browser.
  • pyxform-parity XForm generation — the serializer's output is golden- tested against pyxform 4.5.0 (tests/golden/) — entities, multilingual itext and label media included — so generated forms behave exactly like XLSForm-converted ones.
  • Native XLSForm engine — imports and exports .xlsx workbooks fully client-side, with row-level import reports telling you exactly what was read and what was skipped; the first in-browser XLSForm converter (everything else in the ecosystem calls pyxform on a server).
  • Lossless round-trips — unknown columns, custom bind/body attributes and unrecognized XForm fragments are preserved through import → edit → export; forms travel as XForm XML, XLSForm .xlsx, or either bundled in a ZIP with every media/CSV attachment — and the same bundle imports back, attachments and all.
  • Form logic without syntax — a visual condition builder for relevance and constraints with ALL/ANY groups, constraint presets (ranges, phone, email…) and calculation templates, with the raw expression editor always one click away; a live problems panel with click-to-navigate catches broken references and expressions before your enumerators do.
  • Multilingual forms without the footguns — labels, hints, guidance, validation messages, choice labels and per-language media in one translations grid; a monolingual form's text simply becomes the first language you add — no "Default" pseudo-language that ODK clients would never show — and mixed-language imports auto-merge, with leftovers kept visible until you resolve them.
  • Label media & image annotation — attach an image (with zoomable big-image), audio or video to any question, group or choice label — shared across languages by default, overridable per language — and give image questions a draw-on-top template; the attachment manager flags missing files, previews images and datasets in place, and a rename updates every reference in one undo step.
  • Direct to ODK Central, opt-in — publish drafts (definition + attachments) to any number of Central servers, track every destination with a local freshness check and one-click re-publish, and import forms back — even never-published drafts — without leaving the builder. It stays invisible until you add a server; credentials are encrypted at rest in a passphrase-derived vault that never leaves your device, and every connection is manual — no background sync, no telemetry. Requires a one-time CORS setup on (or in front of) your Central server.
  • Works fully offline — installable PWA that precaches the entire app (preview engine included) and updates itself from the hosting site; a one-file workspace backup carries your whole library — forms, attachments, templates, Central config and preferences — between machines.
  • Embeddable — host applications can drive the builder in an iframe over a postMessage API: load a form, let the user edit, get the full configuration (attachments included) back — with theme, accent, contrast and language under the host's control.
  • Accessible, themeable, in your language — English, French and Spanish UI aligned with ODK's own terminology, light/dark/system color schemes with six accents, a WCAG-AAA high-contrast mode, and WCAG-AA conformance by default — contrast-clamped accents and a screen-reader- friendly UI, held to zero violations by an automated axe audit — all styling the builder and the live preview as one.
1 Like

I used it for a form to make it easier for me to translate. I like it a lot, the only gripe I have is the fact that it's in light theme. It's quite hard to see buttons and texts for me due to my cataract, if you had an option to change themes to dark mode or dark high contrast, that'd be better.

Another is the export, 1 option states "ZIP with attachment" but it's just a ZIP file with the xml inside it. It should be easier to identify what it does if it says "XML" instead and never zips it. On the other hand, in the overall forms list, there I suggest putting an "Export all to:" then a list of options "ZIP with xlsx" and "ZIP with xml".

I've made a lot of changes recently and updated the highlights in my main post. Most of the changes were around improving usablity, accessability and most importantly for my use case - integration with Central.

@didotb In Settings, there is now light & dark modes and it is also possible to change the primary color and turn high contrast mode.

1 Like