OpenForm
Concepts

Anatomy of a Form

Last updated on

Fields, parties, and annexes

Forms are the central artifact of OpenForm. They can be used to create anything from a simple purchase order to a complex multi-party agreement involving numerous nested fields, annexes, and logic.

In this section, we introduce the fundamental building blocks of a Form.

Fields

Fields define what data a form collects. They are strongly typed, can represent different data types, and can be grouped into fieldsets. All fields have common base properties such as label, description, required, and visible that define their behavior in a form.

const form = open.form()
  .name("application")
  .fields({
    fullName: { type: "text", label: "Full Name", required: true },
    age: { type: "number", label: "Age" },
    startDate: { type: "date", label: "Start Date" },
  })
  .build()

Primitives

Beyond basic types, OpenForm includes primitives for common real-world data—address, money, phone, person, organization, and others. Primitives carry semantic meaning: a money field includes currency and can be serialized appropriately for different locales.

fields: {
  propertyAddress: { type: "address", label: "Property Address" },
  monthlyRent: { type: "money", label: "Monthly Rent" },
  tenantPhone: { type: "phone", label: "Phone Number" },
}

See Primitives for the complete list of field types.


Parties

Parties are the roles that interact with a form. A lease might have landlord and tenant parties. An employment agreement might have employer and employee.

Parties define roles, not identities. At runtime, actual people or organizations are assigned to these roles.

const form = open.form()
  .name("lease")
  .parties({
    landlord: open.party().label("Landlord"),
    tenant: open.party().label("Tenant").multiple(true).max(4),
  })
  .build()

Signatures

Signature requirements are defined per party. You can specify whether signatures are required, must be witnessed, or need notarization.

parties: {
  buyer: open.party().label("Buyer").signature({ required: true, witnesses: 1 }),
  seller: open.party().label("Seller").signature({ required: true }),
}

Signature requirements are part of the artifact definition. How signatures are captured and rendered depends on the runtime and layer.


Annexes

Annexes are file attachments that accompany the form—things like photo IDs, proof of income, or supporting documents.

const form = open.form()
  .name("lease-application")
  .annexes({
    photoId: open.annex().title("Photo ID").required(true),
    proofOfIncome: open.annex().title("Proof of Income").required(true),
  })
  .build()

Annexes can have conditional visibility and requirements using Logic.

On this page