Skip to main content
Menu
On this page

Form.io alternative for forms inside a modern app

Compare Form.io with Fillo when the form lives in a component app: a typed schema in your repo, no database to operate, and fields your own code renders.

The schema moves into your repo

Form.io turns forms into resources on a platform you run. Fillo is for when the form should be a typed schema in your codebase, rendered by your components, with nothing to operate behind it.

Typed in your repo, checked on the server.

defineForm() or JSX defines the fields once; the same rules run in the rendered form and on submit.

Rendered by your components.

Real DOM in your tree, under your app's own Content Security Policy, styled by your stylesheet.

app.acme.co/requests/new

Access request

Powered by Fillo

A workspace instead of a submission server.

Grid, versions, exports, API reads, and signed webhooks — with nothing to size or fail over.

Files go to storage you already own.

Browser-direct uploads to your connected Drive, Box, or S3-compatible bucket, verified by Fillo.

Form.io is a form and API platform. You author forms as JSON, render them with formio.js or its React, Angular, and Vue wrappers, and its server turns each form into a REST resource with its own submissions and permissions. Run it on their cloud, or entirely inside your own network.

Fillo is narrower and hosted: one typed schema, fields rendered by your own components, responses in a workspace, nothing for you to operate.

Which should you choose?

When Fillo fits

  • There is nothing you want to run — no database to size, no load balancer, no failover plan.
  • The schema should be typed and live in the repo beside the feature that uses it.
  • The app ships a strict Content Security Policy you would rather not carve an exception into.
  • The fields should be your components, in your DOM, styled by your stylesheet.

When to stay on Form.io

  • Regulated or on-premise requirements. Fillo has no self-hosted edition. If the platform has to run inside your own network with no third party in the request path, Form.io is the honest answer. The cost of staying is the operating model below: a MongoDB-compatible database and the availability stack around it, run by you.
  • You ship a form builder to your own users. Form.io's embeddable builder lets your customers author forms inside your product, each becoming an API resource with its own roles and submission rules. Fillo's editor is for your team only. The cost is that you take the renderer with it, constraints included.
  • Offline capture and generated PDFs, neither of which Fillo has. The cost is that the rest of the form stack then moves at Form.io's cadence.

What changes in a React app

With @formio/react, the form is a JSON definition your app points at, and the library renders it from formio.js templates:

tsx
import { Form } from "@formio/react";

export function ContactForm() {
  return <Form src="https://example.form.io/contact" onSubmit={console.log} />;
}

With @usefillo/react, the fields are components in your tree and the schema is typed:

tsx
import { Fillo, when, createClient } from "@usefillo/react";

const client = createClient({ key: process.env.NEXT_PUBLIC_FILLO_KEY });

export function ContactForm() {
  return (
    <Fillo.Form id="contact" title="Contact us" client={client}>
      <Fillo.Email id="email" label="Work email" required />
      <Fillo.LongText
        id="details"
        label="What do you need?"
        visibleIf={when("email").answered()}
      />
    </Fillo.Form>
  );
}

A Fillo condition is a record — field ID, operator, value — not an expression. The same rule decides what renders and what Fillo's server accepts on submit, and there is no expression string for the renderer to evaluate.

Key differences

DecisionFilloForm.io
What you runNothingTheir cloud, or self-hosted: a MongoDB-compatible database, container, load balancer, availability design
SchemaTyped defineForm() or JSX in your repo; conditions are dataJSON definition stored as a server resource; logic can include JavaScript
RenderingYour React components, a DOM renderer, or a fillo-form custom elementformio.js renderer with React, Angular, and Vue wrappers
BuilderHosted editor for your teamEmbeddable builder you can ship to your own users
File uploadsBrowser-direct to Google Drive, Box, or S3-compatible storage you connectStorage providers configured per project
Working with responsesGrid, versions, CSV, Management API, signed webhooksSubmission resources with role-based access

Form.io's enterprise self-hosting page is the source for the database requirement, and lists Atlas, DocumentDB, Cosmos DB, and Mongo Enterprise Advanced as the options. Three long-running formio.js issues are worth reading before committing the renderer to a component app: shadow DOM support has been open since 2019, and in April 2026 a maintainer noted there is still no explicit support; JavaScript conditionals need unsafe-eval in the page's CSP, with disabling evaluations or the protected evaluator as the documented alternatives; and a typing gap on the base component class, open since January 2024, has as any or @ts-ignore as its workaround. All four checked on August 6, 2026.

Before you switch

Fillo does not replace what Form.io is best at: no embeddable builder for your end users, no offline capture, no PDF generation, no per-form REST resource with its own permission rules. If one of those is why Form.io is in the stack, moving removes capability rather than plumbing.

Fillo also starts a new response history. Submissions in your database stay yours, but cannot be imported as Fillo responses with schema versions and delivery state.

What you would need to change

Existing Form.io setupExpected work
A JSON form rendered by @formio/reactExpress the fields as a Fillo schema and render with @usefillo/react or the DOM renderer
JavaScript conditionals and custom validatorsMap them to declarative conditions and field rules; dynamic behavior moves into your own code
An embedded builder your users author inNo equivalent — decide whether those users still need to author forms
Submission resources with role-based accessResponses live in the Fillo workspace; reads go through the Management API and webhooks

Next step

Open the editor, or define one form in code with defineForm() and sync it from the repo. Render it on a real route before moving the rest.

Updated

Was this page helpful?