{"id":51916119,"url":"https://github.com/solspace/freeform-headless-react-demo","last_synced_at":"2026-07-27T11:01:01.865Z","repository":{"id":372480244,"uuid":"1307669344","full_name":"solspace/freeform-headless-react-demo","owner":"solspace","description":"Public example app: [Vite + React] rendering Craft Freeform forms with Solspace’s official packages from the npm registry.","archived":false,"fork":false,"pushed_at":"2026-07-21T12:48:06.000Z","size":23,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-21T14:16:24.143Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/solspace.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-21T12:19:02.000Z","updated_at":"2026-07-21T12:51:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/solspace/freeform-headless-react-demo","commit_stats":null,"previous_names":["solspace/freeform-headless-react-demo"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/solspace/freeform-headless-react-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solspace%2Ffreeform-headless-react-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solspace%2Ffreeform-headless-react-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solspace%2Ffreeform-headless-react-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solspace%2Ffreeform-headless-react-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/solspace","download_url":"https://codeload.github.com/solspace/freeform-headless-react-demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solspace%2Ffreeform-headless-react-demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35949059,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-27T02:00:06.776Z","response_time":101,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-27T11:01:00.917Z","updated_at":"2026-07-27T11:01:01.831Z","avatar_url":"https://github.com/solspace.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Freeform Headless React Demo\n\nExample **Vite + React** app that renders [Solspace Freeform](https://docs.solspace.com/craft/freeform/) forms using the official npm packages:\n\n| Package | Role |\n| --- | --- |\n| [`@solspace/freeform-core`](https://www.npmjs.com/package/@solspace/freeform-core) | Manifest, state, submit |\n| [`@solspace/freeform-react`](https://www.npmjs.com/package/@solspace/freeform-react) | `\u003cFreeform /\u003e` and `useFreeform()` |\n| [`@solspace/freeform-extensions`](https://www.npmjs.com/package/@solspace/freeform-extensions) | Captchas, datetime, file drag \u0026 drop |\n| [`@solspace/freeform-react-theme-default`](https://www.npmjs.com/package/@solspace/freeform-react-theme-default) | Default light / dark theme |\n\n## What you need\n\nBefore running this app:\n\n1. A **Craft CMS** site with **Freeform** installed (version that includes the headless REST API)\n2. A Freeform form you want to display (you’ll use its **handle**, e.g. `contact`)\n3. **Node.js 20+**\n\n## 1. Enable headless Freeform (on your Craft site)\n\nThis step is done in your **Craft CMS project**, not in this React demo repo.\n\nHeadless must be turned on in Freeform **before** this app can load a form.\n\n1. Open your Craft site project (the CMS install — e.g. a DDEV project, not this Vite app).\n2. Edit (or create) the Freeform config file at:\n\n   ```text\n   your-craft-project/config/freeform.php\n   ```\n\n   Typical locations:\n\n   | Setup | Path |\n   | --- | --- |\n   | Standard Craft | `config/freeform.php` at the Craft project root |\n   | DDEV / local | same — e.g. `~/Sites/my-site/config/freeform.php` |\n\n3. Merge a `headless` section into that file (keep any other Freeform settings you already have). See the [Freeform Headless docs](https://docs.solspace.com/craft/freeform/v5/headless/getting-started/) for the full options:\n\n```php\n\u003c?php\n// your-craft-project/config/freeform.php\n\nreturn [\n    'headless' =\u003e [\n        'enabled' =\u003e true,\n        'forms' =\u003e [\n            'contact' =\u003e [          // ← your Freeform form handle\n                'exposeManifest' =\u003e true,\n                'allowSubmit' =\u003e true,\n            ],\n        ],\n    ],\n];\n```\n\nTips:\n\n- Replace `contact` with the form **handle** from the Freeform control panel (Forms → your form).\n- For public forms, enable a **captcha** in Freeform.\n- Keep Craft running (e.g. DDEV at `https://site.ddev.site`) — you will point `CRAFT_PROXY_TARGET` at that URL in step 2.\n\n## 2. Clone and configure this app\n\n```bash\ngit clone https://github.com/solspace/freeform-headless-react-demo.git\ncd freeform-headless-react-demo\n\ncp .env.example .env\n```\n\nEdit `.env`:\n\n```bash\n# Craft site URL (Vite proxies /freeform here)\nCRAFT_PROXY_TARGET=https://your-site.example\n\n# Form handle from Freeform (same as in step 1)\nVITE_FREEFORM_HANDLE=contact\n```\n\n| Variable | Purpose |\n| --- | --- |\n| `CRAFT_PROXY_TARGET` | Your Craft / Freeform site URL |\n| `VITE_FREEFORM_HANDLE` | Default form handle shown when the app starts |\n\n## 3. Install and run\n\n```bash\nnpm install\nnpm run dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000).\n\nHow it connects: the React app calls `/freeform/...` on **localhost**. Vite proxies those requests to `CRAFT_PROXY_TARGET`, so CSRF cookies work on the same origin.\n\nYou can also use `pnpm` or `yarn` if you prefer.\n\n## How to use a form in this app\n\n### Load your form\n\n1. Make sure the form is headless-enabled (step 1).\n2. In the app **Form settings**, enter the form handle → **Load form**.  \n   Or set `VITE_FREEFORM_HANDLE` in `.env` and restart `npm run dev`.\n\n### Try the demo modes\n\n| Tab | What it shows |\n| --- | --- |\n| `\u003cFreeform /\u003e` | Full form with the default theme (easiest) |\n| `useFreeform()` | Headless hook — you own the markup |\n| Manifest JSON | Raw API response (useful for debugging) |\n\n### Use the same pattern in your own project\n\n```tsx\nimport { Freeform } from \"@solspace/freeform-react\";\nimport { recommendedExtensions } from \"@solspace/freeform-extensions\";\nimport \"@solspace/freeform-react-theme-default/styles.css\";\n\nexport function ContactForm() {\n  return (\n    \u003cFreeform\n      handle=\"contact\"\n      baseUrl={window.location.origin}\n      extensions={recommendedExtensions}\n    /\u003e\n  );\n}\n```\n\nWhen `/freeform` is proxied (or served) on the same host as your frontend, keep `baseUrl` as your app’s origin.\n\n## Scripts\n\n| Command | Description |\n| --- | --- |\n| `npm run dev` | Dev server (port `3000` by default) |\n| `npm run build` | Production build → `dist/` |\n| `npm run preview` | Preview the production build |\n\nCustom port: `PORT=3001 npm run dev`\n\n## Next.js\n\nThe same packages work in Next.js. Use a Client Component and rewrite `/freeform` to your Craft site (same idea as this Vite proxy). See Solspace Freeform → **Headless** docs.\n\n## Docs\n\n- [Solspace Freeform documentation](https://docs.solspace.com/craft/freeform/) → Headless\n- Packages on [npm](https://www.npmjs.com/org/solspace)\n\n## Troubleshooting\n\n| Issue | Fix |\n| --- | --- |\n| Form won’t load / 404 | Wrong handle, or headless not enabled for that form (step 1). |\n| CSRF / session errors | Keep using the Vite proxy; don’t call Craft from another origin without CORS + credentials. |\n| CORS errors | Prefer the proxy, or add `http://localhost:3000` to `headless.allowedOrigins`. |\n| Captcha / file upload missing | Enable those integrations in Freeform; this demo already loads `recommendedExtensions`. |\n\n## License\n\nThis demo is MIT. The Freeform Craft plugin is licensed separately — see [Solspace Freeform](https://docs.solspace.com/craft/freeform/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolspace%2Ffreeform-headless-react-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsolspace%2Ffreeform-headless-react-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolspace%2Ffreeform-headless-react-demo/lists"}