diff --git a/v2/core-concepts/the-protocol.mdx b/v2/core-concepts/the-protocol.mdx
index ac44715..5e7fe06 100644
--- a/v2/core-concepts/the-protocol.mdx
+++ b/v2/core-concepts/the-protocol.mdx
@@ -143,6 +143,16 @@ The following headers are automatically sent by Inertia when making requests. Yo
Indicates whether the requested data should be appended or prepended when using [Infinite scroll](/v2/data-props/infinite-scroll).
+The following headers are used for [Precognition](/v2/the-basics/forms#precognition) validation requests.
+
+
+ Set to `true` to indicate this is a Precognition validation request.
+
+
+
+ Comma-separated list of field names to validate.
+
+
## Response Headers
The following headers should be sent by your server-side adapter in Inertia responses. If you're using an official server-side adapter, these are handled automatically.
@@ -159,6 +169,20 @@ The following headers should be sent by your server-side adapter in Inertia resp
Set to `X-Inertia` to help browsers correctly differentiate between HTML and JSON responses.
+The following headers are used for [Precognition](/v2/the-basics/forms#precognition) validation responses.
+
+
+ Set to `true` to indicate this is a Precognition validation response.
+
+
+
+ Set to `true` when validation passes with no errors, combined with a `204 No Content` status code.
+
+
+
+ Set to `Precognition` on all responses when the Precognition middleware is applied.
+
+
## The Page Object
Inertia shares data between the server and client via a page object. This object includes the necessary information required to render the page component, update the browser's history state, and track the site's asset version. The page object can include the following properties:
@@ -442,3 +466,10 @@ Inertia uses specific HTTP status codes to handle different scenarios.
| **302 Found** | Standard redirect response. Inertia's server-side adapters automatically convert this to `303 See Other` when returned after `PUT`, `PATCH`, or `DELETE` requests. |
| **303 See Other** | Used for redirects after non-GET requests. This status code tells the browser to make a `GET` request to the redirect URL, preventing duplicate form submissions that could occur if the browser repeated the original request method. |
| **409 Conflict** | Returned when there's an asset version mismatch or for external redirects. For asset mismatches, this prompts a full page reload. For external redirects, the response includes an `X-Inertia-Location` header and triggers a `window.location` redirect client-side. |
+
+The following status codes are used for [Precognition](/v2/the-basics/forms#precognition) validation requests.
+
+| Status Code | Description |
+|:------------------------------|:------------------------------------------------------------------------------------------------|
+| **204 No Content** | Successful Precognition validation request with no validation errors. |
+| **422 Unprocessable Entity** | Precognition validation request with validation errors. The response body contains the errors. |
diff --git a/v2/the-basics/forms.mdx b/v2/the-basics/forms.mdx
index d906887..621e089 100644
--- a/v2/the-basics/forms.mdx
+++ b/v2/the-basics/forms.mdx
@@ -954,6 +954,427 @@ function handleSubmit() {
In React and Vue, refs provide access to all form methods and reactive state. In Svelte, refs expose only methods, so reactive state like `isDirty` and `errors` should be accessed via [slot props](#slot-props) instead.
+### Precognition
+
+The `
` component, Inertia also provides a `useForm` helper for when you need programmatic control over your form's data and submission behavior.
@@ -1561,6 +1982,311 @@ form.submit(store())
+### Precognition
+
+Just like the `
` component, the `useForm` helper supports [Precognition](#precognition) for real-time validation. You may enable it by chaining the `withPrecognition()` method with the HTTP method and endpoint for validation requests.
+
+
+
+```js Vue icon="vuejs"
+import { useForm } from '@inertiajs/vue3'
+
+const form = useForm({
+ name: '',
+ email: '',
+}).withPrecognition('post', '/users')
+```
+
+```js React icon="react"
+import { useForm } from '@inertiajs/react'
+
+const form = useForm({
+ name: '',
+ email: '',
+}).withPrecognition('post', '/users')
+```
+
+```js Svelte icon="s"
+import { useForm } from '@inertiajs/svelte'
+
+const form = useForm({
+ name: '',
+ email: '',
+}).withPrecognition('post', '/users')
+```
+
+
+
+For backwards compatibility with the `laravel-precognition` packages, you may also pass the method and URL as the first arguments to `useForm()`.
+
+```js
+const form = useForm('post', '/users', {
+ name: '',
+ email: '',
+})
+```
+
+You may also use [Wayfinder](https://github.com/laravel/wayfinder) when enabling Precognition.
+
+```js
+import { store } from 'App/Http/Controllers/UserController'
+
+const form = useForm({
+ name: '',
+ email: '',
+}).withPrecognition(store())
+
+// Or passing Wayfinder as the first argument...
+const form = useForm(store(), {
+ name: '',
+ email: '',
+})
+```
+
+Once Precognition is enabled, call `validate()` with a field name to trigger validation for that field. The `invalid()` helper checks if a field has validation errors, while `validating` indicates when a request is in progress.
+
+
+
+```vue Vue icon="vuejs"
+
+
+
+
+```
+
+
+
+You may also use the `valid()` helper to check if a field has passed validation.
+
+#### Touch and Validate
+
+The `touch()` method marks fields as "touched" without triggering validation. You may then validate all touched fields by calling `validate()` without arguments. The `touched()` helper checks if a field has been touched. The `reset()` method clears the touched state for reset fields.
+
+
+
+```vue Vue icon="vuejs"
+
+
+
+
+
+
+{/if}
+```
+
+
+
+#### Options
+
+Validation requests are automatically debounced. The first request fires immediately, then subsequent changes are debounced (1500ms by default). You may customize this timeout using `setValidationTimeout()`.
+
+
+
+```js Vue icon="vuejs"
+const form = useForm('post', '/users', {
+ name: '',
+}).setValidationTimeout(500)
+```
+
+```js React icon="react"
+const form = useForm('post', '/users', {
+ name: '',
+})
+
+form.setValidationTimeout(500)
+```
+
+```js Svelte icon="s"
+const form = useForm('post', '/users', {
+ name: '',
+})
+
+$form.setValidationTimeout(500)
+```
+
+
+
+By default, files are excluded from validation requests to avoid unnecessary uploads. You may enable file validation using `validateFiles()`.
+
+
+
+```js Vue icon="vuejs"
+const form = useForm('post', '/users', {
+ avatar: null,
+}).validateFiles()
+```
+
+```js React icon="react"
+const form = useForm('post', '/users', {
+ avatar: null,
+})
+
+form.validateFiles()
+```
+
+```js Svelte icon="s"
+const form = useForm('post', '/users', {
+ avatar: null,
+})
+
+$form.validateFiles()
+```
+
+
+
+By default, validation errors are simplified to strings (the first error message). You can indicate you would like all errors as arrays using `withAllErrors()`.
+
+
+
+```js Vue icon="vuejs"
+const form = useForm('post', '/users', {
+ name: '',
+}).withAllErrors()
+```
+
+```js React icon="react"
+const form = useForm('post', '/users', {
+ name: '',
+})
+
+form.withAllErrors()
+```
+
+```js Svelte icon="s"
+const form = useForm('post', '/users', {
+ name: '',
+})
+
+$form.withAllErrors()
+```
+
+
+
+With Precognition enabled, you may call `submit()` without arguments to submit to the configured endpoint.
+
## Server-Side Responses
When using Inertia, you don't typically inspect form responses client-side like you would with traditional XHR/fetch requests. Instead, your server-side route or controller issues a [redirect](/v2/the-basics/redirects) response after processing the form, often redirecting to a success page.