binary-wp / admin-guide
JSON-driven admin guide builder for WordPress. Works as a standalone plugin or as a Composer dependency in another plugin/theme.
Requires
- php: >=7.4
- erusev/parsedown-extra: ^0.9
- league/html-to-markdown: ^5.1
Requires (Dev)
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Admin guide builder for WordPress with hierarchical CPT storage, drag & drop nav-menu style builder, WYSIWYG editor with placeholder pills, JSON-driven integration registry, and per-instance prefix isolation so multiple hosts can bundle it side-by-side.
Works three ways:
- Standalone plugin — drop into
wp-content/plugins/admin-guide/, activate, done. - Composer dependency in another plugin —
composer require binary-wp/admin-guide, thenPlugin::boot()from your plugin's main file. - Composer dependency in a theme — same as above from
functions.php.
Requirements
- PHP 7.4+
- WordPress 5.8+
Installation
As a standalone plugin
cd wp-content/plugins git clone https://github.com/wasilosos/admin-guide.git cd admin-guide composer install
Then activate "Admin Guide" in Plugins.
As a Composer dependency
composer require binary-wp/admin-guide
In your plugin/theme main file, boot an instance before admin_menu:
use BinaryWP\AdminGuide\Plugin; // Minimal — package_path/url auto-detected from vendor location: Plugin::boot( 'my_prefix' );
All options are optional. Full example with overrides:
Plugin::boot( 'my_prefix', [ 'package_path' => __DIR__ . '/vendor/binary-wp/admin-guide/', 'package_url' => plugin_dir_url( __FILE__ ) . 'vendor/binary-wp/admin-guide/', 'guide_dir' => __DIR__ . '/guide/', 'capability' => 'manage_options', 'menu' => [ 'parent' => 'tools.php', // or your own top-level slug, or '' for standalone 'viewer_label' => 'Admin Guide', 'builder_label' => 'Guide Builder', ], 'integrations_dirs' => [ __DIR__ . '/my-integrations/' ], ] );
Auto-detection: package_path defaults to the package's own directory. package_url is resolved via plugins_url() or theme URI. guide_dir falls back to the nearest plugin/theme root + /guide/.
Your instance prefix ('my_prefix') scopes all CPT slugs, AJAX actions, nonces, asset handles, and admin page slugs so multiple instances can coexist.
How it works
Storage
Guide pages are stored as a hierarchical custom post type ({prefix}_guide):
| Field | Usage |
|---|---|
post_title |
Tab label |
post_name |
Tab slug |
post_content |
HTML template with {{placeholders}} |
post_parent |
Hierarchy (0 = top-level, >0 = child) |
menu_order |
Sort position |
_guide_source meta |
system / post_type / taxonomy / platform / custom |
_guide_group meta |
1 = group-only tab (no own content, shows first child) |
Benefits: revisions, REST API, standard WP queries, native WP export.
Builder page
Nav-menu style drag & drop sortable with depth management (max 1 level deep). Matches WP core menu editor look and feel. Sidebar with metaboxes for adding system guides (from integrations) and custom guides.
Editor page
Standalone TinyMCE with placeholder palette sidebar. Click to insert or drag & drop placeholders into the editor. Placeholders render as non-editable pills in the editor and are stored as {{tokens}} in the database.
Output generation
On every save, the generator:
- Queries all published
{prefix}_guideposts - Resolves
{{placeholders}}via PHP callbacks - Writes
.htmlsnapshots toguide/html/(for fast admin rendering) - Writes
.mdcopies toguide/(portable reading, vialeague/html-to-markdown)
Display
The host renders the guide viewer with:
- Top-level tabs as horizontal
nav-tab-wrapper - Children as inline sub-navigation (WooCommerce-style
subsubsub) - Group-only tabs auto-fall through to first child content
The viewer ships its own paint (assets/guide-viewer.css, enqueued automatically),
so guide content needs no styling from the host:
- Tables get the wp-admin list-table look — no class needed on the
<table>. - Figures get a bordered image and a muted caption. No width or float is imposed, so a figure that carries its own sizing keeps it.
binary-wp-admin-guide-figure-inset— add this class to a<figure>to float it right with the copy wrapping around it. Suits screenshots; leave it off anything that needs its natural width.
<figure class="binary-wp-admin-guide-figure-inset"> <img src="..." alt="..."> <figcaption>Where to find the Transform menu.</figcaption> </figure>
Per-host integrations
Ship your own JSON integration definitions alongside the package:
Plugin::boot( 'my_prefix', [ 'integrations_dirs' => [ __DIR__ . '/guide-integrations/' ], // ... ] );
Each directory is scanned for *.json integration files. Each JSON defines:
name,slug,requires(class/function/option checks for auto-detection)placeholders[]with token, description, type, optional callbacktab_templates[]for auto-creating system tabsexternal_statusfor live service status checks
Render functions live in functions/{slug}.php alongside the JSON files.
Example: custom integration JSON
Create guide-integrations/my-crm.json:
{
"slug": "my-crm",
"name": "My CRM",
"prefix": "my_crm",
"requires": { "plugin": "my-crm/my-crm.php" },
"settings_url": "admin.php?page=my-crm-settings",
"docs_url": "https://example.com/docs/",
"external": [
{
"service": "API Connection",
"description": "CRM sync status",
"check": "my_crm_api"
}
],
"tab_templates": [
{ "slug": "my-crm-overview", "label": "My CRM Overview" }
],
"placeholders": {
"{{my_crm_sync_status}}": {
"callback": "my_crm_guide_sync_status",
"description": "Current CRM sync status"
},
"{{my_crm_settings_link}}": {
"type": "settings_link",
"url": "admin.php?page=my-crm-settings",
"label": "CRM Settings",
"description": "Link to CRM settings page"
}
}
}
Then create guide-integrations/functions/my-crm.php with the render callback:
function my_crm_guide_sync_status() { $last_sync = get_option( 'my_crm_last_sync' ); return $last_sync ? sprintf( 'Last sync: %s', human_time_diff( $last_sync ) . ' ago' ) : 'Not synced yet'; }
The integration auto-detects when my-crm/my-crm.php is active — its placeholders and tab templates appear in the builder automatically.
Extensions
Other plugins add screens, toolbar buttons, settings cards and tab sources through public hooks. See HOOKS.md for the full list.
Site Compare, a source-vs-target screenshot gallery for migrations, was built into this package up to 0.12. It now lives in binary-wp/site-compare and attaches through those hooks.
Exposed API
$plugin = \BinaryWP\AdminGuide\Plugin::get( 'my_prefix' ); // Tabs $plugin->config->get_tabs(); // [ slug => label ] (top-level) $plugin->config->get_children( $parent_slug ); // [ slug => label ] (children) $plugin->config->get_all_guides(); // full tree with depth $plugin->config->get_template( $slug ); // raw HTML content $plugin->config->add_tab( $slug, $label, $source ); $plugin->config->remove_tab( $slug ); $plugin->config->save_order( $items ); // [{ id, parent_id, position }] // Import / Export $plugin->config->export(); // JSON-serializable array $plugin->config->import( $bundle ); // true | WP_Error // Generator $plugin->generator->generate(); // regenerate all output files $plugin->generator->read_tab( $slug ); // rendered HTML for display $plugin->generator->remove_files( $slug ); // clean up generated files for a slug
Hooks
Filters (each also fires a prefix-scoped variant, e.g. my_prefix/guide_builder/guide_dir):
guide_builder/guide_dir— output directory for generated filesguide_builder/system_tabs— available system tab groups in the builder UI
Actions:
guide_builder/placeholders— register custom placeholdersadmin_guide_builder/integrations— register additional integrations at runtime (full hook list: HOOKS.md)
Translations
The package ships with a translation template (languages/admin-guide-builder.pot) and a Czech translation (cs_CZ). Text domain: admin-guide-builder, loaded on init priority 1 (a WordPress.org language pack first, then the bundled file).
To contribute a translation:
- Copy
languages/admin-guide-builder.pottolanguages/admin-guide-builder-{locale}.po - Translate each
msgstr(use Poedit or any PO editor) - Compile:
msgfmt --check --output-file=languages/admin-guide-builder-{locale}.mo languages/admin-guide-builder-{locale}.po - Submit a PR with both
.poand.mofiles
Regenerating the .pot template
composer make-pot
This runs wp i18n make-pot, which also picks up the translators: comments. Then update existing translations with msgmerge --update languages/admin-guide-builder-cs_CZ.po languages/admin-guide-builder.pot and recompile them with msgfmt.
License
GPL-2.0-or-later (see LICENSE). Releases up to 0.12.0 were published under MIT.