Agent-skills wp-interactivity-api
Use when building or debugging WordPress Interactivity API features (data-wp-* directives, @wordpress/interactivity store/state/actions, block viewScriptModule integration, wp_interactivity_*()) including performance, hydration, and directive behavior.
git clone https://github.com/WordPress/agent-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/WordPress/agent-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/wp-interactivity-api" ~/.claude/skills/wordpress-agent-skills-wp-interactivity-api && rm -rf "$T"
skills/wp-interactivity-api/SKILL.mdWP Interactivity API
When to use
Use this skill when the user mentions:
- Interactivity API,
,@wordpress/interactivity
,data-wp-interactive
,data-wp-on--*
,data-wp-bind--*
,data-wp-context- block
/ module-based view scripts,viewScriptModule - hydration issues or “directives don’t fire”.
Inputs required
- Repo root + triage output (
).wp-project-triage - Which block/theme/plugin surfaces are affected (frontend, editor, both).
- Any constraints: WP version, whether modules are supported in the build.
Procedure
1) Detect existing usage + integration style
Search for:
data-wp-interactive@wordpress/interactivityviewScriptModule
Decide:
- Is this a block providing interactivity via
view script module?block.json - Is this theme-level interactivity?
- Is this plugin-side “enhance existing markup” usage?
If you’re creating a new interactive block (not just debugging), prefer the official scaffold template:
(via@wordpress/create-block-interactive-template
)@wordpress/create-block
2) Identify the store(s)
Locate store definitions and confirm:
- state shape,
- actions (mutations),
- callbacks/event handlers used by
.data-wp-on--*
3) Server-side rendering (best practice)
Pre-render HTML on the server before outputting to ensure:
- Correct initial state in the HTML before JavaScript loads (no layout shift).
- SEO benefits and faster perceived load time.
- Seamless hydration when the client-side JavaScript takes over.
Enable server directive processing
For components using
block.json, add supports.interactivity:
{ "supports": { "interactivity": true } }
For themes/plugins without
block.json, use wp_interactivity_process_directives() to process directives.
Initialize state/context in PHP
Use
wp_interactivity_state() to define initial global state:
wp_interactivity_state( 'myPlugin', array( 'items' => array( 'Apple', 'Banana', 'Cherry' ), 'hasItems' => true, ));
For local context, use
wp_interactivity_data_wp_context():
<?php $context = array( 'isOpen' => false ); ?> <div <?php echo wp_interactivity_data_wp_context( $context ); ?>> ... </div>
Define derived state in PHP
When derived state affects initial HTML rendering, replicate the logic in PHP:
wp_interactivity_state( 'myPlugin', array( 'items' => array( 'Apple', 'Banana' ), 'hasItems' => function() { $state = wp_interactivity_state(); return count( $state['items'] ) > 0; } ));
This ensures directives like
data-wp-bind--hidden="!state.hasItems" render correctly on first load.
For detailed examples and patterns, see
references/server-side-rendering.md.
4) Implement or change directives safely
When touching markup directives:
- keep directive usage minimal and scoped,
- prefer stable data attributes that map clearly to store state,
- ensure server-rendered markup + client hydration align.
WordPress 6.9 changes:
is deprecated and will be removed in future versions. It broke context inheritance and caused issues with client-side navigation. Avoid using it.data-wp-ignore- Unique directive IDs: Multiple directives of the same type can now exist on one element using the
separator (e.g.,---
anddata-wp-on--click---plugin-a="..."
).data-wp-on--click---plugin-b="..." - New TypeScript types:
andAsyncAction<ReturnType>
help with async action typing.TypeYield<T>
For quick directive reminders, see
references/directives-quickref.md.
5) Build/tooling alignment
Verify the repo supports the required module build path:
- if it uses
, prefer its conventions.@wordpress/scripts - if it uses custom bundling, confirm module output is supported.
6) Debug common failure modes
If “nothing happens” on interaction:
- confirm the
is enqueued/loaded,viewScriptModule - confirm the DOM element has
,data-wp-interactive - confirm the store namespace matches the directive’s value,
- confirm there are no JS errors before hydration.
See
references/debugging.md.
Verification
indicateswp-project-triage
after your change (if applicable).signals.usesInteractivityApi: true- Manual smoke test: directive triggers and state updates as expected.
- If tests exist: add/extend Playwright E2E around the interaction path.
Failure modes / debugging
- Directives present but inert:
- view script not loading, wrong module entrypoint, or missing
.data-wp-interactive
- view script not loading, wrong module entrypoint, or missing
- Hydration mismatch / flicker:
- server markup differs from client expectations; simplify or align initial state.
- derived state not defined in PHP: use
with closures.wp_interactivity_state()
- Initial content missing or wrong:
not set insupports.interactivity
(for blocks).block.json
not called (for themes/plugins).wp_interactivity_process_directives()- state/context not initialized in PHP before render.
- Layout shift on load:
- derived state like
missing on server, causingstate.hasItems
attribute to be absent.hidden
- derived state like
- Performance regressions:
- overly broad interactive roots; scope interactivity to smaller subtrees.
- Client-side navigation issues (WordPress 6.9):
andgetServerState()
now reset between page transitions—ensure your code doesn't assume stale values persist.getServerContext()- Router regions now support
for rendering overlays (modals, pop-ups) dynamically.attachTo
Escalation
- If repo build constraints are unclear, ask: "Is this using
or a custom bundler (webpack/vite)?"@wordpress/scripts - Consult:
references/server-side-rendering.mdreferences/directives-quickref.mdreferences/debugging.md