diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/.wp-env.json b/examples/nuxt/nuxt-headlesswp-gravity-forms/.wp-env.json new file mode 100644 index 00000000..810c6ed4 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/.wp-env.json @@ -0,0 +1,23 @@ +{ + "phpVersion": "7.4", + "plugins": [ + "https://github.com/wp-graphql/wp-graphql/releases/latest/download/wp-graphql.zip", + "https://github.com/AxeWP/wp-graphql-gravity-forms/releases/latest/download/wp-graphql-gravity-forms.zip" + ], + "config": { + "WP_DEBUG": true, + "SCRIPT_DEBUG": false, + "GRAPHQL_DEBUG": true, + "WP_DEBUG_LOG": true, + "WP_DEBUG_DISPLAY": false, + "SAVEQUERIES": false + }, + "mappings": { + "db": "./wp-env/db", + "wp-content/uploads": "./wp-env/uploads", + ".htaccess": "./wp-env/setup/.htaccess" + }, + "lifecycleScripts": { + "afterStart": "wp-env run cli -- wp rewrite structure '/%postname%/' && wp-env run cli -- wp rewrite flush" + } +} diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/README.md b/examples/nuxt/nuxt-headlesswp-gravity-forms/README.md new file mode 100644 index 00000000..0da632a8 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/README.md @@ -0,0 +1,111 @@ +# Example: Gravity Forms in Headless WordPress with Nuxt/Vue + +This example shows you how to wire up a full headless WordPress backend—complete with Gravity Forms, WPGraphQL, and a pre-built "Questionnaire" form—alongside a Nuxt 3 front end that dynamically renders your forms using the GraphQL interfaces feature of WPGraphQL for Gravity Forms. + +## Features + +- **Headless WordPress with Gravity Forms** + + - Stand up WP + WPGraphQL + Gravity Forms (and your Questionnaire JSON) in one command. + +- **Dynamic form rendering** + + - Use GraphQL interfaces (`GfFieldWithLabelSetting`, `GfFieldWithChoicesSetting`, etc.) plus a single `useFormFields` composable to automatically map any new field type to the correct Vue component. + +- **Composable Nuxt 3 front end** + + - Fetch your form schema with `useGravityForm` and render all fields via a dynamic `` pattern. + +- **Out-of-the-box data** + - Includes a SQL dump of WP + Gravity Forms data and a zipped uploads folder so you can dive right in. + +## Project Structure + +``` + +``` + +example-app/ +├── components/ # Vue form-field components & barrel file +├── composables/ # useGravityForm.js & useFormFields.js +├── pages/ # Nuxt page (index.vue) that renders the form +└── nuxt.config.ts # Nuxt application config +wp-env/ +│ ├── db/ +│ │ └── database.sql # WordPress + Gravity Forms schema & data +│ ├── setup/ +│ │ └── .htaccess # CORS + pretty-permalinks for wp-env +│ └── uploads.zip # wp-content/uploads media files +├── .wp-env.json # @wordpress/env configuration +├── package.json # wp-env + Nuxt dev scripts + +```` + +## Running the Example with wp-env + +### Prerequisites + +- Node.js (v18+ recommended) +- npm +- Docker (so that @wordpress/env can spin up the WP container) + +### Setup Repository and Install + +```bash +git clone https://github.com/your-org/nuxt-gravityforms-example.git +cd nuxt-gravityforms-example +npm install + +echo "NUXT_PUBLIC_WORDPRESS_URL=http://localhost:8888" > example-app/.env +```` + +### Quick Start + +1. Unzip uploads, start WP, import DB, then launch Nuxt: + + ```bash + npm run example:build + ``` + +2. Or run steps separately: + + ```bash + # Start WP + npm run wp:start + + # Import DB + npm run wp:db:import + + # Unzip uploads + npm run wp:images:unzip + + # Start Nuxt dev server + npm run dev + ``` + +By the end, you will have: + +- WordPress Admin: http://localhost:8888/wp-admin/ + - user: admin / pass: password +- Nuxt Front End: http://localhost:3000/ + +## Scripts + +| Command | Description | +| ------------------------- | ---------------------------------------------------------------- | +| `npm run example:build` | Unzip media → start WP env → import DB → launch Nuxt dev server | +| `npm run example:start` | Start WP env, then Nuxt dev server | +| `npm run example:stop` | Stop the WordPress environment (wp-env stop) | +| `npm run example:prune` | Destroy & rebuild the WP environment, then restart—all in one go | +| `npm run wp:start` | @wordpress/env start (launches PHP/MySQL container with WP) | +| `npm run wp:stop` | @wordpress/env stop | +| `npm run wp:db:import` | Import the SQL dump into the running WP container | +| `npm run wp:db:export` | Export the current WP database back to wp-env/db/database.sql | +| `npm run wp:images:unzip` | Clear & unzip wp-env/uploads.zip → populates wp-content/uploads | +| `npm run dev` | Start the Nuxt 3 development server on port 3000 | + +> **Tip:** You can also run any arbitrary WP-CLI command inside the container via `npm run wp:cli -- ` + +## Database Access + +If you need direct database access (phpMyAdmin), add a `"phpmyadminPort": 11111` entry to your `.wp-env.json` and then navigate to http://localhost:11111. diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/.gitignore b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/.gitignore new file mode 100644 index 00000000..4a7f73a2 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/.gitignore @@ -0,0 +1,24 @@ +# Nuxt dev/build outputs +.output +.data +.nuxt +.nitro +.cache +dist + +# Node dependencies +node_modules + +# Logs +logs +*.log + +# Misc +.DS_Store +.fleet +.idea + +# Local env files +.env +.env.* +!.env.example diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/README.md b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/README.md new file mode 100644 index 00000000..0287a36c --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/README.md @@ -0,0 +1,73 @@ +# Nuxt 3 Headless WordPress with Gravity Forms + +This project demonstrates how to integrate Nuxt 3 with WordPress as a headless CMS, specifically focusing on Gravity Forms integration using WPGraphQL and WPGraphQL for Gravity Forms. + +## Project Overview + +This project includes several demo routes: + +- `/headlesswp-gform`: Main demo showcasing Gravity Forms integration with WPGraphQL +- `/products`: Test route using a dummy REST API (for API integration testing) +- `/wpblog`: Test route demonstrating native WordPress post data fetching + +## Prerequisites + +- WordPress installation with: + - WPGraphQL plugin + - WPGraphQL for Gravity Forms plugin + - Gravity Forms plugin +- Nuxt 3 + +## Setup + +Make sure to install dependencies: + +```bash +# npm +npm install + + +``` + +## Development Server + +Start the development server on `http://localhost:3000`: + +```bash +# npm +npm run dev + + +``` + +## Environment Variables + +Create a `.env` file with: + +```bash +WORDPRESS_URL= +``` + +## Production + +Build the application for production: + +```bash +# npm +npm run build + + +``` + +Locally preview production build: + +```bash +# npm +npm run preview + + + + +``` + +Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information. diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/assets/css/tailwind.css b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/assets/css/tailwind.css new file mode 100644 index 00000000..1565f44b --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/assets/css/tailwind.css @@ -0,0 +1,16 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +body { + @apply bg-gray-50; +} + +@layer components { + .btn { + @apply bg-[#12b488] text-white px-3 py-2 rounded-md text-sm text-white inline-block; + } + .card { + @apply p-3 rounded-md bg-white shadow-md h-full; + } +} diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/AddressField.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/AddressField.vue new file mode 100644 index 00000000..db2037df --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/AddressField.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/ChoiceListField.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/ChoiceListField.vue new file mode 100644 index 00000000..22bbaf54 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/ChoiceListField.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/DateField.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/DateField.vue new file mode 100644 index 00000000..cbe735a4 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/DateField.vue @@ -0,0 +1,39 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/DropdownField.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/DropdownField.vue new file mode 100644 index 00000000..3a5e62ca --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/DropdownField.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/EmailField.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/EmailField.vue new file mode 100644 index 00000000..fbf19880 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/EmailField.vue @@ -0,0 +1,54 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/InputField.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/InputField.vue new file mode 100644 index 00000000..98be9337 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/InputField.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/NameField.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/NameField.vue new file mode 100644 index 00000000..673d0691 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/NameField.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/PhoneField.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/PhoneField.vue new file mode 100644 index 00000000..8d332acf --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/PhoneField.vue @@ -0,0 +1,37 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/TimeField.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/TimeField.vue new file mode 100644 index 00000000..8852241e --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/TimeField.vue @@ -0,0 +1,38 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/index.js b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/index.js new file mode 100644 index 00000000..f4493c93 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/form-fields/index.js @@ -0,0 +1,9 @@ +export { default as InputField } from "./InputField.vue"; +export { default as EmailField } from "./EmailField.vue"; +export { default as DropdownField } from "./DropdownField.vue"; +export { default as ChoiceListField } from "./ChoiceListField.vue"; +export { default as AddressField } from "./AddressField.vue"; +export { default as DateField } from "./DateField.vue"; +export { default as TimeField } from "./TimeField.vue"; +export { default as NameField } from "./NameField.vue"; +export { default as PhoneField } from "./PhoneField.vue"; diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/product/ProductCard.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/product/ProductCard.vue new file mode 100644 index 00000000..8763e670 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/product/ProductCard.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/product/ProductDetails.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/product/ProductDetails.vue new file mode 100644 index 00000000..1d4139ed --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/product/ProductDetails.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/wp/Post.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/wp/Post.vue new file mode 100644 index 00000000..d51f4f58 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/wp/Post.vue @@ -0,0 +1,18 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/wp/TheHeader.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/wp/TheHeader.vue new file mode 100644 index 00000000..88829ff6 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/components/wp/TheHeader.vue @@ -0,0 +1,5 @@ + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/composables/useFormFields.js b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/composables/useFormFields.js new file mode 100644 index 00000000..a8ab0dd5 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/composables/useFormFields.js @@ -0,0 +1,52 @@ +import { defineAsyncComponent } from "vue"; + +export const useFormFields = () => { + const loggedTypes = new Set(); + + /** + * Resolves the Vue component for a given field based on its inputType. + * If inputType is not present, falls back to using type. + * + * @param {Object} field - The Gravity Form field object. + * @returns {Component|null} The async Vue component for this field. + */ + const resolveFieldComponent = (field) => { + const fieldType = field.inputType + ? field.inputType.toUpperCase() + : field.type.toUpperCase(); + + const typeToComponent = { + ADDRESS: "AddressField", + TEXT: "InputField", + TEXTAREA: "InputField", + EMAIL: "EmailField", + NAME: "NameField", + PHONE: "PhoneField", + SELECT: "DropdownField", + MULTISELECT: "DropdownField", + CHECKBOX: "ChoiceListField", + RADIO: "ChoiceListField", + DATE: "DateField", + TIME: "TimeField", + WEBSITE: "InputField", + // Add any additional mappings if needed. + }; + + // Log the field type for debugging on the first occurrence. + if (!loggedTypes.has(fieldType)) { + console.log("Mapping field type:", fieldType); + loggedTypes.add(fieldType); + } + + const componentName = typeToComponent[fieldType]; + return componentName + ? defineAsyncComponent(() => + import(`~/components/form-fields/${componentName}.vue`) + ) + : null; + }; + + return { + resolveFieldComponent, + }; +}; diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/composables/useGravityForm.js b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/composables/useGravityForm.js new file mode 100644 index 00000000..35c27e3b --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/composables/useGravityForm.js @@ -0,0 +1,236 @@ +import { ref } from "vue"; +import { useRuntimeConfig } from "#app"; + +export default function useGravityForm() { + const config = useRuntimeConfig(); + const formFields = ref([]); + + const formQuery = ` + query GetGravityForm($formId: ID!) { + gfForm(id: $formId, idType: DATABASE_ID) { + formFields(first: 300) { + nodes { + id + databaseId + inputType + type + visibility + ... on GfFieldWithLabelSetting { + label + } + ... on GfFieldWithRulesSetting { + isRequired + } + ... on GfFieldWithCssClassSetting { + cssClass + } + ... on GfFieldWithDefaultValueSetting { + defaultValue + } + ... on GfFieldWithSizeSetting { + size + } + ... on GfFieldWithPlaceholderSetting { + placeholder + } + ... on GfFieldWithMaxLengthSetting { + maxLength + } + ... on GfFieldWithInputMaskSetting { + inputMaskValue + } + ... on GfFieldWithChoicesSetting { + choices { + text + value + } + inputs { + id + label + } + } + ... on GfFieldWithConditionalLogicSetting { + conditionalLogic { + actionType + logicType + rules { + fieldId + operator + value + } + } + } + } + } + } +} + + + `; + + const fetchForm = () => { + console.log("Making GraphQL request:", { + url: config.public.wordpressUrl, + query: formQuery, + }); + + const { data, status, fetchError, execute, refresh } = useFetch( + config.public.wordpressUrl, + { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify({ + query: formQuery, + variables: { formId: "1" }, + }), + immediate: false, + transform: (res) => { + if (res.errors) { + console.error("GraphQL Errors:", res.errors); + throw new Error(res.errors[0].message); + } + const fields = res.data?.gfForm?.formFields?.nodes; + if (!Array.isArray(fields)) { + console.error("Invalid fields data:", res.data); + throw new Error("Invalid form fields data"); + } + return fields; + }, + } + ); + + return { data, status, fetchError, execute, refresh }; + }; + + const transformFieldValue = (field, value) => { + if (!field) return null; + const fieldId = parseInt(field.databaseId, 10); + switch (field.type) { + case "CHECKBOX": + if (!Array.isArray(value) || !value.length) return null; + return { + id: fieldId, + checkboxValues: value.map((val, index) => ({ + inputId: parseFloat(`${fieldId}.${index + 1}`), + value: val, + })), + }; + case "ADDRESS": + return { + id: fieldId, + addressValues: { + street: value?.street || "", + lineTwo: value?.lineTwo || "", + city: value?.city || "", + state: value?.state || "", + zip: value?.zip || "", + country: value?.country || "US", + }, + }; + case "EMAIL": + return { + id: fieldId, + emailValues: { + value: value || "", + confirmationValue: value || "", + }, + }; + case "NAME": + return { + id: fieldId, + nameValues: { + prefix: value?.prefix || "", + first: value?.first || "", + middle: value?.middle || "", + last: value?.last || "", + suffix: value?.suffix || "", + }, + }; + case "MULTISELECT": + case "POST_CATEGORY": + case "POST_CUSTOM": + case "POST_TAGS": + return { + id: fieldId, + values: Array.isArray(value) ? value : [], + }; + default: + return { + id: fieldId, + value: value?.toString() || "", + }; + } + }; + + const submitForm = async (formId, fieldValues) => { + try { + const transformedValues = Object.entries(fieldValues) + .map(([id, value]) => { + const field = formFields.value.find( + (f) => f.databaseId === parseInt(id, 10) + ); + if (!field) { + console.warn(`No field found for ID ${id}`); + return null; + } + return transformFieldValue(field, value); + }) + .filter(Boolean); + + const mutation = ` + mutation SubmitForm($formId: ID!, $fieldValues: [FormFieldValuesInput!]!) { + submitGfForm(input: { + id: $formId + fieldValues: $fieldValues + }) { + errors { + id + message + } + confirmation { + message + type + } + entry { + id + ... on GfSubmittedEntry { + databaseId + } + } + } + } + `; + + const response = await fetch(config.public.wordpressUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify({ + query: mutation, + variables: { + formId: parseInt(formId, 10), + fieldValues: transformedValues, + }, + }), + }); + + const result = await response.json(); + + if (result.errors) { + throw new Error(result.errors.map((e) => e.message).join(", ")); + } + + return result.data.submitGfForm; + } catch (error) { + console.error("Submit form error:", error); + throw error; + } + }; + + return { formFields, fetchForm, submitForm }; +} diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/layouts/default.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/layouts/default.vue new file mode 100644 index 00000000..d300a606 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/layouts/default.vue @@ -0,0 +1,25 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/layouts/products.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/layouts/products.vue new file mode 100644 index 00000000..464f24ee --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/layouts/products.vue @@ -0,0 +1,25 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/nuxt.config.ts b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/nuxt.config.ts new file mode 100644 index 00000000..e926da8f --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/nuxt.config.ts @@ -0,0 +1,19 @@ +// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + compatibilityDate: "2024-11-01", + devtools: { enabled: true }, + modules: ["@nuxtjs/tailwindcss"], + runtimeConfig: { + public: { + wordpressUrl: "", + }, + }, + routeRules: { + // Blog listing page - revalidates every 60 seconds + "/wpblog": { isr: 60 }, + // Individual blog posts - cached until next deployment + "/wpblog/**": { isr: true }, + // Pre-render the form page at build time + "/headlesswp-gform": { prerender: true }, + }, +}); diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/package.json b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/package.json new file mode 100644 index 00000000..652f48ea --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/package.json @@ -0,0 +1,25 @@ +{ + "name": "nuxt-app", + "private": true, + "type": "module", + "scripts": { + "build": "nuxt build", + "dev": "nuxt dev", + "generate": "nuxt generate", + "preview": "nuxt preview", + "postinstall": "nuxt prepare", + "start": "nuxt start" + }, + "dependencies": { + "graphql": "^16.10.0", + "nuxt": "^3.16.0", + "vue": "^3.5.13", + "vue-router": "^4.5.0" + }, + "devDependencies": { + "@nuxtjs/tailwindcss": "^6.13.2" + }, + "engines": { + "node": ">=18.19.0" + } +} diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/index.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/index.vue new file mode 100644 index 00000000..21784369 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/index.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/products/[id].vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/products/[id].vue new file mode 100644 index 00000000..20db8d97 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/products/[id].vue @@ -0,0 +1,17 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/products/index.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/products/index.vue new file mode 100644 index 00000000..b571091e --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/products/index.vue @@ -0,0 +1,20 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/questionnaire/index.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/questionnaire/index.vue new file mode 100644 index 00000000..98a510aa --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/questionnaire/index.vue @@ -0,0 +1,278 @@ + + + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/wpblog/[...uri].vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/wpblog/[...uri].vue new file mode 100644 index 00000000..16b3d4d4 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/wpblog/[...uri].vue @@ -0,0 +1,48 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/wpblog/index.vue b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/wpblog/index.vue new file mode 100644 index 00000000..bf0ee4ea --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/pages/wpblog/index.vue @@ -0,0 +1,42 @@ + + + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/public/favicon.ico b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/public/favicon.ico new file mode 100644 index 00000000..18993ad9 Binary files /dev/null and b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/public/favicon.ico differ diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/public/robots.txt b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/public/robots.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/public/robots.txt @@ -0,0 +1 @@ + diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/server/tsconfig.json b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/server/tsconfig.json new file mode 100644 index 00000000..b9ed69c1 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/server/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../.nuxt/tsconfig.server.json" +} diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/tsconfig.json b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/tsconfig.json new file mode 100644 index 00000000..a746f2a7 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/example-app/tsconfig.json @@ -0,0 +1,4 @@ +{ + // https://nuxt.com/docs/guide/concepts/typescript + "extends": "./.nuxt/tsconfig.json" +} diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/package.json b/examples/nuxt/nuxt-headlesswp-gravity-forms/package.json new file mode 100644 index 00000000..aaa73dce --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/package.json @@ -0,0 +1,18 @@ +{ + "name": "headlesswp-gravity-forms-nuxt-env", + "version": "1.0.0", + "scripts": { + "example:build": "npm run frontend:install && npm run frontend:dev && npm run wp:start && npm run wp:db:import && npm run frontend:dev", + "wp:start": "wp-env start", + "wp:stop": "wp-env stop", + "wp:destroy": "wp-env destroy --config .wp-env.json", + "wp:db:import": "wp-env run cli -- wp db import /var/www/html/db/database.sql", + "wp:db:export": "wp-env run cli -- wp db export /var/www/html/db/database.sql", + "frontend:install": "npm --prefix example-app/ install", + "frontend:dev": "npm --prefix example-app/ dev", + "start": "npm run wp:start && npm run frontend:dev" + }, + "devDependencies": { + "@wordpress/env": "^10.20.0" + } +} diff --git a/examples/nuxt/nuxt-headlesswp-gravity-forms/wp-env/setup/.htaccess b/examples/nuxt/nuxt-headlesswp-gravity-forms/wp-env/setup/.htaccess new file mode 100644 index 00000000..ad8663f5 --- /dev/null +++ b/examples/nuxt/nuxt-headlesswp-gravity-forms/wp-env/setup/.htaccess @@ -0,0 +1,21 @@ + + Header set Access-Control-Allow-Origin "*" + Header set Access-Control-Allow-Methods "GET, POST, OPTIONS" + Header set Access-Control-Allow-Headers "Authorization, Content-Type" + + +# BEGIN WordPress +# The directives (lines) between "BEGIN WordPress" and "END WordPress" are +# dynamically generated, and should only be modified via WordPress filters. +# Any changes to the directives between these markers will be overwritten. + +RewriteEngine On +RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] +RewriteBase / +RewriteRule ^index\.php$ - [L] +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule . /index.php [L] + + +# END WordPress \ No newline at end of file