HXFE — Code-First Forms

Àpèjúwe

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Ìtumọ̀ Yorùbá: ’s servers and verifies the userÌtumọ̀ Yorùbá: ’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Ìtumọ̀ Yorùbá: ’s browser loads the reCAPTCHA script from google.com. On form submission, the reCAPTCHA token generated in the visitorÌtumọ̀ Yorùbá: ’s browser is sent to GoogleÌtumọ̀ Yorùbá: ’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

Ìgbéwọlẹ̀

  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Ìtumọ̀ Yorùbá: ’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Ìtumọ̀ Yorùbá: ’s permission system.

Àwọn àgbéyẹ̀wò

Kò sí àwọn àgbéyẹ̀wò fún plugin yìí.

Àwọn Olùkópa & Olùgbéejáde

“HXFE — Code-First Forms” jẹ́ ètò ìṣàmúlò orísun ṣíṣí sílẹ̀. Àwọn ènìyàn wọ̀nyí ti ṣe ìkópa sí plugin yìí.

Àwọn Olùkópa

Túmọ̀ “HXFE — Code-First Forms” sí èdè rẹ.

Ṣe o nífẹ̀ẹ́ sí ìdàgbàsókè?

Ṣàwárí koodu, ṣàyẹ̀wò ibi ìpamọ́ SVN, tàbí ṣe àgbékalẹ̀ sí àkọsílẹ̀ ìdàgbàsókè nípasẹ̀ RSS.

Àkọsílẹ̀ àwọn àyípadà

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Ìtumọ̀ Yorùbá: ’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