Open source · for public-sector and regulated forms

Official forms, owned by the people who write them.

Write a form in a visual designer, in Excel or in YAML. quillflow turns it into an accessible web form with live lookups in your registers, and checks every submission on your server with exactly the same rules.

Open the designer Read the documentation

  • 1 form definition
  • 2 runtimes, TypeScript and .NET, held to one conformance suite
  • 0 lines of front-end code per form
A live form: try typing vesterg odense in the address field

Runs in your browser with a pretend address register. See its source.

Why quillflow

Forms are where people meet public services. They change often, and they must be right, accessible and secure. quillflow puts the people who own them in charge and takes care of the rest.

  • Written by the people who own the form

    Caseworkers use the designer or Excel, developers use YAML. All three open and save the same files. Problems are reported in the author's words: row 14, column relevant: Unknown field "incme". Did you mean "income"?

  • The same rules in the browser and on the server

    Every submission is checked again by the same engine. Hidden answers are dropped and calculations recomputed. The TypeScript and .NET engines pass one shared conformance suite, so they cannot drift apart.

  • Live lookups, no secrets in the browser

    A company from its CVR number, properties at a postcode, an address as you type. The form names the lookup, and your server calls the register with its own credentials and the signed-in user.

  • Accessible by default

    Real labels and fieldsets, an error summary that links to each field, focus management, a WAI-ARIA combobox for search, and numbers typed the local way. Patterns from GOV.UK and Det Fælles Designsystem.

  • Embed it anywhere

    One web component for plain HTML, Blazor, React, Angular or Vue. No shadow DOM: your design system styles it. Server SDKs for ASP.NET Core and Node.

  • Rules anyone can read

    Rules are Excel formulas: AND(AGE(birthdate) >= 18, amount <= @valuation.value * 0.8). Text can include answers, with numbers written the local way: {{ amount | number }} kr.

One form, written the way you work

The same question in each format. Whichever you write, the compiler produces the same definition.

Sheet “survey”: one row per question
typenamelabel::darequiredrelevantconstraint
select_one employmentemploymentBeskæftigelseyes
textcvrCVR-nummeryesemployment = "self"MATCHES(., "^[0-9]{8}$")
decimalincomeÅrlig indkomst (kr.)yesemployment <> "unemployed". > 0

How it fits together

From author to register Authors write a form in the designer, Excel or YAML. The compiler produces one definition. The qf-form web component shows it in your portal and talks to your server, which runs lookups against your registers and checks every submission again with the same engine. Authors DesignerExcelYAML Compilerone definition (JSON) Your portal <qf-form>HTML · Blazor · React … engine in the browser Your server quillflow SDK (.NET or Node) the same engine checks every submission connectors → your registers

A few lines in the stack you already have

<script type="module" src="quillflow.bundle.js"></script>

<qf-form form="change-of-address" api="/api"></qf-form>

Something for everyone around a form

Form owners

Change a question, a rule or a message yourself, see it live, and hand over a file that passes review. The designer · Authoring

Developers

Embed one element, register a connector per lookup, handle a clean submission. No per-form code. Embedding · Servers

Architects and security

Server-side validation by the same engine, allow-listed lookups, no secrets in the browser, strict CSP. Security · Accessibility

See for yourself

Build a form in the designer, or write one in the playground. Everything runs in your browser.

Open the designer Try the playground