An internal no-code/low-code platform for building nested, conditional forms without code. Every form compiles to a single normalized tree schema that a standalone renderer package and an API mapper share as one source of truth. Built to the PRD.
A pnpm monorepo with a clean separation between the framework-agnostic core, the presentational UI kit, the React renderer, the API, and the builder app.
packages/
form-schema @internal/form-schema Normalized tree schema types (nodes, conditions, compute, mapping)
form-renderer-core @internal/form-renderer-core Framework-agnostic engine: recursive walker, validation,
sandboxed expression evaluator, cycle detection, schema health
ui @internal/ui Standalone presentational component library + design tokens
form-renderer @internal/form-renderer React <FormRenderer> consuming core + ui (componentMap override)
apps/
backend @internal/backend Hono + TypeScript API (forms CRUD, draft/publish/versioning, mappings)
builder @internal/builder Vite + React builder UI (palette, canvas, inspector, preview, mapper)
- Form Builder — drag fields from a palette onto a canvas, nest them into option branches or containers, configure validation / conditional visibility / computed formulas, preview live, and publish immutable versions.
- Form Renderer (
@internal/form-renderer) —<FormRenderer schema initialValues onSubmit />plusvalidateForm,flattenSchema,getVisibleFields. Consuming teams theme it via acomponentMapoverride or use the shipped defaults. - API Mapper — map each flattened
fieldIdto a downstream API key (dot-notation, transforms, if-absent policy), preview the payload, and publish a versioned mapping pinned to a form version.
Nodes are stored flat in nodes keyed by id; structure is expressed via parentId +
children / childrenByOptionValue. A single recursive engine (resolve in
form-renderer-core) resolves computed values in dependency order, evaluates per-field validation
state, and walks visibility — supporting arbitrary depth, cross-branch visibleWhen rules,
validation-state–driven visibility (isValid / isInvalid / isAnswered), and computed fields
(including sum() aggregation across repeatable rows) without per-level special-casing.
pnpm install
pnpm build # build the four packages (schema, core, ui, renderer)
# run both apps (in separate terminals, or `pnpm dev` for both)
pnpm dev:backend # Hono API on http://localhost:8787
pnpm dev:builder # Builder UI on http://localhost:5173 (proxies /api → 8787)Open http://localhost:5173 and sign in. A seeded Business Onboarding (KYC) form demonstrates nesting, a cross-branch rule (GSTIN shows only for India), validation-state visibility (document upload appears once the registration number is valid), a computed full name, and a repeatable line-items group with a computed grand total.
State lives in a SQLite database at apps/backend/data/app.db (created and migrated on first
boot via node:sqlite; requires Node ≥ 22.5). The API requires authentication — every route
except /api/health and /api/auth/login expects an Authorization: Bearer <token> session.
Resources are owned by a team; members of that team can edit and publish, while everyone else has
cross-team read-only access (PRD §9).
Seeded demo accounts (all use the password password):
| Teams | |
|---|---|
ada@internal.dev |
Platform |
grace@internal.dev |
Growth |
alan@internal.dev |
Platform + Growth |
| Command | Description |
|---|---|
pnpm build |
Build all publishable packages |
pnpm typecheck |
Typecheck every workspace project |
pnpm dev |
Run backend + builder together |
pnpm --filter @internal/form-renderer-core test |
Run the engine test suite |
v1 implements the full happy path across all three modules. v2 (in progress) adds the foundation: a migrated SQLite datastore replacing the JSON file, session-based authentication, and enforced per-team permissions (edit/publish gated to owning-team members; cross-team read-only). Remaining known simplifications: per-row validation-state (used inside repeatable groups) is evaluated at global scope, file uploads store metadata rather than binary content, and dev login authenticates by email + shared password rather than a real identity provider.