Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
name: form-schema
name: formhaus-create-form
description: |
Generate @formhaus/core JSON schemas from any input: text description,
Generate @formhaus/core form definitions from any input: text description,
CSV/table, or screenshot of a form. Interactive step/condition builder.
Output pastes directly into the Formhaus Figma plugin or FormRenderer.
Use when: "generate form", "form schema", "form JSON", "create a form",
or when user describes form fields in any format.
Use when: "generate form", "form definition", "form JSON", "create a form",
"formhaus", or when user describes form fields in any format.
allowed-tools:
- Read
- Write
Expand All @@ -15,9 +15,9 @@ allowed-tools:
- Agent
---

# Form Schema Generator
# Form Definition Generator

You generate valid `@formhaus/core` JSON schemas from any input.
You generate valid `@formhaus/core` form definitions from any input.
The output is ready to paste into the Formhaus Figma plugin or use with FormRenderer.

## Types Reference
Expand Down Expand Up @@ -179,7 +179,7 @@ Ask only if there's ambiguity: "Should [field] be required?"

### Step 4: Generate JSON

Output the complete FormSchema JSON. Follow these rules:
Output the complete form definition JSON. Follow these rules:

1. `id` is kebab-case derived from the title
2. `key` for each field is camelCase
Expand All @@ -192,7 +192,7 @@ Output the complete FormSchema JSON. Follow these rules:

Show the generated JSON in a code block. Ask:

> "Here's your form schema. You can paste this directly into the
> "Here's your form definition. You can paste this directly into the
> Formhaus Figma plugin or use with FormRenderer."

Options:
Expand All @@ -219,8 +219,8 @@ a pattern or show the user an example.

- NEVER output invalid JSON. Validate before presenting.
- NEVER invent field types not in the FieldType union.
- NEVER use `fields` AND `steps` in the same schema. Pick one.
- Keys must be unique within a schema (across all steps).
- NEVER use `fields` AND `steps` in the same definition. Pick one.
- Keys must be unique within a definition (across all steps).
- ShowCondition.field must reference an existing field key.
- For multi-step: each step needs `id`, `title`, and `fields`.
- Submit label should match the form's purpose ("Submit", "Create transfer", "Register", etc.).
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
name: figma-connect
name: formhaus-figma-connect
description: |
Generate a @formhaus/figma componentMap JSON by scanning a Figma design system
via MCP. Auto-detects form components (inputs, checkboxes, buttons, etc.),
shows screenshots for confirmation, fills gaps interactively.
Output pastes directly into the Formhaus Figma plugin's Component Map tab.
Use when: "connect figma", "figma components", "component map",
"setup plugin", "map design system", or when user wants to configure
the Figma plugin for their design system.
"formhaus figma", "setup plugin", "map design system", or when user wants
to configure the Figma plugin for their design system.
allowed-tools:
- Read
- Glob
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

## 0.3.0 - 2026-04-07

### Docs

- Replaced "JSON schema" terminology with "form definition" across all docs, README, and CONTRIBUTING to avoid confusion with the JSON Schema spec.
- Renamed `/form-schema` skill to `/formhaus-create-form`.
- Renamed `/figma-connect` skill to `/formhaus-figma-connect`.
- Renamed `docs/api/schema.md` to `docs/api/definition.md`.
- Added "Nested keys" section to field types guide.
- Added "Schema improvements (non-urgent)" section to CONTRIBUTING.

### `@formhaus/core`

- `FieldType` now accepts any string. Built-in types get autocomplete via `DefaultFieldType`.
Expand Down
14 changes: 11 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,25 @@ Opens at http://localhost:5173.
## What could use help

- Svelte adapter (`@formhaus/svelte`)
- More fixture schemas in `packages/core/fixtures/`
- More fixture definitions in `packages/core/fixtures/`
- Bug reports

### Docs wanted

- **Why Formhaus** — comparison page vs react-hook-form, Formik, VeeValidate. One JSON schema renders to React, Vue, Svelte, and Figma. Nobody else does that.
- **Why Formhaus** — comparison page vs react-hook-form, Formik, VeeValidate. One form definition renders to React, Vue, Svelte, and Figma. Nobody else does that.
- **Migration guides** — "Coming from react-hook-form" / "Coming from Formik". Map their concepts to ours.
- **TypeScript** — how to type schemas, infer value types, generics in custom components.
- **TypeScript** — how to type definitions, infer value types, generics in custom components.
- **Recipes** — dependent dropdowns, address autocomplete, file upload, dynamic field arrays. Concrete solutions, not abstract docs.
- **Design system integration** — examples with shadcn/ui, Vuetify, Ant Design. One real UI kit example beats ten abstract ones.

### Schema improvements (non-urgent)

- **`disabled` on fields** — currently only action buttons support `disabled`. Sometimes you need to show a field but block input.
- **`readonly`** — useful for review/preview mode where the form is visible but not editable.
- **Multiple validators per field** — right now it's `"validator": "checkFormat"`. An array like `["checkFormat", "checkUnique"]` would be more flexible.
- **`optionsFrom` / `optionsDependsOn` docs** — the feature works but there's no usage example in the docs. This is the most "magical" part of the definition format.
- **Field groups / sections** — if a single step has 15 fields, you want to visually break them into blocks without going multi-step.

## Code style

- TypeScript everywhere
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
[![bundlephobia](https://img.shields.io/bundlephobia/minzip/@formhaus/core?label=core%20size)](https://bundlephobia.com/package/@formhaus/core)
[![license](https://img.shields.io/github/license/ignsm/formhaus)](LICENSE)

Framework-agnostic JSON-schema-driven form ecosystem.
Define a form once as a JSON schema, render it anywhere in code or Figma.
Framework-agnostic form engine with its own compact JSON-based definition format.
Define a form once — fields, validation, conditions, steps — in a single file. Render it in React, Vue, Figma, or any framework via the core engine. No JSON Schema spec, no separate UI schema, no boilerplate.

## Packages

Expand All @@ -17,7 +17,7 @@ Define a form once as a JSON schema, render it anywhere in code or Figma.
| `@formhaus/react` | React adapter with native HTML defaults and custom component support | `npm i @formhaus/react` |
| `@formhaus/vue` | Vue 3 adapter with native HTML defaults and custom component support | `npm i @formhaus/vue` |

There is also a Figma plugin (`@formhaus/figma`) that generates form mockups from JSON schemas. Available via `manifest.json` for now.
There is also a Figma plugin (`@formhaus/figma`) that generates form mockups from form definitions. Available via `manifest.json` for now.

Svelte, Solid, or anything else: use `@formhaus/core` directly. See the [playground](https://formhaus.dev/playground) for an example.

Expand All @@ -38,9 +38,9 @@ Or use `@formhaus/core` directly with any framework. See the [Svelte example in

## Quick Start

### Define a schema
### Define a form

You can write the JSON by hand or use the [Claude skill](.claude/skills/form-schema/SKILL.md) to generate it from a text description.
You can write the JSON by hand or use the [Claude skill](.claude/skills/formhaus-create-form/SKILL.md) to generate it from a text description.

```json
{
Expand Down Expand Up @@ -191,7 +191,7 @@ Each field component receives the full `FormField` descriptor, the current value

## Figma Plugin

`@formhaus/figma` is a Figma plugin that takes a formhaus JSON schema and generates a styled form mockup directly on the canvas. Useful for rapid prototyping and design handoff.
`@formhaus/figma` is a Figma plugin that takes a formhaus form definition and generates a styled form mockup directly on the canvas. Useful for rapid prototyping and design handoff.

## Contributing

Expand Down
10 changes: 5 additions & 5 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { defineConfig } from 'vitepress'

export default defineConfig({
title: 'Formhaus',
description: 'Framework-agnostic JSON-schema-driven form ecosystem',
description: 'Framework-agnostic form engine with its own compact definition format',
themeConfig: {
nav: [
{ text: 'Guide', link: '/guide/' },
{ text: 'API', link: '/api/schema' },
{ text: 'API', link: '/api/definition' },
{ text: 'Playground', link: '/playground' },
{ text: 'GitHub', link: 'https://github.com/ignsm/formhaus' }
],
Expand All @@ -27,7 +27,7 @@ export default defineConfig({
{
text: 'API Reference',
items: [
{ text: 'Schema', link: '/api/schema' },
{ text: 'Definition', link: '/api/definition' },
]
},
{
Expand All @@ -39,8 +39,8 @@ export default defineConfig({
{
text: 'Claude Skills',
items: [
{ text: '/figma-connect', link: '/guide/figma-connect-skill' },
{ text: '/form-schema', link: '/guide/form-schema-skill' },
{ text: '/formhaus-figma-connect', link: '/guide/formhaus-figma-connect' },
{ text: '/formhaus-create-form', link: '/guide/formhaus-create-form' },
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion docs/api/schema.md → docs/api/definition.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Schema Reference
# Definition Reference

Every form is a JSON object following the `FormSchema` type.

Expand Down
4 changes: 2 additions & 2 deletions docs/guide/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,5 @@ function onFieldChange(key, value) {
## Next steps

- [Validation](/guide/validation): client-side validation rules
- [Examples](/guide/examples): error handling in real schemas
- [Schema Reference](/api/schema): full TypeScript types
- [Examples](/guide/examples): error handling in real definitions
- [Definition Reference](/api/definition): full TypeScript types
10 changes: 5 additions & 5 deletions docs/guide/examples.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Examples

Example form schemas showing different features. These same JSON files drive both Vue and React stories.
Example form definitions showing different features. These same JSON files drive both Vue and React stories.

## Dispute Form

Expand All @@ -11,7 +11,7 @@ Steps:
2. **Additional details** - description (textarea, min 20 chars), contact preference, phone (conditional)
3. **Review & Submit** - acknowledgement checkbox

Schema: [`fixtures/dispute-form.json`](https://github.com/ignsm/formhaus/blob/main/packages/core/fixtures/dispute-form.json)
Definition: [`fixtures/dispute-form.json`](https://github.com/ignsm/formhaus/blob/main/packages/core/fixtures/dispute-form.json)

## All fixtures

Expand All @@ -26,6 +26,6 @@ Schema: [`fixtures/dispute-form.json`](https://github.com/ignsm/formhaus/blob/ma

## Next steps

- [Figma Plugin](/guide/figma): render these schemas as Figma mockups
- [/form-schema](/guide/form-schema-skill): generate new schemas with Claude
- [Schema Reference](/api/schema): full TypeScript types
- [Figma Plugin](/guide/figma): render these definitions as Figma mockups
- [/formhaus-create-form](/guide/formhaus-create-form): generate new definitions with Claude
- [Definition Reference](/api/definition): full TypeScript types
16 changes: 12 additions & 4 deletions docs/guide/fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ File upload. Uses native file input. Set `accept` to restrict file types.
```
:::

In the schema:
In the definition:

```json
{
Expand Down Expand Up @@ -258,11 +258,11 @@ Override any built-in field type by passing a `components` prop:
```
:::

Each custom component gets the field definition from the schema, the current value, and validation state:
Each custom component gets the field descriptor, the current value, and validation state:

| Prop | Type | Description |
|------|------|-------------|
| `field` | `FormField` | Field object from the schema (`key`, `label`, `options`, etc.) |
| `field` | `FormField` | Field descriptor (`key`, `label`, `options`, etc.) |
| `value` | `unknown` | Current value |
| `error` | `string?` | Validation error, if any |
| `loading` | `boolean?` | Field is loading (async options) |
Expand Down Expand Up @@ -324,7 +324,15 @@ const emit = defineEmits<{
</template>
```

`field` has everything from the schema: `key`, `type`, `label`, `placeholder`, `helperText`, `options`, `validation`. Full type in the [Schema Reference](/api/schema).
`field` has everything from the definition: `key`, `type`, `label`, `placeholder`, `helperText`, `options`, `validation`. Full type in the [Definition Reference](/api/definition).

## Nested keys

Field keys are flat strings. `key: "name"` maps to `values.name` in the submit output. If you use a dot in the key (`key: "address.city"`), it stays flat — the submitted value is `{ "address.city": "Berlin" }`, not `{ address: { city: "Berlin" } }`.

This is intentional. Most forms don't need nested data, and flat keys keep the engine simple. If your backend expects nested objects, reshape the values in your `onSubmit` handler.

Repeatable field groups (arrays of items) are not supported yet.

## Next steps

Expand Down
14 changes: 7 additions & 7 deletions docs/guide/figma.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Figma Plugin

The Formhaus Figma plugin renders form mockups from JSON schemas using your design system components.
The Formhaus Figma plugin renders form mockups from form definitions using your design system components.

## Install

Expand All @@ -21,21 +21,21 @@ This compiles `code.ts` into the bundled plugin code that Figma runs.

1. Open a Figma file
2. Run the plugin (**Plugins > Formhaus**)
3. Paste a `@formhaus/core` JSON schema into the **Generate** tab
3. Paste a `@formhaus/core` form definition into the **Generate** tab
4. Click **Generate**

The plugin creates a frame for each step (or one frame for single-step forms) with your design system components rendered inside.

### Quick test

Click **Load example** in the plugin to load a basic contact form schema. Hit **Generate** to see it render with the default component map.
Click **Load example** in the plugin to load a basic contact form definition. Hit **Generate** to see it render with the default component map.

## Component Map

The **Component Map** tells the plugin which Figma components to use for each form field type.

::: tip Auto-generate with Claude
Instead of editing this JSON manually, run [`/figma-connect`](/guide/figma-connect-skill) to scan your design system and generate the component map automatically.
Instead of editing this JSON manually, run [`/formhaus-figma-connect`](/guide/formhaus-figma-connect) to scan your design system and generate the component map automatically.
:::

### Structure
Expand Down Expand Up @@ -140,7 +140,7 @@ The card width (400px), padding, and spacing are currently fixed. Future version

## Next steps

- [/form-schema](/guide/form-schema-skill): generate schemas from text descriptions
- [/figma-connect](/guide/figma-connect-skill): auto-detect your design system components
- [/formhaus-create-form](/guide/formhaus-create-form): generate form definitions from text descriptions
- [/formhaus-figma-connect](/guide/formhaus-figma-connect): auto-detect your design system components
- [Field Types](/guide/fields): all supported form field types
- [Examples](/guide/examples): example schemas to try with the plugin
- [Examples](/guide/examples): example definitions to try with the plugin
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# /form-schema
# /formhaus-create-form

Generate valid `@formhaus/core` JSON schemas from natural language, CSV data, or screenshots.
Generate valid `@formhaus/core` form definitions from natural language, CSV data, or screenshots.

## Prerequisites

Expand All @@ -10,7 +10,7 @@ Generate valid `@formhaus/core` JSON schemas from natural language, CSV data, or
## Usage

```
/form-schema
/formhaus-create-form
```

Then describe your form:
Expand All @@ -35,14 +35,14 @@ The skill:

## Output

The generated JSON schema works with:
The generated form definition works with:

- The [Figma plugin](/guide/figma): paste into the Generate tab
- [React adapter](https://github.com/ignsm/formhaus/tree/main/packages/react): pass to `FormRenderer`
- [Vue adapter](https://github.com/ignsm/formhaus/tree/main/packages/vue): pass to `FormRenderer`

## Next steps

- [/figma-connect](/guide/figma-connect-skill): connect your design system to the Figma plugin
- [/formhaus-figma-connect](/guide/formhaus-figma-connect): connect your design system to the Figma plugin
- [Field Types](/guide/fields): all supported form field types
- [Schema Reference](/api/schema): full TypeScript types
- [Definition Reference](/api/definition): full TypeScript types
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# /figma-connect
# /formhaus-figma-connect

Auto-detect your Figma design system components and generate a [component map](/guide/figma#component-map) for the Figma plugin.

Expand Down Expand Up @@ -36,7 +36,7 @@ Once connected, Claude can:
## Usage

```
/figma-connect
/formhaus-figma-connect
```

The skill:
Expand All @@ -54,16 +54,16 @@ Paste the output into the Figma plugin's **Component Map** tab.

A complete workflow from idea to Figma mockup:

1. **Describe your form** to Claude, or run [`/form-schema`](/guide/form-schema-skill)
2. Claude generates the JSON schema
3. Run `/figma-connect` to map your design system (one-time setup)
4. Paste the schema into the Figma plugin
1. **Describe your form** to Claude, or run [`/formhaus-create-form`](/guide/formhaus-create-form)
2. Claude generates the form definition
3. Run `/formhaus-figma-connect` to map your design system (one-time setup)
4. Paste the definition into the Figma plugin
5. Click **Generate**, your form renders with your design system components

After the initial setup, you only need steps 1, 4, and 5 for each new form.

## Next steps

- [Figma Plugin](/guide/figma): how the plugin works, component map reference
- [/form-schema](/guide/form-schema-skill): generate schemas from descriptions
- [Examples](/guide/examples): example schemas to try with the plugin
- [/formhaus-create-form](/guide/formhaus-create-form): generate form definitions from descriptions
- [Examples](/guide/examples): example definitions to try with the plugin
Loading
Loading