From 0580ae0cb86deaad8f4288a5cd78a1b5b57165d2 Mon Sep 17 00:00:00 2001 From: thejahid Date: Sun, 19 Jul 2026 22:52:40 +0600 Subject: [PATCH 1/6] Update package.json to support Node.js 24.18.0 and enhance Freeform documentation for headless setups, including React and Next.js. Revise descriptions, add installation instructions, and clarify usage of GraphQL and REST API. Adjust sidebar positions for better navigation. --- craft-freeform/headless/getting-started.mdx | 151 ++++++++++++++ craft-freeform/headless/graphql.mdx | 6 +- craft-freeform/headless/index.mdx | 43 +++- craft-freeform/headless/nextjs.mdx | 167 +++++++++++++-- craft-freeform/headless/reactjs.mdx | 215 ++++++++++++++++++-- craft-freeform/headless/rest-api.mdx | 166 +++++++++++++++ craft-freeform/headless/vuejs.mdx | 6 +- craft-freeform/intro.mdx | 16 +- craft-freeform/setup/betas.mdx | 32 ++- package.json | 2 +- 10 files changed, 746 insertions(+), 58 deletions(-) create mode 100644 craft-freeform/headless/getting-started.mdx create mode 100644 craft-freeform/headless/rest-api.mdx diff --git a/craft-freeform/headless/getting-started.mdx b/craft-freeform/headless/getting-started.mdx new file mode 100644 index 00000000..804f8615 --- /dev/null +++ b/craft-freeform/headless/getting-started.mdx @@ -0,0 +1,151 @@ +--- +title: Getting Started +sidebar_position: 1 +description: Install and enable Freeform's official headless React packages for Craft CMS (npm public beta). +--- + +import { Badge, BadgeGroup } from '@site/src/components/utils'; +import { VerticalStepWrapper, StepMarkdown } from '@site/src/components/docs'; + +# Getting Started (React Headless) + +:::info npm Public Beta — `0.1.0-beta.1` +The official `@solspace/freeform-*` packages ship on the npm **`beta`** tag (`0.1.0-beta.x`). The Freeform **Craft plugin** (with the headless REST API) ships as a normal release on main — not as a plugin beta. Package APIs may still change before a stable `0.1.0` / `1.0.0`. +::: + +Freeform’s recommended headless path for React and Next.js is: + +1. Use a Freeform plugin build that includes the **headless REST API** +2. Enable headless in Freeform config +3. Install the official npm packages (`@beta`) +4. Render forms with `` or build your own UI with `useFreeform()` + +GraphQL and older AJAX demos remain available, but new React/Next.js projects should start here. + +## Requirements + +| Piece | Version / notes | +| --- | --- | +| Craft CMS | 4.17+ or 5.9+ | +| Freeform plugin | Build that includes headless REST (merged to main) | +| npm packages | **`0.1.0-beta.1`** (`@beta` tag) | +| React | 18 or 19 | +| Node | Modern LTS with `npm` / `pnpm` / `yarn` | + +## Quick setup + + + + +Headless is **off by default**. Add a `headless` section to your Craft project’s `config/freeform.php` (merge with your existing config): + +```php title="config/freeform.php" showLineNumbers + [ + // Master switch — endpoints return 404 when false + 'enabled' => true, + + // CORS origins for browser apps that call Craft directly + 'allowedOrigins' => [ + 'http://localhost:3000', + 'https://app.example.com', + ], + + // Per-form exposure (keyed by form handle) + 'forms' => [ + 'contact' => [ + 'exposeManifest' => true, + 'allowSubmit' => true, + ], + ], + ], +]; +``` + +:::tip Same-origin proxy +If your frontend proxies `/freeform/*` to Craft (recommended for Next.js), CSRF cookies stay same-origin and you can keep `allowedOrigins` tight. +::: + +See the full [REST API](./rest-api.mdx) reference for profiles, CSRF, and submit details. + + + + +```bash +npm install @solspace/freeform-core@beta \ + @solspace/freeform-react@beta \ + @solspace/freeform-extensions@beta \ + @solspace/freeform-react-theme-default@beta +``` + +| Package | Purpose | +| --- | --- | +| `@solspace/freeform-core` | Manifest client, form state, conditionals, submit | +| `@solspace/freeform-react` | `` component and `useFreeform()` hook | +| `@solspace/freeform-extensions` | Captchas, datetime picker, file drag & drop | +| `@solspace/freeform-react-theme-default` | Default light/dark theme CSS | + + + + +```tsx title="ContactForm.tsx" showLineNumbers +import { Freeform } from '@solspace/freeform-react'; +import { recommendedExtensions } from '@solspace/freeform-extensions'; +import '@solspace/freeform-react-theme-default/styles.css'; + +export function ContactForm() { + return ( + { + console.log('Submitted', response); + }} + /> + ); +} +``` + +- **`handle`** — Freeform form handle (must be enabled under `headless.forms`) +- **`baseUrl`** — Craft site origin, **or** `""` / same origin when you proxy `/freeform` +- **`extensions`** — register captchas and advanced fields when the form needs them + + + + +## Choose your guide + +| Guide | When to use it | +| --- | --- | +| [React JS](./reactjs.mdx) | Vite, CRA, Remix, or any React SPA | +| [Next.js](./nextjs.mdx) | App Router / Pages Router + proxy | +| [REST API](./rest-api.mdx) | Endpoints, CSRF, CORS, profiles | +| [GraphQL](./graphql.mdx) | Existing GraphQL integrations (alternate path) | + +## What’s included in this npm beta + +- Manifest load + CSRF + submit (JSON and multipart) +- Multi-page forms and conditionals (client UX) +- Captchas via `@solspace/freeform-extensions` +- File upload and File Drag & Drop +- Default theme with light / dark / system color schemes + +## Deferred (coming later) + +- Drafts / save & continue +- Payment fields (Stripe, etc.) +- Calculation fields +- Official Vue adapter +- Bootstrap and Tailwind theme packages +- Full GraphQL parity with the REST contract + +## Security checklist + +1. Keep headless **disabled** until you intentionally enable forms. +2. Set explicit `headless.allowedOrigins` for cross-origin apps. +3. Enable a **captcha** on public forms (do not rely on honeypot alone for API callers). +4. Leave **`allowRawHtml` off** unless HTML / rich-text field content is trusted CMS content. +5. Do not treat client-side conditional hiding as a server access-control boundary yet. diff --git a/craft-freeform/headless/graphql.mdx b/craft-freeform/headless/graphql.mdx index ffd6295f..0e0198d6 100644 --- a/craft-freeform/headless/graphql.mdx +++ b/craft-freeform/headless/graphql.mdx @@ -1,6 +1,6 @@ --- title: GraphQL -sidebar_position: 1 +sidebar_position: 6 description: Integrate Freeform 5.x with GraphQL in Craft CMS for headless form handling and submissions. --- @@ -14,6 +14,10 @@ import { VerticalStepWrapper, StepMarkdown } from '@site/src/components/docs'; Freeform supports querying form layouts and form submission mutations via GraphQL. This guide assumes you have some GraphQL experience. To learn more about GraphQL and Craft, please check out the [Fetch content with GraphQL](https://craftcms.com/docs/getting-started-tutorial/build/graphql.html) guide and [Craft's GraphQL API](https://craftcms.com/docs/5.x/development/graphql.html). +:::tip New React / Next.js projects +For new React and Next.js apps, prefer the official packages and [REST API](./rest-api.mdx) — start with [Getting Started](./getting-started.mdx). GraphQL remains fully supported for existing headless integrations. +::: + or build your own UI with useFreeform().', icon: Icons.ReactIcon, fullCardLink: 'reactjs', + titleBadge: 'Beta', }, { title: 'Next.js', - description: 'Full support for implementation Freeform with Next.js.', + description: + 'App Router Client Components, rewrites proxy, and CSRF-friendly setup.', icon: Icons.NextjsIcon, fullCardLink: 'nextjs', filterIcon: true, + titleBadge: 'Beta', + }, + { + title: 'Vue.js', + description: + 'Headless demos for Vue.js (official Vue package coming later).', + icon: Icons.VuejsIcon, + fullCardLink: 'vuejs', }, { title: 'GraphQL', description: - 'With Freeform, you can easily query form layouts and submit form mutations using GraphQL.', + 'Query form layouts and create submissions with GraphQL mutations.', icon: Icons.GraphqlIcon, fullCardLink: 'graphql', }, diff --git a/craft-freeform/headless/nextjs.mdx b/craft-freeform/headless/nextjs.mdx index 4fb897b5..cd42e66a 100644 --- a/craft-freeform/headless/nextjs.mdx +++ b/craft-freeform/headless/nextjs.mdx @@ -1,33 +1,168 @@ --- title: Next.js sidebar_position: 4 -description: Build headless forms with Freeform 5.x and Next.js in Craft CMS. +description: Build headless Freeform forms with Next.js and the official React packages for Craft CMS. --- import { Badge, BadgeGroup } from '@site/src/components/utils'; +import { VerticalStepWrapper, StepMarkdown } from '@site/src/components/docs'; -# Next.js Implementations +# Next.js -:::warning -Please see the [How to Render a Form](./graphql.mdx#how-to-render-a-form) guide for detailed steps for being able to render your own form in the front-end using GraphQL data and Next.js. +:::info npm Public Beta — `0.1.0-beta.1` +Use the official `@solspace/freeform-react` packages. Complete [Getting Started](./getting-started.mdx) (enable headless + install packages) first. The Freeform plugin itself is a normal release. ::: -## GraphQL Demo +Freeform’s React packages are client-side. In the App Router, render them from a **Client Component** and proxy `/freeform` so CSRF cookies stay on your Next.js origin. -The below demo link shows how Freeform is implemented with [Next.js](https://react.dev/) and [GraphQL](./graphql.mdx). +## Install -:::info -Please note that the paths in the demos are specific for the Solspace demo site and server. Please make sure your code uses paths that match your server setup. -::: +```bash +npm install @solspace/freeform-core@beta \ + @solspace/freeform-react@beta \ + @solspace/freeform-extensions@beta \ + @solspace/freeform-react-theme-default@beta +``` -https://github.com/solspace/craft-freeform-demo-nextjs-graphql +## Setup -## AJAX Demo + + -The below demo link shows how Freeform is implemented with [Next.js](https://react.dev/) and AJAX. +```ts title="next.config.ts" showLineNumbers +import type { NextConfig } from 'next'; -:::info -Please note that the paths in the demos are specific for the Solspace demo site and server. Please make sure your code uses paths that match your server setup. -::: +const nextConfig: NextConfig = { + async rewrites() { + return [ + { + source: '/freeform/:path*', + destination: `${process.env.CRAFT_URL}/freeform/:path*`, + }, + ]; + }, +}; + +export default nextConfig; +``` + +Set `CRAFT_URL` to your Craft site (for example `https://cms.example.com`). Requests from the browser hit `/freeform/...` on the Next.js origin; Next.js forwards them to Craft. + + + + +```tsx title="app/contact/contact-form.tsx" showLineNumbers +'use client'; + +import { Freeform } from '@solspace/freeform-react'; +import { recommendedExtensions } from '@solspace/freeform-extensions'; +import '@solspace/freeform-react-theme-default/styles.css'; + +export function ContactForm() { + return ( + { + console.log(response); + }} + /> + ); +} +``` + +```tsx title="app/contact/page.tsx" showLineNumbers +import { ContactForm } from './contact-form'; + +export default function ContactPage() { + return ( +
+

Contact

+ +
+ ); +} +``` + +
+ + +In `config/freeform.php` on Craft: + +```php +'headless' => [ + 'enabled' => true, + 'forms' => [ + 'contact' => [ + 'exposeManifest' => true, + 'allowSubmit' => true, + ], + ], +], +``` + +With the same-origin proxy you usually do **not** need to add the Next.js origin to `allowedOrigins`. Add it only if the browser calls Craft directly. + + +
+ +## Environment variables + +| Variable | Where | Example | +| --- | --- | --- | +| `CRAFT_URL` | Next.js server (rewrites) | `https://cms.example.com` | +| `NEXT_PUBLIC_CRAFT_URL` | Optional public Craft URL | Only if you skip the proxy | + +Prefer the proxy + `baseUrl=""` pattern over exposing Craft’s origin to the browser. + +## Cross-origin (no proxy) + +If the browser must call Craft directly: + +1. Set `baseUrl={process.env.NEXT_PUBLIC_CRAFT_URL}` +2. Add your Next.js origin to `headless.allowedOrigins` +3. Keep credentials enabled (default in the Freeform client) + +```tsx + +``` + +## Headless markup + +`useFreeform()` works the same as in a Vite React app — still inside a Client Component: + +```tsx +'use client'; + +import { useFreeform } from '@solspace/freeform-react'; + +export function HeadlessContactForm() { + const form = useFreeform({ + handle: 'contact', + baseUrl: '', + }); + + // …build your own fields with form.getFieldProps(), etc. +} +``` + +See [React JS](./reactjs.mdx) for themes, captchas, custom renderers, and the full hook API. + +## File uploads + +Official packages handle multipart submits and File Drag & Drop via `@solspace/freeform-extensions`. You do not need the older GraphQL Base64 upload guides for new projects. + +## Legacy demos + +Older Next.js GraphQL / AJAX demos: + +- [Next.js + GraphQL](https://github.com/solspace/craft-freeform-demo-nextjs-graphql) +- [Next.js + AJAX](https://github.com/solspace/craft-freeform-demo-nextjs-ajax) -https://github.com/solspace/craft-freeform-demo-nextjs-ajax +Recommended path for new work: this page + [Getting Started](./getting-started.mdx). diff --git a/craft-freeform/headless/reactjs.mdx b/craft-freeform/headless/reactjs.mdx index d8cd8dbf..dc3afb00 100644 --- a/craft-freeform/headless/reactjs.mdx +++ b/craft-freeform/headless/reactjs.mdx @@ -1,33 +1,220 @@ --- -title: React.js +title: React JS sidebar_position: 3 -description: Build headless forms with Freeform 5.x and React.js in Craft CMS. +description: Build headless Freeform forms with the official React packages for Craft CMS. --- import { Badge, BadgeGroup } from '@site/src/components/utils'; -# React JS Implementations +# React JS -:::warning -Please see the [How to Render a Form](./graphql.mdx#how-to-render-a-form) guide for detailed steps for being able to render your own form in the front-end using GraphQL data and React JS. +:::info npm Public Beta — `0.1.0-beta.1` +Use the official `@solspace/freeform-react` packages (`@beta` npm tag). See [Getting Started](./getting-started.mdx) for enabling the headless API. The Freeform plugin itself is a normal release. ::: -## GraphQL Demo +## Install -The below demo link shows how Freeform is implemented with [React JS](https://react.dev/) and [GraphQL](./graphql.mdx). +```bash +npm install @solspace/freeform-core@beta \ + @solspace/freeform-react@beta \ + @solspace/freeform-extensions@beta \ + @solspace/freeform-react-theme-default@beta +``` -:::info -Please note that the paths in the demos are specific for the Solspace demo site and server. Please make sure your code uses paths that match your server setup. -::: +Import the default theme CSS once in your app entry: + +```tsx +import '@solspace/freeform-react-theme-default/styles.css'; +``` + +## Render with `` + +The easiest path — Freeform loads the manifest, manages state, renders fields, handles CSRF, and submits: + +```tsx title="ContactForm.tsx" showLineNumbers +import { Freeform } from '@solspace/freeform-react'; +import { recommendedExtensions } from '@solspace/freeform-extensions'; +import '@solspace/freeform-react-theme-default/styles.css'; + +export function ContactForm() { + return ( + { + // response.success, response.submission, etc. + }} + onError={(response) => { + // Field / form errors from Freeform + }} + /> + ); +} +``` + +| Prop | Description | +| --- | --- | +| `handle` | Form handle (must be allowed in `headless.forms`) | +| `baseUrl` | Craft origin. Use `""` or your SPA origin when `/freeform` is proxied. | +| `extensions` | Captcha / datetime / file-dnd extensions | +| `theme` | Optional theme object (`lightTheme`, `darkTheme`, or `createTheme()`) | +| `allowRawHtml` | Default `false`. Set `true` only if HTML/rich-text fields are trusted CMS content. | +| `loadingFallback` / `errorFallback` | Custom loading and error UI | + +### Light / dark theme + +```tsx +import { Freeform } from '@solspace/freeform-react'; +import { + darkTheme, + lightTheme, +} from '@solspace/freeform-react-theme-default'; +import '@solspace/freeform-react-theme-default/styles.css'; + +; +// or theme={lightTheme} +``` + +By default the theme follows the visitor’s OS preference (`system`). + +## Headless control with `useFreeform()` + +Own the markup while Freeform still loads the form, tracks values, evaluates conditionals, and submits: + +```tsx title="HeadlessContactForm.tsx" showLineNumbers +import { useFreeform } from '@solspace/freeform-react'; +import { recommendedExtensions } from '@solspace/freeform-extensions'; + +export function HeadlessContactForm() { + const form = useFreeform({ + handle: 'contact', + baseUrl: 'https://cms.example.com', + extensions: recommendedExtensions, + }); + + if (form.loading) { + return

Loading…

; + } + + if (form.error) { + return

{form.error.message}

; + } + + return ( +
+ {form.formErrors.map((message) => ( +
+ {message} +
+ ))} + + -https://github.com/solspace/craft-freeform-demo-reactjs-graphql + -## AJAX Demo + {form.isComplete && form.successMessage ? ( +

{form.successMessage}

+ ) : null} +
+ ); +} +``` -The below demo link shows how Freeform is implemented with [React JS](https://react.dev/) and AJAX. +Useful helpers on the hook result: + +| API | Purpose | +| --- | --- | +| `getFieldProps(handle)` | `name`, `id`, `onChange`, `onBlur`, etc. | +| `values` / `setValue` | Read / write field values | +| `fieldErrors` / `formErrors` | Validation messages | +| `isFieldVisible(handle)` | Conditional visibility | +| `handleSubmit` / `goNext` / `goBack` | Submit and multi-page | + +## Captchas and advanced fields + +Pass `recommendedExtensions` (or a subset) so Freeform can mount captchas, Flatpickr datetime fields, and File Drag & Drop: + +```tsx +import { + captchaExtensions, + datetimeExtension, + fileDndExtension, + recommendedExtensions, +} from '@solspace/freeform-extensions'; + +// All of the above: + + +// Or pick what you need: + +``` + +Configure captcha integrations in the Freeform control panel. Site keys are exposed on the form manifest; tokens are submitted automatically through `meta.captchas`. + +## Custom field renderers + +Override rendering by handle, frontend renderer key, or field type: + +```tsx + +``` + +## Same-origin proxy (recommended) + +Point your Vite (or other) dev server at Craft so CSRF cookies stay same-origin: + +```ts title="vite.config.ts" +export default { + server: { + proxy: { + '/freeform': { + target: 'https://cms.example.com', + changeOrigin: true, + secure: false, // local TLS only + }, + }, + }, +}; +``` + +Then use `baseUrl=""` (or `window.location.origin`) in the browser. + +For Next.js, see the [Next.js](./nextjs.mdx) guide. + +## Security notes + +- Leave **`allowRawHtml`** at the default (`false`) unless HTML fields are trusted. +- Enable a **captcha** on public forms. +- Set **`headless.allowedOrigins`** when calling Craft cross-origin. +- See [REST API](./rest-api.mdx) for CORS and CSRF details. + +## Legacy GraphQL / AJAX demos + +Older demos that query Freeform via GraphQL or custom AJAX still work, but are **not** the recommended path for new projects: :::info Please note that the paths in the demos are specific for the Solspace demo site and server. Please make sure your code uses paths that match your server setup. ::: -https://github.com/solspace/craft-freeform-demo-reactjs-ajax +- [React + GraphQL demo](https://github.com/solspace/craft-freeform-demo-reactjs-graphql) +- [React + AJAX demo](https://github.com/solspace/craft-freeform-demo-reactjs-ajax) + +For GraphQL field queries and mutations, see [GraphQL](./graphql.mdx). diff --git a/craft-freeform/headless/rest-api.mdx b/craft-freeform/headless/rest-api.mdx new file mode 100644 index 00000000..606f5271 --- /dev/null +++ b/craft-freeform/headless/rest-api.mdx @@ -0,0 +1,166 @@ +--- +title: REST API +sidebar_position: 2 +description: Freeform headless REST API for manifests, submissions, CSRF, CORS, and file uploads in Craft CMS. +--- + +import { Badge, BadgeGroup } from '@site/src/components/utils'; + +# REST API + +:::info npm Public Beta — `@solspace/freeform-*` `0.1.0-beta.1` +The headless REST API ships with the Freeform plugin (normal release). Official npm clients are on a separate **`0.1.0-beta.x`** line. +::: + +Most customers should use [`@solspace/freeform-react`](./reactjs.mdx) and never call these endpoints by hand. This page is the contract reference when you build a custom client or debug requests. + +## Enable the API + +Merge into `config/freeform.php`: + +```php title="config/freeform.php" showLineNumbers + [ + 'enabled' => true, + 'allowedOrigins' => [ + 'http://localhost:3000', + 'https://app.example.com', + ], + 'forms' => [ + 'contact' => [ + 'exposeManifest' => true, + 'allowSubmit' => true, + // Optional per-form CORS override + // 'allowedOrigins' => ['https://app.example.com'], + ], + ], + ], +]; +``` + +| Setting | Purpose | +| --- | --- | +| `headless.enabled` | Master switch. When `false`, headless routes return 404. | +| `headless.allowedOrigins` | Global CORS allow-list (supports `*` wildcards like `https://*.example.com`). | +| `forms.{handle}.exposeManifest` | Allow `GET` manifest for that form. | +| `forms.{handle}.allowSubmit` | Allow `POST` submit for that form. | + +A config example ships with Freeform at `packages/plugin/config/headless.example.php`. + +## Endpoints + +URLs below are relative to your Craft site. Official clients resolve them with your `baseUrl`. + +### Form manifest + +```http +GET /freeform/api/forms/{handle}/manifest +Accept: application/json +``` + +Returns layout, fields, conditionals, security metadata, and submit endpoint URLs. + +### Submit + +```http +POST /freeform/api/forms/{handle}/submit +Content-Type: application/json +# or multipart/form-data +``` + +JSON body shape (simplified): + +```json +{ + "values": { + "email": "jane@example.com", + "message": "Hello" + }, + "intent": "submit", + "meta": { + "honeypot": { "name": "freeform_form_handle", "value": "" }, + "javascriptTest": { "name": "freeform_form_handle", "value": "" }, + "captchas": [{ "name": "g-recaptcha-response", "value": "…" }] + } +} +``` + +| Intent | Use | +| --- | --- | +| `submit` | Final submit (or single-page forms) | +| `next` / `back` | Multi-page navigation | +| `validate` | Validate without completing | +| `saveDraft` | Reserved — drafts are not in this beta | + +**Multipart** submits use a `_freeform` JSON field for the payload plus file inputs, matching what `@solspace/freeform-core` sends automatically. + +### CSRF token + +```http +GET /freeform/tokens +Accept: application/json +``` + +When Craft CSRF is enabled, include the token on submit: + +- JSON: header `X-CSRF-Token: {value}` +- Multipart: form field named with the Craft CSRF param + +Official clients fetch and attach this for you when `credentials: "include"` is used (default). + +### File Drag & Drop + +```http +POST /freeform/api/forms/{handle}/files/{fieldHandle} +POST /freeform/api/forms/{handle}/files/{fieldHandle}/delete +``` + +Used by the `file-dnd` extension. Requires CSRF and the upload token header provided by the client. + +### Named profiles (advanced) + +```http +GET /freeform/api/manifests/{profile}/manifest?properties[eventId]=123 +POST /freeform/api/manifests/{profile}/submit +``` + +Profiles are explicit config entries under `headless.profiles` — never inferred from integrations. Use them for contextual manifests that need auth, signed tokens, or typed query properties. + +## CORS and credentials + +Browser apps that call Craft on another origin must: + +1. List that origin in `headless.allowedOrigins` (or per-form / per-profile overrides) +2. Send requests with credentials (`credentials: "include"`) so CSRF cookies work + +**Recommended:** proxy `/freeform/*` through your frontend (Next.js rewrites, Vite proxy, etc.) so the browser stays same-origin. + +:::warning Do not use a wildcard CORS origin in production +Set explicit origins. A misconfigured fallback to GraphQL’s `*` is unsafe for credentialed requests. +::: + +## Security metadata + +The manifest includes `security` for honeypot, javascript test, and captcha site keys. Official clients fill `meta` automatically. For public forms, enable a captcha integration in Freeform — honeypot / JS test alone are soft signals for direct API callers. + +## Compatibility headers + +Manifests include: + +```json +{ + "schemaVersion": "1.0", + "pluginVersion": "5.15.19", + "minimumClientVersion": "0.1.0" +} +``` + +`pluginVersion` matches Freeform. `minimumClientVersion` matches the npm client line (`0.1.0-beta.x` satisfies `0.1.0+`). + +## Next steps + +- [Getting Started](./getting-started.mdx) — install packages +- [React JS](./reactjs.mdx) — `` and `useFreeform()` +- [Next.js](./nextjs.mdx) — App Router + proxy diff --git a/craft-freeform/headless/vuejs.mdx b/craft-freeform/headless/vuejs.mdx index 53b1472b..31b32671 100644 --- a/craft-freeform/headless/vuejs.mdx +++ b/craft-freeform/headless/vuejs.mdx @@ -1,6 +1,6 @@ --- title: Vue.js -sidebar_position: 2 +sidebar_position: 5 description: Build headless forms with Freeform 5.x and Vue.js in Craft CMS. --- @@ -8,6 +8,10 @@ import { Badge, BadgeGroup } from '@site/src/components/utils'; # Vue.js Implementations +:::info Official Vue package — coming later +Freeform’s first-class headless packages currently target **React / Next.js** (public beta). An official `@solspace/freeform-vue` adapter is planned after the React beta. Until then, use GraphQL or custom AJAX as shown below, or call the [REST API](./rest-api.mdx) from your own Vue client. +::: + :::warning Please see the [How to Render a Form](./graphql.mdx#how-to-render-a-form) guide for detailed steps for being able to render your own form in the front-end using GraphQL data and Vue.js. ::: diff --git a/craft-freeform/intro.mdx b/craft-freeform/intro.mdx index 7dc50f20..3f977ea6 100644 --- a/craft-freeform/intro.mdx +++ b/craft-freeform/intro.mdx @@ -1377,7 +1377,7 @@ import Icons from '@site/static/icons/cards'; or useFreeform().', icon: Icons.ReactIcon, linkWithDescription: 'headless/reactjs', }, { title: 'Next.js', - description: 'Full support for implementation Freeform with Next.js.', + description: 'App Router Client Components and CSRF-friendly proxy setup.', icon: Icons.NextjsIcon, filterIcon: true, linkWithDescription: 'headless/nextjs', }, { title: 'GraphQL', - description: 'With Freeform, you can easily query form layouts and submit form mutations using GraphQL.', + description: 'Query form layouts and create submissions with GraphQL mutations.', icon: Icons.GraphqlIcon, linkWithDescription: 'headless/graphql', }, diff --git a/craft-freeform/setup/betas.mdx b/craft-freeform/setup/betas.mdx index d4e29212..db1998bb 100644 --- a/craft-freeform/setup/betas.mdx +++ b/craft-freeform/setup/betas.mdx @@ -10,30 +10,44 @@ import { Photo } from '@site/src/components/utils'; As part of our commitment to developing and releasing reliable and stable software, we thoroughly beta test all major and minor feature releases. -:::info -Freeform 5 is now available! -::: - ## Current Beta -

Stay tuned for the next Freeform beta!

+### Headless React npm packages — `0.1.0-beta.1` + +Public **npm** beta of first-class headless support for **React** and **Next.js**. The Freeform **Craft plugin** (headless REST API) ships as a normal release — only the frontend packages use the `beta` tag. + +- `@solspace/freeform-core@0.1.0-beta.1` +- `@solspace/freeform-react@0.1.0-beta.1` +- `@solspace/freeform-extensions@0.1.0-beta.1` +- `@solspace/freeform-react-theme-default@0.1.0-beta.1` + +**Customer docs:** [Headless → Getting Started](../headless/getting-started.mdx) + +#### Install the npm packages + +```bash +npm install @solspace/freeform-core@beta \ + @solspace/freeform-react@beta \ + @solspace/freeform-extensions@beta \ + @solspace/freeform-react-theme-default@beta +``` -If you wish to join this beta, please follow the instructions and guide below. +Use a Freeform plugin build that includes the headless REST API, then enable headless in `config/freeform.php` (see Getting Started). :::danger -While we carefully develop new features and put all of them through rigorous alpha and beta testing, we cannot guarantee that there will be no major issues in beta software. It's also possible that specific edge case scenarios may have been missed, etc. For this reason, we strongly advise you **not** to use the current beta version in production environments. +While we carefully develop new features and put all of them through rigorous alpha and beta testing, we cannot guarantee that there will be no major issues in beta software. It's also possible that specific edge case scenarios may have been missed, etc. For this reason, we strongly advise you to test thoroughly before relying on the npm beta packages in production — and keep headless disabled until you are ready. ::: ## Providing Feedback We would greatly appreciate it if you are able to provide us with routine feedback throughout your testing and usage of the beta. Even if you aren't using any of the new features or changes, providing feedback allows us to get a better idea of how things are going for all kinds of websites. -To make this even easier, we've included a Beta Feedback widget that displays in the Freeform control panel. Just click a star rating (_5/5_ to indicate if everything is going well, or less if you are experiencing any issues) and if you have anything to clarify, fill in a quick note in the text area and click submit. You can optionally include your email address, which will also help us get in touch with you to get more information about any issues and/or assist you as necessary. +To make this even easier, we've included a Beta Feedback widget that displays in the Freeform control panel during plugin betas. Just click a star rating (_5/5_ to indicate if everything is going well, or less if you are experiencing any issues) and if you have anything to clarify, fill in a quick note in the text area and click submit. You can optionally include your email address, which will also help us get in touch with you to get more information about any issues and/or assist you as necessary. Feel free to also just use a [Private Support Ticket](/support/) or report an issue via [GitHub Issues](https://github.com/solspace/craft-freeform/issues). :::info -**This widget will only display during betas.** If you wish to disable it from displaying, add `FREEFORM_DISABLE_BETA_FEEDBACK_WIDGET=1` to your `.ENV` file. +**This widget will only display during plugin betas.** If you wish to disable it from displaying, add `FREEFORM_DISABLE_BETA_FEEDBACK_WIDGET=1` to your `.ENV` file. ::: Date: Sun, 19 Jul 2026 22:57:27 +0600 Subject: [PATCH 2/6] Update package.json to support Node.js version range and add install command in vercel.json for improved deployment setup. --- package.json | 2 +- vercel.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 8d002ed8..4abbafe9 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ ] }, "engines": { - "node": "24.18.0" + "node": ">=24.14.0 <25" }, "pnpm": { "overrides": { diff --git a/vercel.json b/vercel.json index 6017c5c0..4a734736 100644 --- a/vercel.json +++ b/vercel.json @@ -1,6 +1,7 @@ { "cleanUrls": true, "trailingSlash": true, + "installCommand": "corepack enable && pnpm install", "redirects": [ { "destination": "/craft/freeform/v5/", From 7e41112729f98116a108fa75b1bf700807cbb484 Mon Sep 17 00:00:00 2001 From: thejahid Date: Tue, 21 Jul 2026 18:43:09 +0600 Subject: [PATCH 3/6] Update Freeform documentation to reflect the release of official headless React packages (0.1.0). Revise descriptions, installation instructions, and remove references to beta versions across multiple files for clarity and consistency. --- craft-freeform/headless/getting-started.mdx | 29 +++++++++++---------- craft-freeform/headless/index.mdx | 12 +++------ craft-freeform/headless/nextjs.mdx | 12 ++++----- craft-freeform/headless/reactjs.mdx | 16 +++++++----- craft-freeform/headless/rest-api.mdx | 8 +++--- craft-freeform/headless/vuejs.mdx | 2 +- craft-freeform/intro.mdx | 4 +-- craft-freeform/setup/betas.mdx | 26 ++---------------- 8 files changed, 40 insertions(+), 69 deletions(-) diff --git a/craft-freeform/headless/getting-started.mdx b/craft-freeform/headless/getting-started.mdx index 804f8615..9054bf1e 100644 --- a/craft-freeform/headless/getting-started.mdx +++ b/craft-freeform/headless/getting-started.mdx @@ -1,7 +1,7 @@ --- title: Getting Started sidebar_position: 1 -description: Install and enable Freeform's official headless React packages for Craft CMS (npm public beta). +description: Install and enable Freeform's official headless React packages for Craft CMS. --- import { Badge, BadgeGroup } from '@site/src/components/utils'; @@ -9,26 +9,26 @@ import { VerticalStepWrapper, StepMarkdown } from '@site/src/components/docs'; # Getting Started (React Headless) -:::info npm Public Beta — `0.1.0-beta.1` -The official `@solspace/freeform-*` packages ship on the npm **`beta`** tag (`0.1.0-beta.x`). The Freeform **Craft plugin** (with the headless REST API) ships as a normal release on main — not as a plugin beta. Package APIs may still change before a stable `0.1.0` / `1.0.0`. -::: - Freeform’s recommended headless path for React and Next.js is: 1. Use a Freeform plugin build that includes the **headless REST API** 2. Enable headless in Freeform config -3. Install the official npm packages (`@beta`) +3. Install the official npm packages (`0.1.0`) 4. Render forms with `` or build your own UI with `useFreeform()` GraphQL and older AJAX demos remain available, but new React/Next.js projects should start here. +:::tip Example app +Clone the [Freeform Headless React Demo](https://github.com/solspace/freeform-headless-react-demo) to try the packages against your Craft site. +::: + ## Requirements | Piece | Version / notes | | --- | --- | | Craft CMS | 4.17+ or 5.9+ | -| Freeform plugin | Build that includes headless REST (merged to main) | -| npm packages | **`0.1.0-beta.1`** (`@beta` tag) | +| Freeform plugin | Build that includes headless REST | +| npm packages | **`0.1.0`** ([npm org](https://www.npmjs.com/org/solspace)) | | React | 18 or 19 | | Node | Modern LTS with `npm` / `pnpm` / `yarn` | @@ -74,10 +74,10 @@ See the full [REST API](./rest-api.mdx) reference for profiles, CSRF, and submit ```bash -npm install @solspace/freeform-core@beta \ - @solspace/freeform-react@beta \ - @solspace/freeform-extensions@beta \ - @solspace/freeform-react-theme-default@beta +npm install @solspace/freeform-core \ + @solspace/freeform-react \ + @solspace/freeform-extensions \ + @solspace/freeform-react-theme-default ``` | Package | Purpose | @@ -124,8 +124,9 @@ export function ContactForm() { | [Next.js](./nextjs.mdx) | App Router / Pages Router + proxy | | [REST API](./rest-api.mdx) | Endpoints, CSRF, CORS, profiles | | [GraphQL](./graphql.mdx) | Existing GraphQL integrations (alternate path) | +| [Example demo](https://github.com/solspace/freeform-headless-react-demo) | Cloneable Vite app using the published packages | -## What’s included in this npm beta +## What’s included - Manifest load + CSRF + submit (JSON and multipart) - Multi-page forms and conditionals (client UX) @@ -133,7 +134,7 @@ export function ContactForm() { - File upload and File Drag & Drop - Default theme with light / dark / system color schemes -## Deferred (coming later) +## Coming later - Drafts / save & continue - Payment fields (Stripe, etc.) diff --git a/craft-freeform/headless/index.mdx b/craft-freeform/headless/index.mdx index a3100cc5..42a60c72 100644 --- a/craft-freeform/headless/index.mdx +++ b/craft-freeform/headless/index.mdx @@ -6,11 +6,9 @@ import Icons from '@site/static/icons/cards'; Freeform supports headless website architecture for JavaScript front ends such as React, Next.js, and Vue.js. -**Recommended for new React / Next.js projects:** the official npm packages (`0.1.0-beta.x` on the `beta` tag) and the headless REST API (ships with the Freeform plugin on main). GraphQL remains available for existing integrations. +**Recommended for new React / Next.js projects:** the official npm packages (`0.1.0`) and the headless REST API. GraphQL remains available for existing integrations. -:::info Public Beta -Start with [Getting Started](./getting-started) to enable headless and install `@solspace/freeform-react`. -::: +Start with [Getting Started](./getting-started) to enable headless and install `@solspace/freeform-react`, or try the [example React demo](https://github.com/solspace/freeform-headless-react-demo). or build your own UI with useFreeform().', icon: Icons.ReactIcon, fullCardLink: 'reactjs', - titleBadge: 'Beta', }, { title: 'Next.js', @@ -46,7 +41,6 @@ Start with [Getting Started](./getting-started) to enable headless and install ` icon: Icons.NextjsIcon, fullCardLink: 'nextjs', filterIcon: true, - titleBadge: 'Beta', }, { title: 'Vue.js', diff --git a/craft-freeform/headless/nextjs.mdx b/craft-freeform/headless/nextjs.mdx index cd42e66a..1b2c9a52 100644 --- a/craft-freeform/headless/nextjs.mdx +++ b/craft-freeform/headless/nextjs.mdx @@ -9,19 +9,17 @@ import { VerticalStepWrapper, StepMarkdown } from '@site/src/components/docs'; # Next.js -:::info npm Public Beta — `0.1.0-beta.1` -Use the official `@solspace/freeform-react` packages. Complete [Getting Started](./getting-started.mdx) (enable headless + install packages) first. The Freeform plugin itself is a normal release. -::: +Use the official `@solspace/freeform-react` packages (`0.1.0`). Complete [Getting Started](./getting-started.mdx) (enable headless + install packages) first. Freeform’s React packages are client-side. In the App Router, render them from a **Client Component** and proxy `/freeform` so CSRF cookies stay on your Next.js origin. ## Install ```bash -npm install @solspace/freeform-core@beta \ - @solspace/freeform-react@beta \ - @solspace/freeform-extensions@beta \ - @solspace/freeform-react-theme-default@beta +npm install @solspace/freeform-core \ + @solspace/freeform-react \ + @solspace/freeform-extensions \ + @solspace/freeform-react-theme-default ``` ## Setup diff --git a/craft-freeform/headless/reactjs.mdx b/craft-freeform/headless/reactjs.mdx index dc3afb00..68919a64 100644 --- a/craft-freeform/headless/reactjs.mdx +++ b/craft-freeform/headless/reactjs.mdx @@ -8,17 +8,15 @@ import { Badge, BadgeGroup } from '@site/src/components/utils'; # React JS -:::info npm Public Beta — `0.1.0-beta.1` -Use the official `@solspace/freeform-react` packages (`@beta` npm tag). See [Getting Started](./getting-started.mdx) for enabling the headless API. The Freeform plugin itself is a normal release. -::: +Use the official `@solspace/freeform-react` packages (`0.1.0`). See [Getting Started](./getting-started.mdx) for enabling the headless API. ## Install ```bash -npm install @solspace/freeform-core@beta \ - @solspace/freeform-react@beta \ - @solspace/freeform-extensions@beta \ - @solspace/freeform-react-theme-default@beta +npm install @solspace/freeform-core \ + @solspace/freeform-react \ + @solspace/freeform-extensions \ + @solspace/freeform-react-theme-default ``` Import the default theme CSS once in your app entry: @@ -206,6 +204,10 @@ For Next.js, see the [Next.js](./nextjs.mdx) guide. - Set **`headless.allowedOrigins`** when calling Craft cross-origin. - See [REST API](./rest-api.mdx) for CORS and CSRF details. +## Example demo + +- [Freeform Headless React Demo](https://github.com/solspace/freeform-headless-react-demo) — Vite app using the official npm packages + ## Legacy GraphQL / AJAX demos Older demos that query Freeform via GraphQL or custom AJAX still work, but are **not** the recommended path for new projects: diff --git a/craft-freeform/headless/rest-api.mdx b/craft-freeform/headless/rest-api.mdx index 606f5271..8dca3b7d 100644 --- a/craft-freeform/headless/rest-api.mdx +++ b/craft-freeform/headless/rest-api.mdx @@ -8,9 +8,7 @@ import { Badge, BadgeGroup } from '@site/src/components/utils'; # REST API -:::info npm Public Beta — `@solspace/freeform-*` `0.1.0-beta.1` -The headless REST API ships with the Freeform plugin (normal release). Official npm clients are on a separate **`0.1.0-beta.x`** line. -::: +The headless REST API ships with the Freeform plugin. Official npm clients are on an independent **`0.1.0`** line ([npm org](https://www.npmjs.com/org/solspace)). Most customers should use [`@solspace/freeform-react`](./reactjs.mdx) and never call these endpoints by hand. This page is the contract reference when you build a custom client or debug requests. @@ -92,7 +90,7 @@ JSON body shape (simplified): | `submit` | Final submit (or single-page forms) | | `next` / `back` | Multi-page navigation | | `validate` | Validate without completing | -| `saveDraft` | Reserved — drafts are not in this beta | +| `saveDraft` | Reserved — drafts are not available yet | **Multipart** submits use a `_freeform` JSON field for the payload plus file inputs, matching what `@solspace/freeform-core` sends automatically. @@ -157,7 +155,7 @@ Manifests include: } ``` -`pluginVersion` matches Freeform. `minimumClientVersion` matches the npm client line (`0.1.0-beta.x` satisfies `0.1.0+`). +`pluginVersion` matches Freeform. `minimumClientVersion` matches the npm client line (`0.1.0+`). ## Next steps diff --git a/craft-freeform/headless/vuejs.mdx b/craft-freeform/headless/vuejs.mdx index 31b32671..27116676 100644 --- a/craft-freeform/headless/vuejs.mdx +++ b/craft-freeform/headless/vuejs.mdx @@ -9,7 +9,7 @@ import { Badge, BadgeGroup } from '@site/src/components/utils'; # Vue.js Implementations :::info Official Vue package — coming later -Freeform’s first-class headless packages currently target **React / Next.js** (public beta). An official `@solspace/freeform-vue` adapter is planned after the React beta. Until then, use GraphQL or custom AJAX as shown below, or call the [REST API](./rest-api.mdx) from your own Vue client. +Freeform’s first-class headless packages currently target **React / Next.js**. An official `@solspace/freeform-vue` adapter is planned. Until then, use GraphQL or custom AJAX as shown below, or call the [REST API](./rest-api.mdx) from your own Vue client. ::: :::warning diff --git a/craft-freeform/intro.mdx b/craft-freeform/intro.mdx index 3f977ea6..6afd6a27 100644 --- a/craft-freeform/intro.mdx +++ b/craft-freeform/intro.mdx @@ -1377,7 +1377,7 @@ import Icons from '@site/static/icons/cards'; Date: Tue, 21 Jul 2026 18:48:22 +0600 Subject: [PATCH 4/6] Enhance documentation for Freeform headless setup by clarifying configuration instructions for Craft CMS. Specify the location of the `config/freeform.php` file and emphasize that headless settings should be configured in the Craft project, not in the frontend repo. --- craft-freeform/headless/getting-started.mdx | 20 +++++++++++++++++--- craft-freeform/headless/rest-api.mdx | 4 +++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/craft-freeform/headless/getting-started.mdx b/craft-freeform/headless/getting-started.mdx index 9054bf1e..a7ce8013 100644 --- a/craft-freeform/headless/getting-started.mdx +++ b/craft-freeform/headless/getting-started.mdx @@ -35,9 +35,23 @@ Clone the [Freeform Headless React Demo](https://github.com/solspace/freeform-he ## Quick setup - + -Headless is **off by default**. Add a `headless` section to your Craft project’s `config/freeform.php` (merge with your existing config): +Headless is **off by default**. Configure it in your **Craft CMS project** (the site where Freeform is installed) — not in your React / Next.js app repo. + +Edit or create: + +```text +your-craft-project/config/freeform.php +``` + +That file lives next to Craft’s other config files (`general.php`, `routes.php`, etc.), for example: + +```text +~/Sites/my-craft-site/config/freeform.php +``` + +Merge a `headless` section into that file (keep any existing Freeform settings): ```php title="config/freeform.php" showLineNumbers [ 'contact' => [ 'exposeManifest' => true, diff --git a/craft-freeform/headless/rest-api.mdx b/craft-freeform/headless/rest-api.mdx index 8dca3b7d..f54cbf69 100644 --- a/craft-freeform/headless/rest-api.mdx +++ b/craft-freeform/headless/rest-api.mdx @@ -14,7 +14,9 @@ Most customers should use [`@solspace/freeform-react`](./reactjs.mdx) and never ## Enable the API -Merge into `config/freeform.php`: +Configure this in your **Craft CMS project** (where Freeform is installed), not in your frontend repo. + +Edit or create `config/freeform.php` alongside Craft’s other config files (e.g. `your-craft-project/config/freeform.php`). Merge a `headless` section (keep any existing Freeform settings): ```php title="config/freeform.php" showLineNumbers Date: Mon, 10 Aug 2026 12:19:54 +0600 Subject: [PATCH 5/6] Update Freeform headless documentation to remove version references and enhance clarity. Revise installation instructions for official npm packages, add details on new features like Save & Continue Later, and improve descriptions of advanced fields and extensions. --- craft-freeform/headless/getting-started.mdx | 14 +-- craft-freeform/headless/index.mdx | 2 +- craft-freeform/headless/nextjs.mdx | 2 +- craft-freeform/headless/reactjs.mdx | 98 +++++++++++++++++++-- craft-freeform/headless/rest-api.mdx | 22 ++++- 5 files changed, 120 insertions(+), 18 deletions(-) diff --git a/craft-freeform/headless/getting-started.mdx b/craft-freeform/headless/getting-started.mdx index a7ce8013..cec77a84 100644 --- a/craft-freeform/headless/getting-started.mdx +++ b/craft-freeform/headless/getting-started.mdx @@ -13,13 +13,13 @@ Freeform’s recommended headless path for React and Next.js is: 1. Use a Freeform plugin build that includes the **headless REST API** 2. Enable headless in Freeform config -3. Install the official npm packages (`0.1.0`) +3. Install the official npm packages 4. Render forms with `` or build your own UI with `useFreeform()` GraphQL and older AJAX demos remain available, but new React/Next.js projects should start here. :::tip Example app -Clone the [Freeform Headless React Demo](https://github.com/solspace/freeform-headless-react-demo) to try the packages against your Craft site. +Clone the [Freeform Headless React Demo](https://github.com/solspace/freeform-headless-react-demo) to try the packages against your Craft site (Save & Continue, table, signature, calculation, and more). ::: ## Requirements @@ -28,7 +28,7 @@ Clone the [Freeform Headless React Demo](https://github.com/solspace/freeform-he | --- | --- | | Craft CMS | 4.17+ or 5.9+ | | Freeform plugin | Build that includes headless REST | -| npm packages | **`0.1.0`** ([npm org](https://www.npmjs.com/org/solspace)) | +| npm packages | Official `@solspace/freeform-*` packages ([npm org](https://www.npmjs.com/org/solspace)) | | React | 18 or 19 | | Node | Modern LTS with `npm` / `pnpm` / `yarn` | @@ -98,7 +98,7 @@ npm install @solspace/freeform-core \ | --- | --- | | `@solspace/freeform-core` | Manifest client, form state, conditionals, submit | | `@solspace/freeform-react` | `` component and `useFreeform()` hook | -| `@solspace/freeform-extensions` | Captchas, datetime picker, file drag & drop | +| `@solspace/freeform-extensions` | Captchas, datetime, file drag & drop, calculation, table, signature | | `@solspace/freeform-react-theme-default` | Default light/dark theme CSS | @@ -146,13 +146,15 @@ export function ContactForm() { - Multi-page forms and conditionals (client UX) - Captchas via `@solspace/freeform-extensions` - File upload and File Drag & Drop +- **Save & Continue Later** (draft token + key; see [React JS](./reactjs.mdx#save--continue-later)) +- Calculation fields +- Table fields (row limits, required columns, file cells) +- Signature fields (canvas pad + clear) - Default theme with light / dark / system color schemes ## Coming later -- Drafts / save & continue - Payment fields (Stripe, etc.) -- Calculation fields - Official Vue adapter - Bootstrap and Tailwind theme packages - Full GraphQL parity with the REST contract diff --git a/craft-freeform/headless/index.mdx b/craft-freeform/headless/index.mdx index 42a60c72..dafc74af 100644 --- a/craft-freeform/headless/index.mdx +++ b/craft-freeform/headless/index.mdx @@ -6,7 +6,7 @@ import Icons from '@site/static/icons/cards'; Freeform supports headless website architecture for JavaScript front ends such as React, Next.js, and Vue.js. -**Recommended for new React / Next.js projects:** the official npm packages (`0.1.0`) and the headless REST API. GraphQL remains available for existing integrations. +**Recommended for new React / Next.js projects:** the official npm packages and the headless REST API. GraphQL remains available for existing integrations. Start with [Getting Started](./getting-started) to enable headless and install `@solspace/freeform-react`, or try the [example React demo](https://github.com/solspace/freeform-headless-react-demo). diff --git a/craft-freeform/headless/nextjs.mdx b/craft-freeform/headless/nextjs.mdx index 1b2c9a52..11adf1bd 100644 --- a/craft-freeform/headless/nextjs.mdx +++ b/craft-freeform/headless/nextjs.mdx @@ -9,7 +9,7 @@ import { VerticalStepWrapper, StepMarkdown } from '@site/src/components/docs'; # Next.js -Use the official `@solspace/freeform-react` packages (`0.1.0`). Complete [Getting Started](./getting-started.mdx) (enable headless + install packages) first. +Use the official `@solspace/freeform-react` packages. Complete [Getting Started](./getting-started.mdx) (enable headless + install packages) first. Freeform’s React packages are client-side. In the App Router, render them from a **Client Component** and proxy `/freeform` so CSRF cookies stay on your Next.js origin. diff --git a/craft-freeform/headless/reactjs.mdx b/craft-freeform/headless/reactjs.mdx index 68919a64..d433e037 100644 --- a/craft-freeform/headless/reactjs.mdx +++ b/craft-freeform/headless/reactjs.mdx @@ -8,7 +8,7 @@ import { Badge, BadgeGroup } from '@site/src/components/utils'; # React JS -Use the official `@solspace/freeform-react` packages (`0.1.0`). See [Getting Started](./getting-started.mdx) for enabling the headless API. +Use the official `@solspace/freeform-react` packages. See [Getting Started](./getting-started.mdx) for enabling the headless API. ## Install @@ -56,7 +56,8 @@ export function ContactForm() { | --- | --- | | `handle` | Form handle (must be allowed in `headless.forms`) | | `baseUrl` | Craft origin. Use `""` or your SPA origin when `/freeform` is proxied. | -| `extensions` | Captcha / datetime / file-dnd extensions | +| `extensions` | Captcha / datetime / file-dnd / calculation / table / signature | +| `draftToken` / `draftKey` | Resume a saved draft (from a prior `saveDraft` response) | | `theme` | Optional theme object (`lightTheme`, `darkTheme`, or `createTheme()`) | | `allowRawHtml` | Default `false`. Set `true` only if HTML/rich-text fields are trusted CMS content. | | `loadingFallback` / `errorFallback` | Custom loading and error UI | @@ -133,29 +134,114 @@ Useful helpers on the hook result: | `values` / `setValue` | Read / write field values | | `fieldErrors` / `formErrors` | Validation messages | | `isFieldVisible(handle)` | Conditional visibility | -| `handleSubmit` / `goNext` / `goBack` | Submit and multi-page | +| `handleSubmit` / `goNext` / `goBack` / `saveDraft` | Submit, multi-page, and save progress | + +## Save & Continue Later + +Enable **Save** on the form’s Button Layout in Freeform. React shows the Save button automatically. + +After Save, Freeform returns a `token` and `key`. Put those in your page URL so the visitor can come back later (email the link, bookmark it, or copy it): + +```tsx title="ContactFormWithSave.tsx" showLineNumbers +import { Freeform } from '@solspace/freeform-react'; +import { recommendedExtensions } from '@solspace/freeform-extensions'; + +function readDraft() { + const params = new URLSearchParams(window.location.search); + return { + draftToken: params.get('session-token'), + draftKey: params.get('key'), + }; +} + +function writeDraft(token: string, key: string) { + const url = new URL(window.location.href); + url.searchParams.set('session-token', token); + url.searchParams.set('key', key); + window.history.replaceState({}, '', url); +} + +export function ContactFormWithSave() { + const { draftToken, draftKey } = readDraft(); + + return ( + { + if ( + response.status === 'draft_saved' && + response.draft?.token && + response.draft?.key + ) { + writeDraft(response.draft.token, response.draft.key); + // Optional: show “Progress saved — bookmark this page” + } + }} + /> + ); +} +``` + +**Customer flow** + +1. Enable Save in Freeform → set Save label (Redirect URL optional). +2. Visitor clicks **Save** → your app stores `token` + `key` in the URL (as above). +3. Visitor returns via that URL → pass `draftToken` / `draftKey` → fields restore. +4. Visitor clicks **Submit** → real submission; draft is removed. + +Optional: set the form’s Save **Redirect URL** to +`https://your-app.com/contact?session-token={token}&key={key}` +so the API also returns `draft.resumeUrl` for emails or custom UI. ## Captchas and advanced fields -Pass `recommendedExtensions` (or a subset) so Freeform can mount captchas, Flatpickr datetime fields, and File Drag & Drop: +Pass `recommendedExtensions` (or a subset) so Freeform can mount captchas and advanced fields: ```tsx import { captchaExtensions, datetimeExtension, fileDndExtension, + calculationExtension, + tableExtension, + signatureExtension, recommendedExtensions, } from '@solspace/freeform-extensions'; -// All of the above: +// Recommended preset (captchas + datetime + file DnD + calculation + table + signature): // Or pick what you need: - + ``` +| Extension | Covers | +| --- | --- | +| Captchas | Turnstile, reCAPTCHA, hCaptcha, Friendly Captcha | +| `datetimeExtension` | Flatpickr / native datetime fields | +| `fileDndExtension` | File Drag & Drop uploads | +| `calculationExtension` | Live calculation fields | +| `tableExtension` | Table rows (min/max/exact limits, required columns, file cells) | +| `signatureExtension` | Signature pad (draw, clear, required validation) | + Configure captcha integrations in the Freeform control panel. Site keys are exposed on the form manifest; tokens are submitted automatically through `meta.captchas`. +For **table** fields: enable the field in Freeform as usual. Row limits and required columns come from the form builder. File columns upload through the same headless multipart path as standalone file fields. + +For **signature** fields: visitors draw on the canvas; the value is stored as a PNG data URL. Clear resets the pad. + ## Custom field renderers Override rendering by handle, frontend renderer key, or field type: diff --git a/craft-freeform/headless/rest-api.mdx b/craft-freeform/headless/rest-api.mdx index f54cbf69..f76554db 100644 --- a/craft-freeform/headless/rest-api.mdx +++ b/craft-freeform/headless/rest-api.mdx @@ -8,7 +8,7 @@ import { Badge, BadgeGroup } from '@site/src/components/utils'; # REST API -The headless REST API ships with the Freeform plugin. Official npm clients are on an independent **`0.1.0`** line ([npm org](https://www.npmjs.com/org/solspace)). +The headless REST API ships with the Freeform plugin. Official npm clients are published under the [Solspace npm org](https://www.npmjs.com/org/solspace). Most customers should use [`@solspace/freeform-react`](./reactjs.mdx) and never call these endpoints by hand. This page is the contract reference when you build a custom client or debug requests. @@ -92,9 +92,23 @@ JSON body shape (simplified): | `submit` | Final submit (or single-page forms) | | `next` / `back` | Multi-page navigation | | `validate` | Validate without completing | -| `saveDraft` | Reserved — drafts are not available yet | +| `saveDraft` | Save progress (token + key returned in `draft`) | -**Multipart** submits use a `_freeform` JSON field for the payload plus file inputs, matching what `@solspace/freeform-core` sends automatically. +On `draft_saved`, the response includes: + +```json +{ + "status": "draft_saved", + "draft": { "token": "…", "key": "…", "resumeUrl": null }, + "state": { "values": { "…": "…" }, "pageIndex": 0 } +} +``` + +Pass `context.draftToken` and `context.draftKey` on later submits to update or resume the same draft. + +In React, enable Save in the form builder, then follow the simple URL recipe in [React JS → Save & Continue Later](./reactjs.mdx#save--continue-later) (`draftToken` / `draftKey` props + `session-token` / `key` query params). + +**Multipart** submits use a `_freeform` JSON field for the payload plus file inputs, matching what `@solspace/freeform-core` sends automatically. Standalone file fields and **table file cells** both use this path (table cells use nested keys under the table handle). ### CSRF token @@ -157,7 +171,7 @@ Manifests include: } ``` -`pluginVersion` matches Freeform. `minimumClientVersion` matches the npm client line (`0.1.0+`). +`pluginVersion` matches Freeform. `minimumClientVersion` is the oldest npm client line the plugin expects to work with. ## Next steps From ac3d5a02d5b72f56da6a7c1f6d0087752c820538 Mon Sep 17 00:00:00 2001 From: thejahid Date: Mon, 10 Aug 2026 12:56:42 +0600 Subject: [PATCH 6/6] Enhance Freeform headless documentation by updating GraphQL integration details, clarifying the use of headless adapters, and improving descriptions of legacy form queries. Revise example app references and emphasize the recommended approach for new React/Next.js projects. --- craft-freeform/headless/getting-started.mdx | 9 ++- craft-freeform/headless/graphql.mdx | 75 ++++++++++++++++++++- craft-freeform/headless/index.mdx | 4 +- craft-freeform/headless/reactjs.mdx | 10 +-- craft-freeform/headless/rest-api.mdx | 1 + 5 files changed, 85 insertions(+), 14 deletions(-) diff --git a/craft-freeform/headless/getting-started.mdx b/craft-freeform/headless/getting-started.mdx index cec77a84..28a1d406 100644 --- a/craft-freeform/headless/getting-started.mdx +++ b/craft-freeform/headless/getting-started.mdx @@ -19,7 +19,7 @@ Freeform’s recommended headless path for React and Next.js is: GraphQL and older AJAX demos remain available, but new React/Next.js projects should start here. :::tip Example app -Clone the [Freeform Headless React Demo](https://github.com/solspace/freeform-headless-react-demo) to try the packages against your Craft site (Save & Continue, table, signature, calculation, and more). +Clone the [Freeform Headless React Demo](https://github.com/solspace/freeform-headless-react-demo) to try the packages against your Craft site (REST, GraphQL tab, Save & Continue, table, signature, calculation, and more). ::: ## Requirements @@ -137,8 +137,8 @@ export function ContactForm() { | [React JS](./reactjs.mdx) | Vite, CRA, Remix, or any React SPA | | [Next.js](./nextjs.mdx) | App Router / Pages Router + proxy | | [REST API](./rest-api.mdx) | Endpoints, CSRF, CORS, profiles | -| [GraphQL](./graphql.mdx) | Existing GraphQL integrations (alternate path) | -| [Example demo](https://github.com/solspace/freeform-headless-react-demo) | Cloneable Vite app using the published packages | +| [GraphQL](./graphql.mdx) | Headless adapters (`freeformHeadlessManifest` / `freeformHeadlessSubmit`) or legacy form GraphQL | +| [Example demo](https://github.com/solspace/freeform-headless-react-demo) | Cloneable Vite app (REST + GraphQL tab) | ## What’s included @@ -151,14 +151,13 @@ export function ContactForm() { - Table fields (row limits, required columns, file cells) - Signature fields (canvas pad + clear) - Default theme with light / dark / system color schemes +- Headless GraphQL adapters (`freeformHeadlessManifest` / `freeformHeadlessSubmit`) ## Coming later - Payment fields (Stripe, etc.) - Official Vue adapter - Bootstrap and Tailwind theme packages -- Full GraphQL parity with the REST contract - ## Security checklist 1. Keep headless **disabled** until you intentionally enable forms. diff --git a/craft-freeform/headless/graphql.mdx b/craft-freeform/headless/graphql.mdx index 0e0198d6..5a5964db 100644 --- a/craft-freeform/headless/graphql.mdx +++ b/craft-freeform/headless/graphql.mdx @@ -1,7 +1,7 @@ --- title: GraphQL sidebar_position: 6 -description: Integrate Freeform 5.x with GraphQL in Craft CMS for headless form handling and submissions. +description: Freeform headless GraphQL adapters plus legacy form queries and submission mutations for Craft CMS. --- import Tabs from '@theme/Tabs'; @@ -12,17 +12,86 @@ import { VerticalStepWrapper, StepMarkdown } from '@site/src/components/docs'; # GraphQL -Freeform supports querying form layouts and form submission mutations via GraphQL. This guide assumes you have some GraphQL experience. To learn more about GraphQL and Craft, please check out the [Fetch content with GraphQL](https://craftcms.com/docs/getting-started-tutorial/build/graphql.html) guide and [Craft's GraphQL API](https://craftcms.com/docs/5.x/development/graphql.html). +Freeform supports GraphQL in two ways: + +1. **Headless adapters** (recommended when you want GraphQL) — `freeformHeadlessManifest` and `freeformHeadlessSubmit`, matching the [REST API](./rest-api.mdx) contract +2. **Legacy form queries / `save_{handle}_Submission` mutations** — still supported for existing integrations (documented below) + +This guide assumes some GraphQL experience. See Craft’s [Fetch content with GraphQL](https://craftcms.com/docs/getting-started-tutorial/build/graphql.html) and [GraphQL API](https://craftcms.com/docs/5.x/development/graphql.html). :::tip New React / Next.js projects -For new React and Next.js apps, prefer the official packages and [REST API](./rest-api.mdx) — start with [Getting Started](./getting-started.mdx). GraphQL remains fully supported for existing headless integrations. +Prefer the official packages with the [REST API](./rest-api.mdx) for `` / `useFreeform()` — start with [Getting Started](./getting-started.mdx). Use the headless GraphQL adapters when your app already speaks Craft GraphQL and you want the same manifest/submit payload shape. ::: +## Headless GraphQL adapters + +These adapters reuse Freeform’s headless `ManifestService` and `HeadlessSubmitService`. Enable headless for the form first (same `config/freeform.php` as REST). + +### Requirements + +| Requirement | Notes | +| --- | --- | +| Headless config | `headless.enabled` + per-form `exposeManifest` / `allowSubmit` | +| Craft GraphQL schema | Freeform **form read** + **submission create** for that form | +| Site access | Enable your Craft **site** on the schema (missing this returns *Schema doesn’t have access to the “Site” site*) | +| Schema token | Pass as `Authorization: Bearer ` | + +Typical endpoint: `POST /actions/graphql/api` (or your Craft GraphQL URL). + +### Manifest query + +Returns the same manifest object as REST `GET /freeform/api/forms/{handle}/manifest` (the `data` payload). + +```graphql showLineNumbers +query { + freeformHeadlessManifest(handle: "contact") +} +``` + +### Submit mutation + +Returns the same structured submit response as REST (`success`, `status`, `errors`, `draft`, etc.). + +```graphql showLineNumbers +mutation { + freeformHeadlessSubmit( + handle: "contact" + intent: "submit" + values: { email: "jane@example.com", message: "Hello" } + meta: {} + context: {} + ) +} +``` + +| Argument | Description | +| --- | --- | +| `handle` | Form handle (required) | +| `intent` | `submit`, `next`, `back`, `validate`, or `saveDraft` (default `submit`) | +| `values` | Field values by handle (`FreeformJson`) | +| `meta` | Honeypot, captcha, javascriptTest, etc. | +| `context` | Draft tokens and other submit context | +| `csrfToken` | Optional; when omitted, cookie CSRF is skipped (schema token is the gate) | + +### File uploads + +Multipart / File Drag & Drop uploads remain on the **REST** endpoints. Use GraphQL for JSON values; upload files via REST (or the official React packages on REST). + +### Try it + +The [Freeform Headless React Demo](https://github.com/solspace/freeform-headless-react-demo) includes a **GraphQL** tab. Set `VITE_GRAPHQL_TOKEN` (and optional `VITE_GRAPHQL_PATH`) in `.env`. + +--- + +## Legacy GraphQL (form queries and submission mutations) + +The sections below document Freeform’s original GraphQL form layout queries and per-form `save_{handle}_Submission` mutations. + ## Demos Have a look at our headless demos to get a feel for what's possible with GraphQL: diff --git a/craft-freeform/headless/index.mdx b/craft-freeform/headless/index.mdx index dafc74af..ff9377a5 100644 --- a/craft-freeform/headless/index.mdx +++ b/craft-freeform/headless/index.mdx @@ -6,7 +6,7 @@ import Icons from '@site/static/icons/cards'; Freeform supports headless website architecture for JavaScript front ends such as React, Next.js, and Vue.js. -**Recommended for new React / Next.js projects:** the official npm packages and the headless REST API. GraphQL remains available for existing integrations. +**Recommended for new React / Next.js projects:** the official npm packages and the headless REST API. Prefer [headless GraphQL adapters](./graphql#headless-graphql-adapters) when your app already uses Craft GraphQL. Start with [Getting Started](./getting-started) to enable headless and install `@solspace/freeform-react`, or try the [example React demo](https://github.com/solspace/freeform-headless-react-demo). @@ -52,7 +52,7 @@ Start with [Getting Started](./getting-started) to enable headless and install ` { title: 'GraphQL', description: - 'Query form layouts and create submissions with GraphQL mutations.', + 'Headless manifest/submit adapters, plus legacy form queries and mutations.', icon: Icons.GraphqlIcon, fullCardLink: 'graphql', }, diff --git a/craft-freeform/headless/reactjs.mdx b/craft-freeform/headless/reactjs.mdx index d433e037..70a9e9a4 100644 --- a/craft-freeform/headless/reactjs.mdx +++ b/craft-freeform/headless/reactjs.mdx @@ -292,7 +292,11 @@ For Next.js, see the [Next.js](./nextjs.mdx) guide. ## Example demo -- [Freeform Headless React Demo](https://github.com/solspace/freeform-headless-react-demo) — Vite app using the official npm packages +- [Freeform Headless React Demo](https://github.com/solspace/freeform-headless-react-demo) — Vite app using the official npm packages (REST tabs + **GraphQL** tab) + +## GraphQL + +Prefer the [headless GraphQL adapters](./graphql.mdx#headless-graphql-adapters) when you want Craft GraphQL with the same manifest/submit contract as REST. Legacy form queries and `save_{handle}_Submission` mutations are documented on the same page. ## Legacy GraphQL / AJAX demos @@ -303,6 +307,4 @@ Please note that the paths in the demos are specific for the Solspace demo site ::: - [React + GraphQL demo](https://github.com/solspace/craft-freeform-demo-reactjs-graphql) -- [React + AJAX demo](https://github.com/solspace/craft-freeform-demo-reactjs-ajax) - -For GraphQL field queries and mutations, see [GraphQL](./graphql.mdx). +- [React + AJAX demo](https://github.com/solspace/craft-freeform-demo-reactjs-ajax) \ No newline at end of file diff --git a/craft-freeform/headless/rest-api.mdx b/craft-freeform/headless/rest-api.mdx index f76554db..a5fec589 100644 --- a/craft-freeform/headless/rest-api.mdx +++ b/craft-freeform/headless/rest-api.mdx @@ -178,3 +178,4 @@ Manifests include: - [Getting Started](./getting-started.mdx) — install packages - [React JS](./reactjs.mdx) — `` and `useFreeform()` - [Next.js](./nextjs.mdx) — App Router + proxy +- [GraphQL](./graphql.mdx#headless-graphql-adapters) — headless manifest/submit via Craft GraphQL