You’re a Tenant, Not the Owner: 6 Doors in Someone Else’s wp-admin, and How Not to Be a Bad Neighbor
Rules of a Good Neighbor — One Per Hook `admin_init` — move in quietly Don’t run heavy code or checks without a reason — this hook fires on…

Action Hook since 1.5.0
Fires before the admin menu is rendered — register menu pages here
admin_menu is exclusively for add_menu_page() / add_submenu_page() calls; anything else belongs on admin_init.
On every admin page load, after admin_init, before the admin screen renders.
do_action( 'admin_menu' );add_action( 'admin_menu', function() {
add_menu_page( 'My Plugin', 'My Plugin', 'manage_options', 'my-plugin', 'my_plugin_render_page', 'dashicons-admin-generic', 66 );
} );Register a top-level admin page.
Rules of a Good Neighbor — One Per Hook `admin_init` — move in quietly Don’t run heavy code or checks without a reason — this hook fires on…
add_menu_page() must be called on admin_menu, not admin_init or plugins_loaded — those run before the menu system is ready.
Source: wp-admin/menu.php
One session: this hook, then each related_hooks entry. Walk it and tell us what to change.
admin_menu → admin_init
Practice the admin_menu WordPress action hook in our interactive sandbox — a VS Code-style editor with a step-by-step admin_menu tutorial, add_action exercises, and instant feedback. No local WordPress install required.