★ New · feat/form-builder

Point your pole layer at it. Get an inspection form.

The Dynamic Form Builder introspects a PostGIS asset table or a GeoPackage vector layer — poles, transformers, spans, damage reports — and generates a complete, validated data-entry form: labels, types, options, geometry handling, and layout, rendered to live HTML. Pair it with the offline-capable field-collection PWA and crews capture inspections and damage assessments with zero infrastructure.

PostGISGeoPackageJSON Schema HTML · React · Vue · AngularValidationDuckDB-WASMPWA · offline
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 typesText, 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": "Pole Inspection",
  "title": "Pole Inspection 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

The visual Form Builder designer includes PostGIS and GeoPackage table discovery, schema validation, and live interactive form previews.

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 — built for damage assessment in storm-hit territory with no backhaul.

  • 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 asset schema to inspection form in minutes

Generate validated forms from the asset layers you already have, render them anywhere, and collect offline — all from one desktop. VoltGrid works operationally with GRID State, so structured field data supports the utility's operational picture.