
Security News
Feross on TBPN: How North Korea Hijacked Axios
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.
@rilaykit/forms
Advanced tools
The form builder and React rendering layer for RilayKit — build type-safe, headless forms from declarative schemas.
@rilaykit/forms provides a fluent builder API to define form configurations and headless React components to render them. State management is powered by Zustand with granular selectors for optimal re-render performance.
# pnpm (recommended)
pnpm add @rilaykit/core @rilaykit/forms
# npm
npm install @rilaykit/core @rilaykit/forms
# yarn
yarn add @rilaykit/core @rilaykit/forms
# bun
bun add @rilaykit/core @rilaykit/forms
@rilaykit/coreis a required peer dependency.
import { ril } from '@rilaykit/core';
import { Input } from './components/Input';
const rilay = ril.create()
.addComponent('input', { renderer: Input });
import { form } from '@rilaykit/forms';
import { required, email } from '@rilaykit/core';
const loginForm = form
.create(rilay, 'login')
.add({
id: 'email',
type: 'input',
props: { label: 'Email', type: 'email' },
validation: { validate: [required(), email()] },
})
.add({
id: 'password',
type: 'input',
props: { label: 'Password', type: 'password' },
validation: { validate: [required()] },
});
import { Form, FormField } from '@rilaykit/forms';
function LoginForm() {
const handleSubmit = (data: { email: string; password: string }) => {
console.log('Login:', data);
};
return (
<Form formConfig={loginForm} onSubmit={handleSubmit}>
<FormField fieldId="email" />
<FormField fieldId="password" />
<button type="submit">Sign In</button>
</Form>
);
}
Construct forms with a chainable, type-safe API. Each field type and its props are validated at compile time.
import { form } from '@rilaykit/forms';
const contactForm = form
.create(rilay, 'contact')
.add(
{ id: 'firstName', type: 'input', props: { label: 'First Name' } },
{ id: 'lastName', type: 'input', props: { label: 'Last Name' } },
)
.add({
id: 'message',
type: 'textarea',
props: { label: 'Message', rows: 5 },
validation: { validate: [required()] },
});
// Serialize, clone, inspect
const json = contactForm.toJSON();
const variant = contactForm.clone('contact-v2');
const stats = contactForm.getStats();
Zero HTML, zero CSS. You provide the renderers, RilayKit handles state, validation, and orchestration.
| Component | Description |
|---|---|
<Form> | Main wrapper — manages context, state, and submission |
<FormProvider> | Context provider (used separately from Form when needed) |
<FormBody> | Renders the full form body from configuration |
<FormField> | Renders a single field by ID |
<FormRow> | Renders a row of fields |
<FormSubmitButton> | Submit button with loading/disabled state |
Each form instance gets its own Zustand store with granular selectors — only the fields that change trigger re-renders.
import {
useFieldValue,
useFieldErrors,
useFieldTouched,
useFieldState,
useFormValues,
useFormValid,
useFormDirty,
useFormSubmitting,
useFieldActions,
useFormActions,
} from '@rilaykit/forms';
function CustomField({ fieldId }: { fieldId: string }) {
const value = useFieldValue(fieldId);
const errors = useFieldErrors(fieldId);
const { setValue, setTouched } = useFieldActions(fieldId);
// ...
}
Combined with @rilaykit/core's condition system, fields show/hide reactively based on other field values.
import { when } from '@rilaykit/core';
form.create(rilay, 'account')
.add({
id: 'accountType',
type: 'select',
props: { options: [{ value: 'business', label: 'Business' }] },
})
.add({
id: 'companyName',
type: 'input',
props: { label: 'Company Name' },
conditions: { visible: when('accountType').equals('business') },
});
Supports built-in validators, Standard Schema libraries (Zod, Valibot, Yup...), and custom validators — all in the same field.
import { z } from 'zod';
import { required } from '@rilaykit/core';
validation: {
validate: [required(), z.string().email()],
validateOnBlur: true,
}
| Method | Description |
|---|---|
form.create(ril, id?) | Create a new form builder |
.add(...fields) | Add fields to the form |
.addSeparateRows(fields) | Each field on its own row |
.updateField(id, updates) | Update a field definition |
.removeField(id) | Remove a field |
.setValidation(config) | Set form-level validation |
.addFieldConditions(id, conditions) | Add conditional logic |
.build() | Produce the final FormConfiguration |
.toJSON() / .fromJSON(json) | Serialize / deserialize |
.clone(newId?) | Clone the form configuration |
| Hook | Description |
|---|---|
useFieldValue(id) | Current field value |
useFieldErrors(id) | Field validation errors |
useFieldTouched(id) | Whether field has been touched |
useFieldState(id) | Combined field state |
useFieldActions(id) | setValue, setTouched, etc. |
useFieldConditions(id) | Evaluated condition results |
useFormValues() | All form values |
useFormValid() | Whether form is valid |
useFormDirty() | Whether form has unsaved changes |
useFormSubmitting() | Whether form is submitting |
useFormActions() | submit, reset, validate, etc. |
@rilaykit/core (registry, types, validation, conditions)
↑
@rilaykit/forms ← you are here
↑
@rilaykit/workflow (multi-step workflows)
Generate forms from JSON schemas sent by the backend — no frontend redeployment needed.
import { fromSchema } from '@rilaykit/forms';
const { formConfig, defaultValues } = fromSchema(schema, rilConfig, registry);
Supports validation descriptors, conditions, effects via registry handlers, and repeatable groups. See the Server-Driven Forms guide for details.
Full documentation at rilay.dev:
MIT — see LICENSE for details.
FAQs
Form building utilities and components for RilayKit
We found that @rilaykit/forms demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.

Security News
OpenSSF has issued a high-severity advisory warning open source developers of an active Slack-based campaign using impersonation to deliver malware.

Research
/Security News
Malicious packages published to npm, PyPI, Go Modules, crates.io, and Packagist impersonate developer tooling to fetch staged malware, steal credentials and wallets, and enable remote access.