HTML Forms + Sage integration — log1x/sage-html-forms, hf_get_form, addPostObject html-form, Blade form views, x-form.* shared components, hf-validation JS module, hf-success hf-error hf-submitted events, Constraint Validation API, form traps pattern escaping type-tel ValidityState non-enumerable — stateless contact forms with progressive JS validation on top of the HTML Forms WordPress plugin. Invoke for: contact form with HTML Forms plugin, hf_get_form usage, form validation with Constraint...
Scanned 9/11/2026
Install to Claude Code
npx -y skills add hekivo/superpowers-sage --skill sage-forms --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Sage Forms?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/hekivo-sage-forms-superpowers-sage)More formats (shields.io, HTML) on the badges page.
---
name: superpowers-sage:sage-forms
description: >
HTML Forms + Sage integration — log1x/sage-html-forms, hf_get_form,
addPostObject html-form, Blade form views, x-form.* shared components,
hf-validation JS module, hf-success hf-error hf-submitted events,
Constraint Validation API, form traps pattern escaping type-tel
ValidityState non-enumerable — stateless contact forms with progressive
JS validation on top of the HTML Forms WordPress plugin.
Invoke for: contact form with HTML Forms plugin, hf_get_form usage, form validation
with Constraint API, pattern escaping trap, type=tel Chrome bug, form audit.
user-invocable: false
---
# HTML Forms + Sage Integration
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.
## When to Use
| 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 |
## When NOT to Use
- Form requires multi-step state → use Livewire (`acorn-livewire` skill)
- Form payload drives a Laravel controller action → Acorn Routes + Blade form, not HTML Forms
- Form must be embedded outside a block context (e.g. header newsletter) → Blade component + native `<form>` is simpler
## Prerequisites
- Sage 11+ / Acorn 4+ on Bedrock with Lando
- ACF Composer installed (for the block field declaration)
- Shared `x-form.*` components present in `resources/views/components/form/` (the design-system form primitives)
## Installation Summary
```bash
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](references/installation.md).
## Integration Pattern Summary
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.
```blade
{{-- Block view (snippet) --}}
@if ($form)
{!! hf_get_form($form->ID)->get_html() !!}
@endif
```
```blade
{{-- 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](references/blade-form-views.md).
## Validation Module Summary
Client-side validation is a reusable ES module imported by the block's JS — never globally enqueued. The module exposes one function:
```js
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](references/hf-validation.md).
## Traps (Critical)
Three documented bugs that silently break forms in this stack. Full symptom/root cause/fix for each: [references/traps.md](references/traps.md).
- **T1 — `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.
- **T2 — `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).
- **T3 — `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 Map (canonical per form integration)
| 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) |
## Consumers
- `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.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!