---
title: "Form.io alternative for forms inside a modern app"
description: "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."
group: "Compare & migrate"
order: 11
type: "comparison"
keywords:
  - "Fillo vs Form.io"
  - "Form.io alternative"
  - "embedded form builder"
  - "JSON form renderer"
updated: "2026-08-06"
---

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

| Decision | Fillo | Form.io |
| --- | --- | --- |
| What you run | Nothing | Their cloud, or self-hosted: a MongoDB-compatible database, container, load balancer, availability design |
| Schema | Typed `defineForm()` or JSX in your repo; conditions are data | JSON definition stored as a server resource; logic can include JavaScript |
| Rendering | Your React components, a DOM renderer, or a `fillo-form` custom element | formio.js renderer with React, Angular, and Vue wrappers |
| Builder | Hosted editor for your team | Embeddable builder you can ship to your own users |
| File uploads | Browser-direct to Google Drive, Box, or S3-compatible storage you connect | Storage providers configured per project |
| Working with responses | Grid, versions, CSV, Management API, signed webhooks | Submission resources with role-based access |

Form.io's [enterprise self-hosting page](https://form.io/enterprise-self-hosting/) 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](https://github.com/formio/formio.js/issues/1448) has been open since 2019, and in April 2026 a maintainer noted there is still no explicit support; [JavaScript conditionals need `unsafe-eval`](https://github.com/formio/formio.js/issues/6078) 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](https://github.com/formio/formio.js/issues/5481), 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 setup | Expected work |
| --- | --- |
| A JSON form rendered by `@formio/react` | Express the fields as a Fillo schema and render with `@usefillo/react` or the DOM renderer |
| JavaScript conditionals and custom validators | Map them to declarative conditions and field rules; dynamic behavior moves into your own code |
| An embedded builder your users author in | No equivalent — decide whether those users still need to author forms |
| Submission resources with role-based access | Responses live in the Fillo workspace; reads go through the Management API and webhooks |

## Next step

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

## Related

- [Author forms in code](/docs/authoring): Keep a typed Fillo schema in your repo.
- [Embed a Fillo form](/docs/embed): Render native fields in React, the DOM, or a hosted page.
- [Custom field UI](/docs/custom-ui): Replace any field with your own component.
- [Compare form tools](/compare): Find the right starting point for the form you need.
- [Fillo plans and limits](/docs/limits): Check response, branding, and upload limits.
