v0.11.0
The licenses release. The System page grows a full license manager: every paid plugin and theme classified from the vendor's own locally stored state, with paste-to-activate, deactivate and re-verify wired through each vendor's own code and proven against the live licensing services of more than twenty vendors. Around it, the daily-work gaps close (a terms manager, bulk actions for media, comments and users, media captions, post formats, Custom CSS), Settings reorganizes around intent instead of history, and the site's posture becomes glanceable: Minn now warns when the site is hidden from the public and reports firewall, SSL, loopback and REST health at the same glance.
Added
- License visibility: the System page gains a Licenses card listing every paid plugin and theme with a state pill (valid, expired, invalid, missing or unknown), the vendor's expiry where one is stored, and a health check that flags expired or invalid licenses. Everything reads from locally stored vendor state: no network calls, no vendor code execution, so looking can never burn an activation seat. Bundled readers cover Elementor Pro, ACF PRO, WP Rocket, Gravity Forms, Bricks, Divi, Beaver Builder, WPBakery, Brizy, Etch, AnalyticsWP, Avada, Slider Revolution, LayerSlider, Rank Math Pro, Envato Market and the Brainstorm Force family, plus generic Freemius, EDD Software Licensing, SureCart and StellarWP/PUE detection via SDK fingerprints. Third parties join through the
minn_admin_license_providersfilter, the card rolls into the copy report, and rows for inactive components still read their stored license truthfully. - License activation: license rows grow paste-to-activate, deactivate (behind a confirm) and re-verify controls that route through each vendor's own activation code. Guardrails throughout: a pasted key rides one request and is never stored, logged or echoed back; a failed activation is never retried automatically (retries can burn paid seats) and keeps the field in place with the typed key selected for a quick retype; hitting a site limit is named plainly instead of reading as a generic error; controls render only while the vendor's code is loaded; a rejected key never leaves residue (prior key and status are snapshot-restored). Wired vendors, each proven against the live service: Elementor Pro, ACF PRO, WP Rocket, Beaver Builder, Brizy Pro, Etch, Bricks, Divi (username plus API key), Gravity Forms, Gravity SMTP, The Events Calendar family (Events Calendar Pro, Event Tickets Plus, Filter Bar, Community), Kadence Blocks Pro, WPMU DEV, SearchWP, Gravity Perks, GP Premium, Perfmatters, WP All Import Pro, WP All Export Pro, Slider Revolution and LayerSlider. Portal-handshake vendors (WPBakery, Rank Math Pro, Envato Market) get an Activate ↗ link to their own screen instead of a paste field that could not work. Vendors that keep no readable local state (Gravity SMTP, Brizy) show Minn's own last check result with honest wording ("verified 2 hours ago from Minn"). The contract, including multi-secret fields and the tested-vendor table, is documented in
docs/license-manager.mdanddocs/for-plugin-authors.md. - Turn a licensed component back on in place: dimmed rows for inactive plugins and themes carry a small power button (shown only when the file exists and you hold the capability) that activates the component and re-renders the card, revealing its license controls. Themes confirm first, since that switches the site's active theme.
- Terms manager: Manage → Structure covers every REST-enabled taxonomy that organizes public content, with a switcher (categories and tags first), an indented tree for hierarchical taxonomies, inline create and edit (name, slug, parent, description), delete with confirms that say what actually happens, and count links straight into the filtered content list. Merge is the one new primitive: pick a surviving term and every post moves over through core's own reassignment machinery before the source is deleted. Editors get it through their normal
manage_categoriescapability. - Bulk comment moderation: comment rows carry checkboxes with shift-range select and a Select-page control; the selection bar offers the current tab's own verbs (Approve, Spam, Trash, Restore, Delete forever), so a batch can never apply a status the tab doesn't offer.
- Bulk media select and delete: grid tiles and list rows gain checkboxes (hover-revealed on the grid) with shift-click range select and a selection bar. Bulk delete confirms once, then deletes per item so one failure never aborts the rest.
- Media captions and descriptions: the media detail modal now edits Caption and Description alongside title and alt text, fetched lazily so the library list stays light.
- Bulk role change: the users table gains a checkbox column and a bar to change every selected user's role in one action, using the same themed combobox as the rest of the app. Your own account is skipped by the batch, with a note, so you cannot demote yourself mid-batch.
- Per-post format picker: the editor's Settings card offers the post format (aside, gallery, link and the rest) when the active theme declares post-format support, hidden exactly as wp-admin hides it otherwise.
- Custom CSS: Settings gains a Design section editing core's per-theme Additional CSS (the same store the Customizer uses), gated on the
edit_csscapability. Structural validation refuses unbalanced braces or unclosed comments without writing, and a refused save keeps the typed CSS in the editor instead of re-rendering over it. - Site visibility warnings: a site can be silently invisible to the public (a maintenance or coming-soon plugin, a whole-site password gate, or "discourage search engines" left on after launch) and its owner never notices. Minn now detects all of it read-only from local options and says so: an amber Overview banner, a persistent topbar chip on every route, and a System health check that appears only when something is hiding the site. The chip opens a popover with the actual control where Minn can safely flip it (its own maintenance mode, search-engine visibility); third-party gates link out. Bundled detectors: WP Maintenance Mode, SeedProd, Under Construction, Password Protected, WooCommerce coming soon, Elementor maintenance mode, Minn's own maintenance mode and the search-visibility setting; WooCommerce's store-pages-only shape reads as "Partly hidden" rather than claiming the whole site is dark. Third parties register through the
minn_admin_visibility_providersfilter. - Security posture on System: with Wordfence active, health rows report the firewall mode (blocking, learning or off) and the last scan with its unresolved issue count. With Really Simple SSL active, an SSL-enforcement row reports whether the whole site redirects to HTTPS, which the generic HTTPS check cannot prove. The WordPress group also shows the real login URL, honoring login-hider plugins.
- Loopback and REST self-checks: two health rows driven by core's own Site Health tests catch the failure that silently kills cron, scheduled posts and background updates, cached for 15 minutes.
- Autoload and Cron detail modals: the System page's autoload breakdown and cron row (cards and grid rows both) expand into wide modals: every autoloaded option by size, and every scheduled event with its next run, recurrence and overdue highlighting.
- Tools card: deep links to wp-admin's one-shot jobs (Site Health, export and import content, the GDPR personal-data tools), the honest link-out instead of a rebuild.
- Order PDFs: with PDF Invoices & Packing Slips active, the order modal offers a download link per enabled document through the plugin's own endpoint and nonce.
- Switch to this user: with User Switching active, the users row menu gains a switch action riding the plugin's own nonce URL.
- Regenerate thumbnails: with Regenerate Thumbnails active, the media detail modal gains a ↻ Thumbnails action running the plugin's own regenerator server-side.
- SiteSEO in the SEO panel, WP Armour on the Spam page (all-time blocked count from its honeypot, deliberately no toggles) and 301 Redirects (WebFactory) in the Redirects family (list, search, create, edit and delete, with its 404 log kept out of the rule list).
- Theme follows the OS: until you explicitly toggle, Minn now matches the system's light or dark preference and flips live when it changes. An explicit choice still wins forever.
Improved
- Settings reorganized by intent: the historical General/Writing/Reading/Discussion tabs are regrouped by the job you're doing: Site (identity, locale, admin), Visibility (search engines, maintenance mode, membership), Homepage, Content (new-content defaults plus permalinks), Comments (discussion plus spam, because they are the same job) and Design. The section nav is sticky, and a tab that shows settings from more than one save endpoint persists them all in one click.
- Structure page: Post Types, Taxonomies and Terms are three tabs on one Manage page instead of separate nav items, gated individually (an admin sees all three, an editor sees Terms). The taxonomy tab's term counts cross-link into the Terms tab in place.
- System page order and jump bar: Licenses moves up under the health checks (licensing is daily work; PHP info is reference), and a sticky jump bar (Health, Licenses, Debug, System, Extensions, Integrations) smooth-scrolls between sections with a scroll-spy pill.
- Revision browsing: the revision diff modal steps with the left/right arrow keys and header buttons with a position count, so flipping through versions no longer means close, click, reopen.
- Visibility controls update live: toggling maintenance mode or search-engine visibility from Settings, the chip popover or the Overview banner refreshes the banner, chip, Settings page and System health check in the same session, no reload.
Fixed
- Session list showed dead sessions: the profile modal listed expired session tokens core itself filters out, padding the list with rows offering a pointless sign-out, and same-day logins were indistinguishable. Expired tokens are now dropped and each row shows a precise sign-in time.
- Modal comboboxes clipped their options: a dropdown panel inside a modal was cut off at the modal edge (the Add-user role picker lost its lower roles). Panels that would spill now re-anchor to the viewport and flip above when there's no room below; everything that fits is untouched.
- "email · email" user labels: users whose display name is their email (common for imported accounts) showed the value twice in delete, send-email and reassign controls.
- Content shifted sideways between pages: navigating between a tall page and a short one changed the scrollbar's presence and re-centered the content a few pixels left or right. The scrollbar gutter is now reserved app-wide.
- Install-modal drops landed in Media: with Add plugin or Add theme open, a zip dropped a few pixels outside the dropzone uploaded to the media library. Any drop while the installer is open now routes to the installer.
- Integrations card falsely flagged
status: the descriptor validator rejected the documented surfacestatuskey, so a correct adapter (Disembark) read as misdeclared. - Order modal Status block padding: the status controls sat flush against the modal edge.