From superpowers-sage
Integrates HTML Forms WordPress plugin with Sage via log1x/sage-html-forms, providing stateless contact forms with Blade rendering, Constraint Validation API, and progressive JS validation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/superpowers-sage:sage-formsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Stateless form rendering via the HTML Forms WordPress plugin, bridged into Sage by `log1x/sage-html-forms`. Forms live as a CPT (`html-form`), are referenced from ACF blocks via `addPostObject`, and render through a Blade filter that routes to project-controlled form views.
Stateless form rendering via the HTML Forms WordPress plugin, bridged into Sage by log1x/sage-html-forms. Forms live as a CPT (html-form), are referenced from ACF blocks via addPostObject, and render through a Blade filter that routes to project-controlled form views.
| Approach | Best for |
|---|---|
| HTML Forms + sage-html-forms | Stateless contact/lead forms; editors pick the form from a dropdown; submissions handled by the HF plugin |
| Livewire form | Reactive state, multi-step wizards, inline validation tied to server state |
Blade + native <form> | Single-field or trivial forms with no submission pipeline |
acorn-livewire skill)<form> is simplerx-form.* components present in resources/views/components/form/ (the design-system form primitives)lando composer require wpackagist-plugin/html-forms
lando theme-composer require log1x/sage-html-forms
Acorn's package discovery auto-registers the service provider — no manual wiring. Full details: references/installation.md.
The form is a html-form CPT post. A block exposes an ACF addPostObject field scoped to that CPT so the editor picks the form. The block view renders it via hf_get_form($form->ID)->get_html(), which the sage-html-forms provider intercepts and routes to a Blade view at resources/views/forms/{form-slug}.blade.php. The Blade form view uses the project's x-form.* components.
{{-- Block view (snippet) --}}
@if ($form)
{!! hf_get_form($form->ID)->get_html() !!}
@endif
{{-- resources/views/forms/{form-slug}.blade.php --}}
<x-html-forms :form="$form">
<x-form.field label="Name" for="name" :required="true">
<x-form.input type="text" name="name" :required="true" minlength="2" />
</x-form.field>
{{-- ...more fields... --}}
<x-button type="submit" variant="primary" class="w-full">Send</x-button>
</x-html-forms>
Full walkthrough: references/blade-form-views.md.
Client-side validation is a reusable ES module imported by the block's JS — never globally enqueued. The module exposes one function:
initHfValidation(formEl, { messages, validators, onSuccess, onError });
Four layers: native HTML5 constraints, blur validation, input lazy re-validation while aria-invalid="true", and post-submit scroll via the HTML Forms plugin's DOM events (hf-success, hf-error, hf-submitted).
Full API and implementation: references/hf-validation.md.
Three documented bugs that silently break forms in this stack. Full symptom/root cause/fix for each: references/traps.md.
pattern attribute backslash escaping in Blade components. $attributes->merge() double-escapes backslashes; patternMismatch never fires. Symptom: form submits even though pattern regex doesn't match user input. Workaround: use a JS validator, not a pattern attribute.type="tel" skips patternMismatch in Chrome. Use type="text" inputmode="tel" instead. Symptom: phone format validator silently no-ops in Chrome (works in Firefox/Safari).ValidityState is non-enumerable. Spread ({ ...field.validity }) and Object.keys() return empty. Symptom: your error-message lookup object is always empty. Access named properties directly: validity.valueMissing, validity.patternMismatch, validity.tooShort, validity.customError, etc.| File | Role |
|---|---|
app/Blocks/{ClassName}.php | ACF block — addPostObject field + with() mapping |
resources/views/blocks/{slug}.blade.php | Block view — calls hf_get_form($form->ID)->get_html() |
resources/views/forms/{form-slug}.blade.php | Form view — x-html-forms + x-form.* structure |
resources/js/blocks/{slug}.js | Block custom element — imports initHfValidation, configures per form |
resources/js/modules/hf-validation.js | Reusable validation module (one per project, not per form) |
agents/forms.md (user-invocable specialist — analyzes and refactors existing forms, or scaffolds new ones)skills/block-scaffolding/SKILL.md Phase 0c (coordinated scaffold when a block embeds a form)Both consumers treat this skill as authoritative — no pattern, template, or trap is documented outside this skill.
npx claudepluginhub hekivo/superpowers-sageScaffolds ACF Composer blocks with custom element architecture, scoped CSS, theme variations, and JS lifecycle. Use when creating new Gutenberg blocks in Sage-based WordPress themes.
Develops WordPress themes using Sage framework: create from scratch, set up Blade templates/components, configure Vite/Bud builds, handle template hierarchy, integrate ACF fields, manage assets.
Guide for Netlify Forms HTML form handling. Covers data-netlify attribute, AJAX submissions, file uploads, spam filtering, notifications, and static skeleton files for JavaScript-rendered forms.