From 0580ae0cb86deaad8f4288a5cd78a1b5b57165d2 Mon Sep 17 00:00:00 2001 From: thejahid Date: Sun, 19 Jul 2026 22:52:40 +0600 Subject: [PATCH 1/4] 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/4] 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/4] 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/4] 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