Library / SDK
TanStack/form avatar
TanStack/form

TanStack Form: 6,697 stars for the decision to render nothing

🤖 Headless, performant, and type-safe form state management for TS/JS, React, Vue, Angular, Solid, and Lit.

6,716 stars693 forksTypeScriptMIT

At a glance

What is it?
Most form libraries ship a set of input elements along with their state logic. TanStack Form ships the state logic and leaves every pixel to you, then ports that logic to seven frameworks from a single core package.
Who is it for?
TanStack Form makes a bet that most of a form library's weight is not the state logic at all, it is the markup, the styling and the twenty small decisions about how an error should look next to a label. Strip those out and what is left is a typed state machine that one team can write and seven adapters can expose.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The core package holds the logic and renders nothing

The README calls the project a headless form library for managing complex form state with full control over fields, validation, and workflows across any framework. The word doing the work there is headless. There is no input component in this repository, no label, no error container, no theme. You get a typed object graph representing your form and a set of hooks or reactive primitives that let you read from it.

That decision has consequences in both directions. You lose the convenience of dropping in a ready-made fieldset, and in exchange you are not locked into somebody else's markup, your CSS framework, or a component library's error styling. For a design system, that trade is usually worth taking. For a weekend prototype, it probably is not.

The four bullets under the title are the entire feature pitch: framework-agnostic and headless with bring your own UI, fully typed with TypeScript, reactive hooks with an extensible modular architecture, and sync plus async validation with debouncing and nested fields. Four claims, all of them falsifiable, and none of them about templates.

The GitHub description adds one detail the README body does not repeat in the same form: it says TS/JS. So JavaScript users are nominally supported even though TypeScript is the repository's language and the type story is the headline feature. Topics on the repository include zod and yup, which tells you the validation adapters have third-party schema libraries wired in rather than being invented in-house.

Seven example apps, five framework names, one missing from both lists

The tree carries an examples directory with seven separate applications, and the directory listing is the most precise statement of framework support anywhere in the repository:

`examples/angular/`, `examples/lit/`, `examples/preact/`, `examples/react/`, `examples/solid/`, `examples/svelte/`, `examples/vue/`.

Now compare that with what the README says. The GitHub description names React, Vue, Angular, Solid, and Lit. The README body does not enumerate frameworks at all. The repository topics add svelte. Preact appears in neither prose list, yet it has a full example application sitting in the tree.

So there are three different statements of scope and none of them agree completely. The examples directory is the one to trust, because a Preact example either works or it does not, and it is committed to the repository. The prose lists look maintained on a slower cadence than the directory.

The three most recent releases reinforce the same reading. `@tanstack/vue-form`, `@tanstack/svelte-form`, and `@tanstack/solid-form` all published 2.0.0-alpha.2 on 2026-08-21 within about twenty seconds of each other, all carrying an identical set of changeset entries. That is what a coordinated monorepo release looks like: one changeset operation, several packages stamped in sequence. Vue, Svelte, and Solid are the three adapters being pushed toward 2.0 right now.

Eight test targets, and what each one actually checks

The root package.json is where this project stops looking like a typical library repository. It is marked private, declares pnpm as its package manager pinned to an exact version and hash, sets an engines floor of pnpm 11, and turns every check into an Nx target.

json
  "type": "module",
  "scripts": {
    "test:pr": "nx affected --targets=test:sherif,test:knip,test:docs,test:eslint,test:lib,test:types,test:build,build",
    "test:ci": "nx run-many --targets=test:sherif,test:knip,test:docs,test:eslint,test:lib,test:types,test:build,build",
    "test:sherif": "sherif",
    "test:knip": "knip",
    "test:docs": "node scripts/verify-links.ts",
    "format": "prettier --experimental-cli --ignore-unknown '**/*' --write",

The eight targets are worth reading one by one, because a repository that runs all eight on every change is doing considerably more than running unit tests.

`test:lib` is the actual test suite, and it excludes the examples directory. `test:types` runs TypeScript checks, also excluding examples. `test:build` confirms every package still builds, excluded examples again. `test:eslint` is the lint pass. `build` compiles with Nx affected.

The three interesting ones are the first three. `test:sherif` runs Sherif, a linter whose entire job is monorepo dependency hygiene: catching packages that depend on the wrong version range, duplicated dependencies that should be hoisted, and internal packages referenced in ways that defeat the workspace. `test:knip` runs Knip, which finds exports, files, and dependencies that nothing imports. In a library with as many adapter packages as this, Knip is how dead code actually gets removed instead of accumulating. `test:docs` calls `scripts/verify-links.ts`, a custom script that checks the documentation links resolve, which is more than most library repositories bother with.

`test:ci` runs all eight across the workspace with `nx run-many`. `test:pr` is the same list through `nx affected`, so a pull request only pays for the packages it touched. Note that `test` is aliased straight to `test:ci`, so a bare `pnpm test` is the full sweep rather than a quick loop.

The badge says Semantic Release, the tooling says Changesets

This is a contradiction worth naming rather than smoothing over, because it tells you something real about the repository's history.

The README carries a badge reading Semantic Release Enabled. The repository contradicts it in three separate ways. There is a `.changeset/` directory at the root of the tree. The package.json scripts include `changeset`, `changeset:publish`, and `changeset:version`. And the release notes for 2.0.0-alpha.2 are formatted exactly the way Changesets formats them, with the Minor Changes and Patch Changes headings and the linked pull request numbers in square brackets.

So the badge is stale. The project moved from Semantic Release to Changesets at some point and the README image was never updated. The direction of the move also makes sense in hindsight: Semantic Release derives versions from commit messages, while Changesets derives them from a markdown file a developer writes before merging. For a monorepo shipping eight or more packages with a coordinated release order, per-change versioning control is the more workable model.

The `changeset:version` script shows how carefully the flow is maintained. It runs `changeset version`, then `pnpm install --no-frozen-lockfile`, then `pnpm format`. So after versions are bumped, the lockfile is regenerated and Prettier runs across the repository before anything is published. That extra formatting step matters more than it sounds: it keeps version bumps from landing as unformatted diffs.

There is also `generate-docs`, which calls `scripts/generate-docs.ts`. With docs, examples, scripts, nx.json, knip.json, pnpm-workspace.yaml, and eslint.config.js all at the root, this is a repository where documentation is generated from the code rather than maintained by hand alongside it.

The breaking change in 2.0 is a signature, not a behaviour

All three of the 2.0.0-alpha.2 releases carry the same three entries, and the first one is marked BREAKING, which makes it worth reading closely.

The refactor is described as adapters no longer shimming the core types and runtime. The consequence is that `formOptions.looseSchema` and `formOptions.strictSchema` now require a schema as the first parameter, rather than taking the options object alone. The stated reason is inference: passing the schema first locks down the type inference instead of letting it widen from an untyped options bag. A fix ships in the same entry, allowing `defaultValues` under `looseSchema` to omit properties instead of requiring each one to be explicitly undefined.

So the breaking change is entirely about how you call the schema helpers, not about what validation does. For most codebases this is a find-and-replace on the call sites. For anyone who relied on the old looser inference, it is a real migration, and the fact that it landed under a patch-style description inside an alpha release is a reminder that alpha tags are where breaking changes are allowed to be quiet.

The second entry is friendlier. Subscription selectors now infer tuple return values without requiring an `as const` annotation, which removes a class of type error that subscribers were previously expected to paper over. The third is a minor feature: default options can now be specified for `createFormHook`, which is how a project supplies shared configuration once instead of at every hook call site.

Pull request numbers for these three entries are 2348, 2339, and 2343. The numbering puts this in a project with well past two thousand pull requests, which is a better signal of activity than star count alone.

206 open issues against a 6,697-star count

The repository has 6,697 stars, 685 forks, 206 open issues, an MIT license, TypeScript as its language, and a homepage at tanstack.com/form. The last push was 2026-09-21, well within the current development window, so this is an actively maintained project and the open issue count reflects triage volume rather than abandonment.

The issue count is still worth putting in proportion. Two hundred and six open issues on a project this size is a healthy backlog rather than a distress signal, and it is the ordinary consequence of running a public issue tracker on something this popular with seven framework adapters and a 2.0 transition in progress.

The README's business side is straightforward. CodeRabbit and Cloudflare are listed as partners, there is a sponsor link aimed at the maintainer, and the project openly solicits additional partners. The Solidity-looking HTML and image wrappers in the README are theme-switching markup for light and dark mode logos, not a signal about the language.

The ecosystem list at the bottom of the README is the best argument for the headless design. TanStack Config, DB, DevTools, Pacer, Query, Ranger, Router, Start, Store, Table, and Virtual all sit alongside Form as separate packages with separate repositories. A headless form library composes cleanly with that set because it renders no DOM of its own. A form library that shipped its own input elements would be fighting for the same pixels as the rest of the family.

Editorial conclusion

TanStack Form makes a bet that most of a form library's weight is not the state logic at all, it is the markup, the styling and the twenty small decisions about how an error should look next to a label. Strip those out and what is left is a typed state machine that one team can write and seven adapters can expose. The repository backs that bet up with a real engineering setup: pnpm 11 pinned by hash, Nx running eight distinct test targets, Sherif checking monorepo dependency policy, Knip hunting unused exports, and a link checker for the documentation. The release story is the part to watch. The badges still advertise Semantic Release, but the tooling has moved to Changesets, and the packages that shipped most recently are 2.0.0-alpha builds for Vue, Svelte and Solid with a breaking change to the schema helper signatures. Alpha tags on three adapters while React and the core sit elsewhere is the sort of thing that matters a great deal if you are about to bet a signup flow on it, and very little if you are just evaluating. The honest summary is that this is an ambitious, well-tooled project in the middle of a version transition, with 206 open issues sitting underneath a 6,697-star count. Read the release notes for the adapter you actually intend to install, and check whether the framework you use is on a stable line or an alpha one.

Frequently asked questions

What does TanStack form do?

It manages form state: field values, nested fields, validation, and submission. It is headless, meaning it ships no input elements, labels, or styling of its own, so you render the markup yourself. The repository describes it as a headless form library for managing complex form state with full control over fields, validation, and workflows across any framework, written in TypeScript and published under the MIT license.

How does TanStack form use Zod for form validation?

Zod is not bundled as the validation engine; it is one of the schema libraries you can plug in, and yup is the other. Both appear as repository topics, which is a signal that official adapters exist for them. Zod schemas are attached through the formOptions helpers looseSchema and strictSchema, whose loose variant validates on every change while the strict variant waits for submit. In the 2.0.0-alpha releases those two helpers began requiring the schema as their first parameter, a breaking change made to improve type inference.

How does TanStack form simplify form handling?

It moves to a single typed object rather than per-field hooks, so nested field paths are addressed as paths and the validation rules live in one schema instead of being scattered across components. The repository's feature list pairs reactive hooks and an extensible modular architecture with sync and async validation, debouncing, and nested fields. Since nothing is rendered for you, the simplification is in state management rather than in markup.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. TanStack/form on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/tanstack-form.svg)](https://hysenlabs.com/projects/tanstack-form)