โ˜… New ยท Form Builder

Point a layer at it. Get a form.

The Dynamic Form Builder introspects a PostGIS table or a GeoPackage vector layer and generates a complete, validated data-entry form - labels, types, options, geometry handling, and layout - then renders it to live HTML. Pair it with the offline-capable field-collection PWA to collect, edit, and export spatial records with zero infrastructure.

PostGISGeoPackageJSON Schema HTML ยท React ยท Vue ยท AngularValidationDuckDB-WASMPWA ยท offline

Form Builder walkthrough - navigating between forms

How it works

Schema-first, not hand-drawn

No more re-keying column names into form fields by hand. The service reads the real column metadata - data type, nullable, max-length, precision, primary/foreign keys, geometry type and SRID - and turns each column into a typed, validated FormField. Exclude the noise, keep the structure.

  • Two live sources - PostGIS tables (/generate/postgis) and GPKG vector layers (/generate/gpkg); schema preview for both before you commit.
  • 21 inferred field types - Text, Number, Date/DateTime, Boolean, Select, Geometry, Json, Color, Range and more - with auto-generated labels and grouping.
  • 6 layout strategies - Vertical, Horizontal, Grid, Tabs, Accordion, and multi-step Wizard; responsive by default.
  • Generation options - toggle geometry / primary-key / foreign-keys inclusion, group related fields, infer types, generate validation, and exclude columns like created_by.
POST /api/dynamicform/generate/gpkg
// GPKG layer โ†’ typed form (shared by PostGIS path)
{
  "formName": "Building Survey",
  "title": "Building Survey Data Entry",
  "filePath": "Data/GPKG/survey_points.gpkg",
  "layerName": "survey_points",
  "geometryColumn": "geom",
  "primaryKey": "fid",
  "options": {
    "includeGeometry": true,
    "groupRelatedFields": true,
    "generateValidation": true,
    "excludedColumns": ["created_by", "updated_at"]
  }
}
โ†’ DynamicForm with N typed FormFields
โ†’ render to HTML / React / Vue / Angular
Generation & options

From column metadata to a usable form

Every FormField carries its own type, constraints, options, validation rules, and the original ColumnInfo it was derived from - so the form stays truthful to the underlying table even after you override individual fields.

๐Ÿ”Ž

Introspection

Reads data_type, nullability, max_length, precision/scale, PK/FK, and is_geometry + geometry_type + srid straight from the layer.

๐Ÿท๏ธ

Auto labels & grouping

autoGenerateLabels humanizes column names; groupRelatedFields clusters them into collapsible FormGroups and FormSections.

โœ…

Validation

generateValidation emits Required, MinLength/MaxLength, MinValue/MaxValue, Pattern, email/url/phone rules per field.

๐ŸŽ›๏ธ

Field overrides

Per-field fieldOverrides let you swap widgets, set defaults, placeholders, help text, or mark a column read-only - without touching the source table.

๐Ÿ“

Geometry aware

Geometry columns map to a Geometry field type; opt in via includeGeometry so the form can capture or edit the feature shape alongside attributes.

๐Ÿ—‚๏ธ

Templates

Three starters - basic, grouped, complete - returned from GET /api/dynamicform/templates to bootstrap a new survey fast.

The API surface

Generate, preview, render, manage

CapabilityEndpointNotes
Generate (generic)POST /api/dynamicform/generateSingle request body, picks source by DataSourceType
Generate from PostGISPOST /api/dynamicform/generate/postgisConnection string + table + schema + geom/PK columns
Generate from GPKGPOST /api/dynamicform/generate/gpkgFile path + layer name + geom/PK columns
PreviewPOST /api/dynamicform/previewEstimated field count & layout, no full generate
SchemaPOST /api/dynamicform/schema/{postgis,gpkg}Raw column metadata before building a form
RenderPOST /api/dynamicform/{id}/renderReturns html + css + javascript
Standalone HTMLGET /api/dynamicform/{id}/html?theme=Full <!DOCTYPE> page, ready to host
ManageGET ยท DELETE /api/dynamicform/{id}Fetch or remove a stored form
TemplatesGET /api/dynamicform/templatesbasic ยท grouped ยท complete presets

In-app designer ships at /form-builder.html with PostGIS / GPKG tabs, options checkboxes, and a live Form Preview panel. Source: Controllers/DynamicFormController.cs, Services/DynamicFormService.cs, Services/FormRenderingService.cs, Models/FormModels.cs.

Render targets

Five output formats, one schema

The FormRenderFormat enum emits to the framework you already use - so a generated survey can drop straight into an existing app, not just the in-app preview.

๐ŸŒ

HTML

Standalone, themed HTML with inline CSS + JS - host it anywhere or embed it in the desktop preview.

โš›๏ธ

React

React-renderable output for Next.js / SPA integration.

๐Ÿ’š

Vue

Vue-renderable output for Vue 3 apps.

๐Ÿ…ฐ๏ธ

Angular

Angular-renderable output for enterprise Angular shells.

{ }

JSON

Portable JSON Schema for any RJSF-compatible renderer or downstream pipeline.

๐ŸŽจ

Themes

Pass ?theme=default on the HTML route to swap the look without regenerating the form.

Field collection PWA ยท form_builder/

Take it to the field - offline

A bundled Next.js PWA (geospatial-form-builder) turns generated designs into a real data-collection app. Built on MapLibre GL JS and DuckDB-WASM, it runs fully offline with no CDN dependencies, stores records in-browser, and exports to the formats your GIS expects.

  • Four design on-ramps - import an Appsmith JSON design, reverse-engineer a schema from an existing DB (SQLite / GPKG / Spatialite / ODBC / MySQL / Postgres), prompt an in-browser LLM for a starter form, or import your own JSON.
  • Spatial field components - capture Lat/Long (DD or DMS), MGRS, USNG, and GARS, with map click-to-select and geometry editing.
  • Related tables, attachments & conditional logic - inline child records, photo/video/document blobs, and rules that show/hide fields based on other answers.
  • Map-backed attribute grid - sync the table to the map bbox, or query the nearest records to a point; click a row to zoom and open its form.
  • Export - GeoJSON, CSV, Shapefile, or GeoPackage, straight from DuckDB-WASM.
form_builder/ ยท package.json
// offline PWA stack (no CDN, no internet required)
{
  "name": "geospatial-form-builder",
  "dependencies": {
    "next": "^16.2.10",
    "react": "^19.2.7",
    "maplibre-gl": "^5.24.0",
    "react-hook-form": "^7.81.0",
    "lets-form": "^0.13.1"
  },
  "devDependencies": {
    "@ducanh2912/next-pwa": "^10.2.9",
    "tailwindcss": "^4.3.3"
  }
}
โ†’ DuckDB-WASM via POST /api/duckdb/{id}/query
โ†’ installable, air-gap-ready
PWA field components

Purpose-built for geospatial collection

The FormBuilder, FormDesigner, and specialized fields below are the building blocks the PWA composes - each driven by a JSON Schema + UI Schema pair.

๐Ÿ› ๏ธ

FormBuilder

Render a schema-driven form bound to a DuckDB table; onSubmit/onChange/onError hooks, readonly & disabled modes, reset button.

๐ŸŽจ

FormDesigner

Visual schema editor with live preview - edit JSON Schema + UI Schema side by side and save the result.

๐Ÿ“

SpatialFormField

Capture Lat/Long (DD & DMS), MGRS, USNG, GARS - with optional map click-to-select.

๐Ÿ“Ž

AttachmentField

Drag-and-drop photos, video, and documents; preview, type/size validation, stored as blobs.

๐Ÿ”—

RelatedTableField

Inline add / edit / remove child records with a sortable, filterable, paginated table view.

๐Ÿ”€

Conditional & Chained

ConditionalField shows fields on rules; ChainedSelectField loads dependent options async.

๐ŸŽ™๏ธ

Voice-enabled

VoiceEnabledForm + VoiceFormControl fill fields by voice command (Qwen3-backed).

๐ŸŒ

Translation & TTS

Inline translate between languages and read-back text-to-speech for accessibility.

๐Ÿ”

Re-survey

Update previously collected records in place - versioned edits, not duplicate rows.

From schema to survey in minutes

Generate validated forms from the layers you already have, render them anywhere, and collect offline - all from one desktop.