À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: chatbotorone_by_oneto 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 (
stepsarray) - 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_ruleswithoutto— show results without sending email - Download after submit:
download_urlshows a download button on the complete screen (document request forms) - Form availability window:
available_from/available_untilwith custom before/after HTML - Custom validation:
pattern,minlength,maxlength,error_messageschema keys +hxfe_validate_fieldandhxfe_validate_formfilter hooks - Field HTML injection:
before_html/after_htmlschema 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.txtandai-reference.mdfor 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ẹ̀
- Upload the plugin folder to
/wp-content/plugins/ - Activate in Plugins Installed Plugins
- Add schemas via the
hxfe_schemasfilter infunctions.php - Place
[hxfe_form id="your-id"]in any page or post - 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_ifconditions work in chatbot mode — hidden fields are automatically skipped. You can also use{field_key}placeholders inbot_messageto reference previous answers. -
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
webhooksarray 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' => falseto your schema. Works for normal forms and step forms. -
Can I restrict a form to specific IP addresses?
-
Yes. Add
allowed_ipsto your schema with a list of IPs or CIDR ranges. Visitors outside the whitelist see a blocked message, which you can customize withip_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
authkey to your schema. To keep passwords out of Git, define them as constants inwp-config.phpand 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ópaTú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_rulescomplete_redirect_rules(consistent with othercomplete_*keys) - Renamed schema keys:
before_open_html/after_close_htmlbefore_html/after_html - Renamed field keys:
min_check/max_checkmin/max(consistent withmin_date/max_date) - Deprecated field key
hide_if— useshow_ifinstead (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_labelschema keys — download button on complete screen - Added:
available_from/available_untilschema keys — form availability window - Added:
before_html/after_htmlschema keys — custom messages outside window - Added:
allowed_originsschema 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_rulesschema key — conditional complete screen HTML (supports {field_key} interpolation) - Added: Diagnosis/calculator mode — omit
towithcomplete_html_rulesfor no-email chatbot - Added: chatbot +
show_if/required_ifconditional fields now fully supported - Improved: chatbot UI redesigned with LINE/Slack-style header, timestamps, and bubble shadows
- Added:
pattern/minlength/maxlength/error_messageschema keys for field-level validation - Added:
hxfe_validate_fieldfilter for per-field custom validation - Added:
hxfe_validate_formfilter for cross-field validation (password confirm, at-least-one, etc.) - Added:
before_html/after_htmlschema keys for injecting HTML around fields - Added:
disable_contextschema 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
