Skip to main content

Command Palette

Search for a command to run...

Why I built Vant Flow: An Angular schema-driven form platform for fast-changing business workflow

Updated
7 min read
Why I built Vant Flow: An Angular schema-driven form platform for fast-changing business workflow

I did not build Vant Flow because I wanted to build another form builder. I built it because I kept running into a delivery wall.

Github Repo: https://github.com/DonnC/vant-flow

https://github.com/DonnC/vant-flow

I work in a banking environment in Zimbabwe, inside a digital team where workflows do not stay still for long. A compliance rule changes, a department wants a new approval step, or a team needs to turn a simple process into a multi-step stepper flow. My internal clients do not care if I build from scratch or use a template—they just need the solution to work.

This is the practical story of the problem I was solving, the approach I chose, and why this model has worked for me.

The problem was never just collecting data

The hard part was dealing with business documents that behave like mini applications.

In my context, that usually means:

  • fields that become required only in certain cases

  • sections that appear or disappear based on values, roles, or status

  • approvals, review notes, and follow-up actions

  • tables, signatures, and attachments

  • workflows that begin as a simple form and later become multi-step

  • the same document needing to support authoring, runtime, and readonly replay

There are good products in this space already. This is not a claim that everything else is bad.

But in my environment, a few constraints kept coming up:

  • paid platforms are not always an option

  • procurement and security reviews take time

  • some tools work well for basic form capture but become awkward when the workflow behaves more like part of the application itself

  • some platforms want to own too much of the stack when I need the host app to stay in control

So I wanted something more specific: a schema-driven way to build forms that change often, carry real business logic, and still fit inside an existing application architecture.

The Approach: Schema Once, Render Everywhere

design the form once, store it as schema, and let the renderer execute it at runtime instead of rebuilding Angular screens every time a workflow changes.

At the center of that is a shared schema contract called DocumentDefinition.

That schema can then power:

  • form builder and rendering

  • preview mode for testing

  • readonly replay for support, review, or audit

The platform is heavily inspired by the ideas and ergonomics of the Frappe ecosystem , but implemented as a focused Angular-first tool. It is split into three main layers:

  • VfBuilder: A visual editor for authoring schemas.

  • VfRenderer: A runtime engine that turns those schemas into live forms.

  • Host Control: The host application (your app) still owns the heavy lifting: authentication, storage, and APIs.

This separation is vital. I did not want a platform that tries to swallow the whole app; I wanted a tool that fits into my existing architecture.

visual side-by-side of vant builder and renderer

What the developer experience looks like

The core setup is intentionally simple.

Register the provider:

import { ApplicationConfig } from '@angular/core';
import { provideVfFlow } from 'vant-flow';

export const appConfig: ApplicationConfig = {
  providers: [provideVfFlow()]
};

Render a schema:

<vf-renderer
  [document]="document"
  [initialData]="initialData"
  [metadata]="metadata"
  (formAction)="handleAction($event)"
></vf-renderer>

Open the builder:

<vf-builder
  [initialSchema]="document"
  [previewMetadata]="previewMetadata"
  (schemaChange)="onSchemaChange($event)"
></vf-builder>

That is the main loop:

  1. author schema

  2. store schema

  3. render schema

  4. respond to runtime events in host code

What I like about this model is that the frontend stops treating every workflow as a brand-new page.

Why it felt useful in real work

The strength of the approach is not just "forms from JSON". Plenty of projects can do that.

What made it useful for me is that the same document can support:

  • builder authoring

  • live runtime execution

  • dynamic conditions

  • stepper flows

  • richer workflow actions

  • readonly replay later

That changes the economics of delivery.

Instead of rebuilding screens every time a department changes a process, a lot of that change can move into schema, runtime rules, and host metadata.

Making it Dynamic with Scripting

Static schema alone is not enough for operational workflows. You also need runtime behavior. For example: You need to calculate totals from tables, update filters on the fly, or block actions until validation passes.

Vant Flow supports two layers:

  • declarative rules like depends_on and mandatory_depends_on

  • scripted behavior through a constrained frm API

This means the business behavior travels with the document definition allowing you to handle things like:

  • make a field required only after a certain value is selected

  • set fields to readonly after approval

  • show or hide sections at runtime

  • update remote lookup filters dynamically

  • calculate totals from table rows

  • block actions until validation passes

For example:

frm.on('status', (value, frm) => {
  if (value === 'Approved') {
    frm.set_df_property('batch_id', 'read_only', true);
  }
});

And for a table total:

// whenever parts table is updated, recompute the total cost of parts
frm.on('parts_used', (rows, frm) => {
  const total = (rows || []).reduce((sum, row) => {
    return sum + ((Number(row.qty) || 0) * (Number(row.rate) || 0));
  }, 0);

  frm.set_value('parts_total', total);
});

This is the kind of logic I used to see hardcoded inside custom page components. I wanted the behavior to travel with the document definition instead

Real-World Use Cases

This approach has been practical for several scenarios we deal with daily:

  • KYC and Onboarding: Handling complex document uploads and signatures.

  • Internal Approvals: Multi-step flows for procurement or leave requests.

  • Audit and Inspection: Capturing data in the field using features like camera capture and replaying it later in a readonly mode for auditors.

The renderer stays host-agnostic, meaning your app controls how uploads are handled through a mediaHandler. This is vital for us because we need to point attachments to our own secure object storage or CDN-backed services.

The "Extra" Goodies

There are a few parts of the approach that I think make it much more useful in real projects.

Link fields

These are remote autocomplete fields, not just static selects. They can point to backend search endpoints, map returned data, and change filters at runtime.

Attachments and signatures

The renderer supports a mediaHandler, so the host application can control uploads and store compact file references instead of raw payloads in form state.

Host-controlled runtime state

The host can still control runtime behavior directly through inputs like:

  • runFormScripts

  • readonlyFields

  • hiddenFields

  • disabledActionButtons

  • hiddenActionButtons

Readonly replay

This is one of the features that matters a lot in enterprise work. The same schema can be reused later against saved data for support, audit, or compliance review.

AI and MCP

As an AI enthusiast, I wanted to see how we could make the authoring process faster. I included support for MCP (Model Context Protocol) so AI agents can scaffold forms directly from a prompt or even an uploaded image of a paper form or assist a user to fill out a form.

A Realistic Perspective

I will not act like this is a perfect solution for every team. Building and owning your own platform comes with trade-offs.

  • a flexible schema model needs discipline

  • scripting needs guardrails

  • the host app still owns workflow orchestration and permissions

  • building your own platform means owning maintenance and documentation

So no, I would not present this as a miracle solution.

But if you keep building workflow-heavy apps and you are tired of turning every process change into another custom frontend rebuild, this pattern is worth serious consideration.

Final Thought

Vant Flow came from a practical need: making workflow changes cheaper without giving up control.

I like solutions that are reusable, grounded, and close to how the business actually works. Vant Flow is one example of that approach, and if you work on internal tools, regulated systems, or operational workflows, you may find the pattern useful for your next project.