HXFE — Code-First Forms

Description

HXFE — Code-First Forms is a code-first WordPress form plugin. Instead of building forms in a GUI, you define them as PHP arrays and place a shortcode anywhere.

This means your forms live in your codebase — version-controlled with Git, automatically deployed, and free from database migration issues.

Why code-first?

  • Git history for free — Every change to your form shows up in git diff
  • Deploy without fear — Forms are code, so they deploy with your theme. No more “the form disappeared on production”
  • Dynamic options — Pull select options from get_posts(), taxonomies, or any PHP source. No manual updates
  • One schema, four UIs — Add step_mode: chatbot or one_by_one to transform the same fields into a completely different interface

Four UI modes from one schema

  • Normal form — Classic input confirm complete flow (default)
  • Step form — Multi-page with progress bar (steps array)
  • One-by-one — Question-at-a-time survey style (step_mode: 'one_by_one')
  • Chatbot — Chat bubble interface with typing animation, header, and timestamps (step_mode: 'chatbot')

Key features

  • 15 field types: text, email, tel, url, textarea, select, radio, checkbox, checkbox_group, number, date, file, honeypot, reCAPTCHA, privacy
  • Conditional logic: show_if, required_if, skip_if (hide_if deprecated) — works in chatbot mode too
  • Dynamic routing: to_rules, subject_rules, complete_redirect_rules, complete_html_rules based on submitted values
  • Diagnosis mode: use complete_html_rules without to — show results without sending email
  • Download after submit: download_url shows a download button on the complete screen (document request forms)
  • Form availability window: available_from / available_until with custom before/after HTML
  • Custom validation: pattern, minlength, maxlength, error_message schema keys + hxfe_validate_field and hxfe_validate_form filter hooks
  • Field HTML injection: before_html / after_html schema keys
  • Page slug tracking: subject auto-appended with [form-id@page-slug] for per-page aggregation
  • Webhook support: send to Zapier, Make, Slack, or any HTTP endpoint
  • SMTP built-in: Gmail, SendGrid, Mailgun, or custom SMTP
  • File upload: attached to email, auto-deleted after send
  • IP restriction and password-protected forms
  • iframe embedding with per-form CORS control (allowed_origins)
  • Zero cookies: GDPR/EU cookie-compliant by design
  • Clean default styles: CSS custom properties (design tokens) for easy theme integration, responsive at 768px
  • Schema examples panel in admin: 11 copy-paste samples to get started fast
  • AI-friendly: ships with llms.txt and ai-reference.md for agentic coding tools

Minimum example

add_filter( 'hxfe_schemas', function( $schemas ) {
    $schemas['contact'] = [
        'id'      => 'contact',
        'to'      => 'admin@example.com',
        'subject' => 'Contact: {name}',
        'fields'  => [
            [ 'key' => 'name',  'type' => 'text',     'label' => 'Name',    'required' => true ],
            [ 'key' => 'email', 'type' => 'email',    'label' => 'Email',   'required' => true ],
            [ 'key' => 'body',  'type' => 'textarea', 'label' => 'Message', 'required' => true ],
            [ 'key' => 'hp',    'type' => 'honeypot' ],
        ],
    ];
    return $schemas;
} );

Shortcode: [hxfe_form id="contact"]

Chatbot example

$schemas['support'] = [
    'id'        => 'support',
    'to'        => 'admin@example.com',
    'step_mode' => 'chatbot',
    'bot_name'  => 'Support Bot',
    'bot_icon'  => '🤖',
    'greeting'  => 'Hi! How can I help you today?',
    'fields'    => [
        [ 'key' => 'name',  'type' => 'text',  'label' => 'Name',
          'bot_message' => 'What is your name?' ],
        [ 'key' => 'email', 'type' => 'email', 'label' => 'Email',
          'bot_message' => 'Thanks {name}! What is your email?' ],
        [ 'key' => 'hp', 'type' => 'honeypot' ],
    ],
];

Diagnosis chatbot (no email)

$schemas['diagnosis'] = [
    'id'        => 'diagnosis',
    // No 'to' — result shown without sending email
    'step_mode' => 'chatbot',
    'complete_html_rules' => [
        [ 'when' => ['plan', '==', 'basic'],
          'html' => '<h3>Basic plan recommended</h3><p>Hi {name}!</p>' ],
        [ 'when' => 'default',
          'html' => '<p>Thank you, {name}. We will be in touch.</p>' ],
    ],
    'fields' => [ ... ],
];

Organize schemas in separate files

// functions.php — one line
require_once get_template_directory() . '/inc/hxfe-forms.php';

Or use HXFE as a standalone plugin with glob() auto-loading.

External Services

This plugin optionally connects to Google reCAPTCHA when the recaptcha field type is enabled in a form schema.

What the service is and what it is used for:
Google reCAPTCHA is a spam-prevention service. When enabled, it loads a script from Google’s servers and verifies the user’s response server-side to determine whether the form submission is from a human or a bot.

What data is sent and when:
When a page containing an HXFE form with reCAPTCHA is loaded, the visitor’s browser loads the reCAPTCHA script from google.com. On form submission, the reCAPTCHA token generated in the visitor’s browser is sent to Google’s verification endpoint (https://www.google.com/recaptcha/api/siteverify) along with your site key. No other form field data is transmitted to Google.

reCAPTCHA is disabled by default. It is only active when a site administrator adds a recaptcha field to a form schema and configures valid API keys in the plugin settings.

Links:
* Google reCAPTCHA Terms of Service: https://policies.google.com/terms
* Google Privacy Policy: https://policies.google.com/privacy

Installation

  1. Upload the plugin folder to /wp-content/plugins/
  2. Activate in Plugins Installed Plugins
  3. Add schemas via the hxfe_schemas filter in functions.php
  4. Place [hxfe_form id="your-id"] in any page or post
  5. View all registered forms at Settings Form Engine — Forms

FAQ

Does HXFE save submissions to the database?

No. HXFE sends email only. This is intentional — forms defined in code stay lightweight and free of database dependencies. Use Webhook support to send data to external services like Google Sheets or a CRM.

Can I use HXFE without writing PHP?

HXFE is designed for developers who want code-first form management. If you need a GUI builder, plugins like WPForms or Fluent Forms may be a better fit.

Does the chatbot mode work with conditional logic?

Yes. show_if conditions work in chatbot mode — hidden fields are automatically skipped. You can also use {field_key} placeholders in bot_message to reference previous answers.

Is HXFE GDPR / EU cookie compliant?

Yes. HXFE uses zero cookies. Form state is preserved via hidden JSON fields on the server side, not browser storage.

Can I embed forms on external domains?

Yes. Use [hxfe_iframe id="contact" site="https://your-site.com"] and configure allowed origins in Settings Form Engine iframe / CORS Settings.

How do I connect to Zapier or Make?

Add a webhooks array to your schema with the target URL. HXFE will POST form data as JSON after each successful submission. Webhook failures do not block form submission.

Can I skip the confirmation screen?

Yes. Add 'confirm' => false to your schema. Works for normal forms and step forms.

Can I restrict a form to specific IP addresses?

Yes. Add allowed_ips to your schema with a list of IPs or CIDR ranges. Visitors outside the whitelist see a blocked message, which you can customize with ip_blocked_html.

allowed_ips => [ '192.168.1.0/24', '203.0.113.5' ],
ip_blocked_html => '<p>This form is only available on the campus network.</p>',

Can I require a password to access a form?

Yes. Add an auth key to your schema. To keep passwords out of Git, define them as constants in wp-config.php and reference them in the schema.

In wp-config.php: define( 'HXFE_STAFF_PASS', 'your-secret-password' );

In your schema:
‘auth’ => [ ‘users’ => [ [ ‘id’ => ‘staff’, ‘password’ => defined(‘HXFE_STAFF_PASS’) ? HXFE_STAFF_PASS : ” ] ] ]

Brute-force protection is built in — access is locked for 15 minutes after 5 failed attempts.

Can I prevent PHP files from being edited via the WordPress admin?

Yes. Add this to wp-config.php:

define( 'DISALLOW_FILE_EDIT', true );

This disables the theme and plugin editors in the WordPress admin. It pairs well with HXFE’s code-first approach — forms and code are managed via deployment, not the admin UI.

Can I save uploaded files somewhere other than email attachments?

HXFE deletes uploaded files from the server immediately after sending the email. This is intentional — keeping files on the server increases security risk and GDPR responsibility.

For permanent storage, the recommended approach is to use Gmail + Google Apps Script (GAS): set up a time-based trigger that reads incoming form emails and saves attachments to a designated Google Drive folder. This keeps files off your WordPress server entirely and lets you manage access through Google’s permission system.

Reviews

There are no reviews for this plugin.

Contributors & Developers

“HXFE — Code-First Forms” is open source software. The following people have contributed to this plugin.

Contributors

Changelog

1.3.7

  • Security: Removed skip_sanitize parameter from hxfe_process_fields() — all values are now sanitized on every call, including confirmsubmit flow
  • Security: Clarified that sanitize_text_field() and related functions are idempotent, so re-sanitizing already-sanitized values is safe

1.3.6

  • Security: Added nonce verification to hxfe_handle_back() to prevent unauthorized form re-rendering
  • Security: Back button now passes hxfe_nonce (hxfe_validate_{form_id}) via hx-vals
  • Code: Clarified skip_sanitize=true comment in hxfe_handle_submit() to explain double-sanitize prevention

1.3.5

  • Renamed schema key: redirect_rules complete_redirect_rules (consistent with other complete_* keys)
  • Renamed schema keys: before_open_html / after_close_html before_html / after_html
  • Renamed field keys: min_check / max_check min / max (consistent with min_date / max_date)
  • Deprecated field key hide_if — use show_if instead (backward compatible, will be removed in a future version)

1.3.4

  • Added: Page slug auto-injected into subject as [form-id@slug] for per-page tracking
  • Added: Schema examples panel in admin UI with 7 copy-paste samples
  • Added: Responsive breakpoint at 768px
  • Added: CSS custom properties (design tokens) for easy theme customization
  • Added: download_url / download_label schema keys — download button on complete screen
  • Added: available_from / available_until schema keys — form availability window
  • Added: before_html / after_html schema keys — custom messages outside window
  • Added: allowed_origins schema key — per-form iframe CORS restriction
  • Added: Embed HTML <iframe> copy button in admin form list
  • Improved: Admin UI redesigned — stat cards, clean table, monospace field type chips
  • Improved: chatbot send button replaced with paper-plane SVG icon
  • Improved: Login/auth screen with border, padding, full-width button
  • Improved: iframe / CORS Settings tab removed — now schema-level only
  • Fixed: hx-encoding=”multipart/form-data” auto-applied when file field present
  • Fixed: File name shown correctly on confirm screen
  • Fixed: File attachment preserved through confirm submit flow
  • Fixed: Temporary file cleanup cron (hourly, 1h expiry)
  • Fixed: Fade-in flash bug (remove+reflow caused visible flicker)
  • Added: complete_html_rules schema key — conditional complete screen HTML (supports {field_key} interpolation)
  • Added: Diagnosis/calculator mode — omit to with complete_html_rules for no-email chatbot
  • Added: chatbot + show_if / required_if conditional fields now fully supported
  • Improved: chatbot UI redesigned with LINE/Slack-style header, timestamps, and bubble shadows
  • Added: pattern / minlength / maxlength / error_message schema keys for field-level validation
  • Added: hxfe_validate_field filter for per-field custom validation
  • Added: hxfe_validate_form filter for cross-field validation (password confirm, at-least-one, etc.)
  • Added: before_html / after_html schema keys for injecting HTML around fields
  • Added: disable_context schema key to opt out of page slug auto-injection

1.3.3

  • Renamed: SHFE HXFE across all PHP/JS/CSS (class names, IDs, function prefixes)
  • Fixed: Scroll after htmx outerHTML swap (re-fetch element by ID after swap)
  • Fixed: Step form Back button returning 403 (nonce was missing from hx-vals)
  • Fixed: chatbot phpcs:ignore comment appearing as visible text in UI
  • Fixed: Copy button fallback for HTTP environments (execCommand)
  • Changed: Shortcode copy buttons labeled “Form” / “iFrame” for clarity

1.3.2

  • Added: IP restriction — whitelist IPs and CIDR ranges per form (allowed_ips)
  • Added: Customizable IP blocked message (ip_blocked_html)
  • Added: Form-level password authentication (auth.users)
  • Added: Brute-force protection — lockout after 5 failed attempts (15 min)
  • Added: Auth session via secure httponly samesite=strict cookie
  • Added: Login form labels fully customizable per form
  • Added: Support for wp-config.php constants as password source (keeps secrets out of Git)

1.3.1

  • Security: file field now uses HXFE’s own safe MIME whitelist by default instead of WordPress defaults
  • Security: added .htaccess to hxfe-uploads/ directory to prevent PHP execution
  • Added: file field type now works — uploaded files are attached to admin notification emails
  • Added: includes/file-upload.php with wp_handle_upload() based processing
  • Added: mime_types schema key to whitelist allowed MIME types server-side
  • Added: temporary files are automatically deleted after email is sent
  • Removed: lint warning about file field being unimplemented

1.3.0

  • Refactored: extracted field renderer functions to includes/fields/field-renderers.php
  • Refactored: added hxfe_validate_step_request() to DRY up step endpoint gate logic
  • Refactored: improved PhpDoc type definitions on core functions (hxfe_process_fields, hxfe_eval_condition, hxfe_interpolate)

1.2.2

  • Fixed: confirm_label now correctly applies to the input form submit button
  • Fixed: hxfe-front.js (scroll, focus, loading state) was not enqueued
  • Fixed: disable_default_css and custom_css now work correctly
  • Fixed: chatbot.js is now only loaded on pages with chatbot forms
  • Fixed: uninstall.php now removes all plugin settings from the database
  • Added: error_message schema key to customize the validation error summary text
  • Added: confirm_label schema key (separate from submit_label for clarity)
  • Note: file field type renders HTML but file saving is not yet implemented

1.2.1

  • Added tel and url field types with built-in validation
  • Added Webhook support (Zapier, Make, Slack, custom HTTP endpoints)
  • Added label customization: submit_label, back_label, next_label, confirm_heading
  • Fixed confirmation screen: radio/select now shows label instead of value
  • Fixed confirmation screen: checkbox_group shows comma-separated labels
  • Fixed confirmation screen: hidden fields (show_if=false) are now excluded
  • Fixed mail body: empty fields and hidden fields are now excluded
  • Added confirm: false support for step forms
  • Added built-in placeholders: {site_name}, {site_url}, {date}, {time}
  • Added admin form list page with lint warnings and shortcode copy buttons
  • Strengthened schema lint: all 15 field types, cascade_from, chatbot bot_message
  • Added wp_mail() failure logging when WP_DEBUG is enabled

1.2.0

  • Added field types: radio, checkbox_group, number, date, file
  • Added chatbot UI mode (step_mode: chatbot) with typing animation
  • Added 4 completion patterns: message, custom HTML, redirect, redirect_rules
  • Added default values (value key on any field)
  • Added multiple recipients (to as array)
  • Added confirm: false for immediate submission
  • Added cascade select (cascade_from / cascade_options)

1.1.0

  • Added step forms (groups and one_by_one mode)
  • Added reCAPTCHA v2 and v3
  • Added privacy policy field
  • Added auto-reply email
  • Added SMTP configuration (Gmail, SendGrid, Mailgun, custom)
  • Added iframe embedding with CORS support
  • Added conditional logic (show_if, required_if, skip_if, to_rules, subject_rules)
  • Added CSS customization options

1.0.0

  • Initial release
  • Schema-driven form rendering
  • htmx-powered input confirm complete flow
  • Admin notification email and auto-reply
  • Honeypot spam protection