Extending the IDE

The IDE is built to be extended the same way its own built-in features are. Everything you can register — panels, tabs, status-bar items, view modes, menu actions, preferences — goes through the public API on window.WPGraphQLIDE, the same registry the IDE itself uses internally (src/registry/index.js).

There are three moving parts:

  1. A PHP shell that enqueues your JavaScript with wpgraphql-ide as a dependency.
  2. A JS entry that waits for the IDE to be ready, then registers your contributions.
  3. The registries and hooks on window.WPGraphQLIDE.

1. Enqueue your script (PHP)

Hook wpgraphql_ide_enqueue_script — it fires right before the IDE’s own render script is enqueued, so depending on wpgraphql-ide guarantees load order.

add_action( 'wpgraphql_ide_enqueue_script', function ( $app_context ) {
	wp_enqueue_script(
		'my-ide-extension',
		plugins_url( 'build/extension.js', __FILE__ ),
		[ 'wpgraphql-ide' ], // ensures window.WPGraphQLIDE exists first
		'1.0.0',
		true
	);
} );

See Actions & Filters for the PHP hooks (wpgraphql_ide_enqueue_script, wpgraphql_ide_localized_data, the capability filter, etc.).

2. Wait for the IDE, then register (JS)

The IDE assembles window.WPGraphQLIDE and then dispatches the WPGraphQLIDE_Window_Ready DOM event. Do all your wiring inside that listener — it’s the guarantee that the stores, registries, and hook bus are in place.

window.addEventListener('WPGraphQLIDE_Window_Ready', () => {
	const { registerResponseExtensionTab } = window.WPGraphQLIDE;

	registerResponseExtensionTab('myExtension', {
		title: 'My Extension',
		content: ({ data, response }) => <pre>{JSON.stringify(data, null, 2)}</pre>,
	}, 50);
});

window.WPGraphQLIDE exposes every register* function plus the shared hooks bus (a @wordpress/hooks instance — the same one wp.hooks delegates to). Anything fired by the IDE’s PHP-side or JS-side hooks travels on that bus.

3. What you can extend

You want to…Register withGuide / reference
Surface your extensions payload in the response paneregisterResponseExtensionTabAdding a Response Panel
Add a live badge by the HTTP status / duration / sizeregisterStatusBarItemAdding a Status Bar Item
Add a global left-sidebar panelregisterActivityBarPanelAdding an Activity Bar Panel
Add a response viewer mode (next to JSON / Table)registerResponseViewModeAccess Functions
Add a tab beneath the editor (next to Variables / Headers)registerEditorBottomTabAccess Functions
Add a query-editor toolbar buttonregisterDocumentEditorToolbarButtonAccess Functions
Add kebab-menu actions (response / editor / document tab)registerResponseAction / registerEditorAction / registerDocumentTabActionAccess Functions
Add a top-bar button + workspace tabregisterTopbarAction / registerWorkspaceTabTypeAccess Functions
Persist a setting (device or user scope)registerPreferenceAccess Functions
Observe or rewrite every request / responsewpgraphql-ide.executeRequest / executeResponse / afterExecuteHooking the Execute Lifecycle
Publish a toastwpgraphql-ide.noticeActions & Filters

Things to know before you build

  • React & JSX — React, ReactDOM, and GraphQL are WordPress script externals. Build your extension with @wordpress/scripts (or any bundler that externalizes react / wp.*) so it shares the IDE’s React instance. The bundled extensions under plugins/ are working examples.
  • Surfaces mount conditionally. A panel/tab/item is unmounted when it isn’t on screen. If you need state that accumulates across executions or persists while hidden, don’t keep it in component state — see Tracking State Across Executions.
  • Public API & SemVer. The register* functions, the @wordpress/data store names, the PHP hooks, and registered preference keys are public. Breaking changes require a major version bump.