DEV Community

Cessare Cn
Cessare Cn

Posted on

From “Where’s That Setting?” to “ K, Type, Enter”: A Developer’s Field Manual for CommandUI

WordPress Themes

If you work inside WordPress all day, you already feel the tax of mouse-driven navigation: nested menus, page loads between every click, and a hundred different places a single setting might hide. A Command Palette fixes that by making navigation and actions keyboard-native. CommandUI (short for CommandUI – Command Palette for WordPress) brings the same speed you love in editors like VS Code to wp-admin and even your front-end. This article is a deep, practical guide to designing a keyboard-first admin, wiring custom actions, handling permissions, and avoiding performance and accessibility footguns. By the end, pressing ⌘K / Ctrl-K won’t be a novelty; it will be how you run your site.

wordpress command palette


TL;DR

  • Command palettes are not search bars; they’re action launchers with fuzzy search, preview, and context.
  • CommandUI ships sane defaults (navigation, posts, users, settings) and an API for you to add domain-specific commands.
  • Treat commands like code: typed, permission-checked, idempotent; everything testable.
  • Keyboard UX and accessibility aren’t “nice to have”—they’re your adoption curve.
  • You can roll out palette usage to content teams incrementally without breaking muscle memory for classic menus.

Table of Contents

  1. Why a Command Palette in WordPress?
  2. Anatomy of a Great Palette (and how CommandUI implements it)
  3. Installing and first-run checklist
  4. Writing Commands (PHP + JS)
  5. Fuzzy search, ranking, and “intent folding”
  6. Permissions, capability checks, and auditability
  7. Navigation items vs. verbs (action design)
  8. Contextual palettes on the front-end (theme & block editor)
  9. Performance budgets and how to stay fast
  10. Accessibility: focus management, ARIA, and reduced motion
  11. Case studies: Publishers, Woo stores, and Multi-site fleets
  12. Recipes: 20 commands your team will actually use
  13. Testing + rollout plan (14-day adoption sprint)
  14. Troubleshooting matrix (symptom → cause → fix)
  15. Opinionated micro-copy you can paste
  16. Final checklist before pushing to production

1) Why a Command Palette in WordPress?

  • Navigation entropy: Plugins add top-level menus, submenus, and settings pages with zero global information architecture. The palette gives you a single mental model: open palette → type intent → run action.
  • Speed: Fuzzy search + keyboard = sub-second navigation. You’ll never “hunt” again.
  • Teachability: A command like “New product” can guide a junior editor through the exact flow you want, with fewer detours.
  • Consistency: Keyboard patterns copy over from dev tools (VS Code, Raycast, Spotlight).
  • Automation: Commands can call REST endpoints and bulk operations. You’re not limited to opening screens.

CommandUI focuses on pragmatic wins: it indexes your admin, exposes native actions, and lets you compose your own commands with minimum glue code.


2) Anatomy of a Great Command Palette

A quality palette is not “search + list.” It’s a UI with strict ergonomics:

  • Open with ⌘K / Ctrl-K (configurable).
  • Fuzzy search (typo-tolerant) with scoring that boosts recently used and role-relevant commands.
  • Groupings (Navigation, Create, Edit, Tools, Developer, Site).
  • Preview pane for risky actions (bulk delete, cache purge) or entity context (post excerpt, product price).
  • Inline shortcuts: show to execute, ⇧↵ to open in new tab, ⌥↵ to run with default options.
  • Context chips: “on this page,” “selected post,” “current user,” etc., to reduce noise.
  • Async sources: search posts/products/users via REST when query length ≥ 2.
  • Undo surface: the last destructive action exposes a one-click revert (if supported).

CommandUI ships these affordances out of the box, with styles that match modern wp-admin.


3) Install + First-Run Checklist

  1. Install/activate the CommandUI plugin.
  2. Hit ⌘K / Ctrl-K in wp-admin—palette opens.
  3. Type “settings” — you’ll see top-level admin pages and common toggles.
  4. Type “new po” — fuzzy search suggests “New Post,” “New Page,” “New Product.”
  5. Hit ? to see built-in shortcuts.
  6. Open Preferences → CommandUI and choose:
    • default hotkey,
    • whether the palette is available on the front-end for logged-in users,
    • which roles can access which command groups,
    • performance mode (pre-index vs on-demand).
  7. Invite one editor to use it for the day. Measure clicks saved and time to task.

4) Writing Commands (PHP + JS)

Commands have three concerns: how they are found, who can run them, and what they do.

4.1 PHP: register a server-side command

// functions.php or a tiny mu-plugin
add_action('commandui_register_commands', function($registry) {
  $registry->register([
    'id'          => 'posts:bulk-publish-drafts',
    'title'       => 'Publish all drafts in category…',
    'group'       => 'Posts',
    'keywords'    => ['publish','draft','bulk','posts'],
    'capability'  => 'edit_others_posts',
    'args'        => [
      ['id' => 'category', 'type' => 'taxonomy', 'taxonomy' => 'category', 'label' => 'Category'],
      ['id' => 'limit',    'type' => 'number',   'label'    => 'Limit', 'default' => 20]
    ],
    'run' => function($args) {
      $q = new WP_Query([
        'post_type'   => 'post',
        'post_status' => 'draft',
        'category__in'=> [(int)$args['category']],
        'posts_per_page' => (int)$args['limit']
      ]);
      $count = 0;
      while($q->have_posts()){ $q->the_post();
        wp_update_post(['ID'=>get_the_ID(),'post_status'=>'publish']);
        $count++;
      }
      wp_reset_postdata();
      return ['message' => "Published {$count} drafts."];
    }
  ]);
});
Enter fullscreen mode Exit fullscreen mode

Notes

  • capability ensures only trusted roles see and run the command.
  • args renders a small, accessible form inside the palette when the command is selected.
  • The run callback returns a message for the confirmation toast and log.

4.2 JS: add a front-end command (Gutenberg/block context)

// enqueue in editor or front-end
window.CommandUI?.registerClientCommand({
  id: 'blocks:wrap-in-group',
  title: 'Wrap selection in Group block',
  keywords: ['group','wrap','block','gutenberg'],
  when: () => wp.data.select('core/block-editor').hasMultiSelection(),
  run: async () => {
    const { getSelectedBlockClientIds, getBlocksByClientId } = wp.data.select('core/block-editor');
    const ids = getSelectedBlockClientIds();
    const blocks = getBlocksByClientId(ids);
    // Simplistic example: replace with a new Group block
    const group = wp.blocks.createBlock('core/group', {}, blocks.map(b => wp.blocks.cloneBlock(b)));
    const { replaceBlocks } = wp.data.dispatch('core/block-editor');
    replaceBlocks(ids, group);
    return { message: `Wrapped ${ids.length} block(s).` };
  }
});
Enter fullscreen mode Exit fullscreen mode

Tips

  • Use when() to conditionally show commands (context-aware palettes feel magical).
  • Avoid long-running operations in the UI thread; prefer async + progress indicator.

5) Fuzzy Search, Ranking, and “Intent Folding”

A palette’s usefulness hinges on results that “feel right.”

  • Fuzzy matching: np should match “New Post” (initials), “New Page,” and even “New Product.” CommandUI’s scorer boosts prefix and acronym matches.
  • Recency bias: recently used commands rise to the top—per user.
  • Capability filtering: never tease commands the user can’t run.
  • Intent folding: one visible command can detect the specific entity and choose a sub-action.
    • Example: “Edit current template” knows whether you’re on a single post, category archive, or product PDP and opens the right editor screen.

You can tune weights via a small filter:

add_filter('commandui_search_weights', function($weights){
  // title has stronger weight; keywords reduced to avoid noisy matches
  return ['title'=>0.6, 'keywords'=>0.2, 'recency'=>0.2];
});
Enter fullscreen mode Exit fullscreen mode

6) Permissions, Capability Checks, and Auditability

Treat commands like endpoints in an API:

  • Visibility: commands are hidden unless the user has the configured capability.
  • Execution: run callbacks should re-check capabilities server-side.
  • Nonce: all client-originated calls must include a nonce; CommandUI signs requests for you.
  • Audit: log “who ran what with which args at what time,” especially for destructive operations.
add_action('commandui_after_run', function($result, $command, $args, $user_id){
  error_log(sprintf(
    '[CommandUI] %s ran %s with %s → %s',
    get_user_by('id',$user_id)->user_login,
    $command['id'],
    json_encode($args),
    json_encode($result)
  ));
}, 10, 4);
Enter fullscreen mode Exit fullscreen mode

7) Navigation Items vs. Verbs

A top mistake is simply mirroring your menu tree. The palette shines when you model user intent:

  • Create: post, page, product, coupon, user
  • Find: post by title/ID/author, recently edited item, last draft
  • Transform: convert classic to blocks, wrap in group, change template, regenerate thumbnails
  • Operate: purge cache, reindex search, toggle maintenance mode, switch theme (staging)
  • Inspect: show current template, list enqueued scripts, show transient count
  • Admin: create backup, export orders, clear scheduled hooks

Think verbs. If a command merely opens “Settings → Reading,” you’re not taking advantage of the palette.


8) Contextual Palettes on the Front-End

You can invoke CommandUI on public pages for logged-in users to manipulate blocks, query data, or navigate to related admin screens.

Examples

  • On a product PDP: “Edit product,” “Duplicate product,” “View orders containing this product,” “Open price history chart.”
  • On a blog post: “Quick fix typos (open Gutenberg),” “Check internal links,” “Promote to homepage hero.”

Enable Front-end availability in preferences and restrict by role (e.g., Editors and Admins only).


9) Performance Budgets

Even a tiny plugin can feel heavy if it loads on every page.

  • LCP target: < 2.5s on typical wp-admin pages.
  • INP: < 200ms for palette open, type, and run.
  • Payload: keep the palette bundle modest; load command sources on demand.
  • Preload only the minimum fonts (ideally none).
  • Defer indexing for large sites until the first command open, then cache for the session.
add_filter('commandui_load_mode', fn() => 'lazy'); // 'eager' for smaller sites
Enter fullscreen mode Exit fullscreen mode

10) Accessibility

If keyboard is your core affordance, you must nail a11y:

  • Focus trap: palette captures focus while open; Esc closes and returns focus.
  • ARIA roles: role="dialog" with aria-label, listbox pattern for results, aria-activedescendant.
  • Screen reader hints: announce search result counts and action confirmation.
  • Contrast: follow WCAG AA for text and selected rows.
  • Reduced motion: respect prefers-reduced-motion on open/close animations.

CommandUI ships compliant defaults; your custom result rows should follow suit.


11) Case Studies

11.1 Newsroom (100+ writers)

  • Commands: “New article from template,” “Open style guide,” “Find image by slug,” “Schedule tweet thread,” “Request copy edit.”
  • Wins: editors never touch the side menu; onboarding time for freelancers falls by 40%.

11.2 WooCommerce store (20k SKUs)

  • Commands: “Change price by %,” “Bulk hide out-of-stock,” “Open product in storefront,” “Refund last order,” “Create coupon for customer.”
  • Wins: operations team cuts repetitive clicks; errors drop due to guarded forms.

11.3 Multi-site agency fleet (60 sites)

  • Commands: “Switch site,” “Open staging,” “Flush cache on current site,” “Sync menus from base,” “Copy block pattern to this site.”
  • Wins: platform team standardizes maintenance with a shared command pack.

12) Recipes: 20 Commands You’ll Actually Use

  1. Find post by ID / slug (autocomplete + open in editor)
  2. Create draft from template (pre-filled blocks)
  3. Bulk change author (selected posts)
  4. Copy internal link (for selected post)
  5. Toggle maintenance mode
  6. Purge object cache + page cache
  7. Regenerate thumbnails (for current media)
  8. Open last error log
  9. List scheduled cron hooks (cancel one)
  10. Reindex site search
  11. Generate share image (featured image + title overlay)
  12. Create coupon (amount + expiry)
  13. Export orders between dates
  14. Duplicate product
  15. Show current template and template parts
  16. Open theme.json editor (for block themes)
  17. Wrap selection in Group block
  18. Convert Classic block to blocks
  19. Fix widows (typography helper)
  20. Start content QA (open checklist with links)

Each recipe is a few lines of registration and an action that calls internal APIs you already trust.


13) Adoption Sprint (14 Days)

  • Day 1: Install CommandUI on staging. Enable for Admin/Editor roles.
  • Day 2: “Core nav” only. Train hotkeys.
  • Day 3–4: Add 5 role-specific commands (Create/Find).
  • Day 5: Add 3 “operate” commands (cache, maintenance, logs).
  • Day 6: Shadow real tasks; log clicks saved.
  • Day 7: Push to production for one team.
  • Day 8–9: Add contextual front-end commands for Editors.
  • Day 10: Introduce 2 Woo ops commands.
  • Day 11: Ship a help overlay (?) explaining hotkeys.
  • Day 12: Remove any noisy commands; tune weights.
  • Day 13: Record a 3-minute screencast; circulate.
  • Day 14: Survey satisfaction; decide what stays in muscle memory.

14) Troubleshooting Matrix

Symptom Likely cause Fix
Palette opens slowly Eager loads sources on big sites Switch to lazy mode; cache index per user
Results feel irrelevant Weighting too high on keywords Tune weights; add intent-specific keywords
Command runs but nothing happens Capability passes on client, fails on server Re-check server capability; confirm nonce
Keyboard focus lost after close Missing focus restore Ensure CommandUI’s close callback restores document.activeElement
Front-end palette visible to subscribers Role scope misconfigured Disable on front-end except for Editor+
Double execution on Enter Event bubbling in custom row event.preventDefault() and stop propagation

15) Micro-copy Library (steal this)

  • Placeholder: “Type an action or page: ‘new post’, ‘purge cache’, ‘settings’”
  • Dangerous confirm: “This clears cached pages. Live users won’t lose data.”
  • Success toast: “Published 12 drafts. Undo”
  • Empty state: “No results. Try fewer words or another verb.”
  • Help link: “Press ? for shortcuts”

16) Final Pre-Launch Checklist

  • [ ] Hotkey chosen and documented in onboarding
  • [ ] Role access and capability checks configured
  • [ ] 10 core commands tested (create/find/operate)
  • [ ] Front-end palette restricted by role and context
  • [ ] Performance: LCP < 2.5s on dashboard, palette open < 100 ms
  • [ ] Accessibility: focus trap, screen reader labels, reduced motion
  • [ ] Audit logs turned on for destructive actions
  • [ ] Short screencast recorded; help overlay linked
  • [ ] Rollback plan (disable plugin) verified

Why CommandUI (and not “just use the menu”)?

Menus are for exploration. Command palettes are for work. CommandUI respects WordPress’ capability model, lets you compose new verbs without inventing a framework, and stays out of your way until you need it. For teams with complex sites, the palette is the shortest path from intent to action.


Sourcing & Version Cadence

When you care about predictable updates and calm rollbacks, standardize your downloads. Many operators rely on gplpal to keep plugin versions consistent across environments so you can focus on building commands, not chasing mismatched zips.


Closing

A fast site is great; a fast workflow is leverage. With CommandUI and a handful of thoughtful commands, WordPress stops feeling like a maze and starts feeling like a tool. Press ⌘K, type what you mean, press Enter—and ship the thing you opened your laptop to do.


Top comments (0)