v0.18.0
The depth release. Plugin surfaces stop being flat lists: detail modals gain typed rows (status pills, code blocks, key-value tables and the real HTML email in a fully sandboxed preview), status cards spread across the whole mail, redirects and snippets families, and columns become sortable where a route supports it. The media library grows up in one cycle: folders from your folder plugin, an Unattached filter and month picker, an Attached-to jump, and replace-file in place through Enable Media Replace. The editor sidebar reaches events, job listings and podcast episodes with panels drawn live from each plugin's own schema, Gravity Forms feeds and FluentSMTP settings come inside, and four more providers join the families (SureForms, SureMails, Site Mailer, All-In-One Security). Underneath it all, a sequential full-suite runner drove all 171 suites green before this release and caught four real bugs, fixed below.
Added
- Event details, editable in Minn: with The Events Calendar active, events gain an Event details panel in the editor sidebar: start and end, all-day, venue, organizer, cost and website. Venue and organizer are live search pickers over your existing TEC records, and every write goes through TEC's own save machinery, so durations, timezones and linked-post bookkeeping behave exactly as on its screens. Events with several organizers keep that field on TEC's screen rather than silently dropping any; recurrence and tickets stay in TEC too.
- Plugin panels can offer search pickers: the editor-panel contract gains a
suggestfield type, an async picker that searches a route you provide as the user types (with a built-in None row for clearing). Documented in the author guide; the Events Calendar venue picker is the reference. - Job listings, editable in Minn: with WP Job Manager active, listings gain a Job listing panel in the editor sidebar covering location, the company fields, the application email or URL, salary, the remote, filled and featured flags, and the expiry date. The field list comes live from WP Job Manager's own schema (add-ons and site customizations included), and every write runs through its own per-field sanitizers.
- PowerPress episodes too: with PowerPress active, plain posts gain the same Podcast episode panel for the default channel: media file URL, file size, duration, subtitle, and the Apple episode fields (title, number, season, type). Edits rebuild PowerPress's enclosure data carefully, so hosting, chapter and artwork details it stores alongside survive untouched, and clearing the URL removes the episode exactly like its own Remove control. Custom channels, artwork, explicit flags and chapters stay on the PowerPress metabox.
- Podcast episodes, editable in Minn: with Seriously Simple Podcasting active, episodes already live in Minn's Content list and editor (they are a normal post type), and the editor sidebar gains a Podcast episode panel with the whole episode-detail estate: the media file URL, audio or video type, duration and file size, date recorded, the explicit and directory-block flags, and the iTunes fields. The panel reads its field list live from SSP's own schema (so a site with iTunes fields turned off sees fewer fields) and stores values exactly as SSP does; the cover-image uploader and Castos hosting sync stay on SSP's screen.
- Gravity Forms feeds at a glance: with any feed add-on installed (Twilio, Mailchimp, Zapier, webhooks and the rest), the Forms surface gains a Feeds view listing every integration across your forms: which add-on, which form, on or off. Turn a feed on or off or delete it right there through Gravity Forms' own model; configuring a feed deep-links to the add-on's screen, where its credentials and builders live.
- FluentSMTP settings, without the wizard: the FluentSMTP Email surface gains a Settings view for the choices that actually change day to day: the default and fallback connection (picked from your configured connections; credentials never leave FluentSMTP), email logging, log retention, and email simulation for staging sites (locked when a wp-config constant forces it). Everything reads and writes through FluentSMTP's own settings model; setting up a new connection stays in its wizard.
- Media folders, from your folder plugin: with FileBird, Real Media Library or Folders by Premio active, the Media view gains a folder picker listing your folders (with counts, children indented, plus each plugin's own no-folder view) and filters the library to the picked folder while search, type tabs and pagination keep working. Everything reads through each plugin's own model or API, so FileBird's per-user folders mode is honored and counts match their screens; organizing stays in the plugin's UI. Other folder plugins can join through the new
minn_admin_media_foldersprovider filter, documented in the author guide; very large folders honestly show their newest 500 files and say so. - Move to folder: select files in the media library and the bulk bar offers a folder picker and a Move button (with "no folder" as a real destination). The move runs through the folder plugin's own assign machinery, so its hooks, counters and per-user scoping all apply; providers opt in with a single
movecallable on the same filter. - The media buttons work with more plugins: the SVG filter tab and detail note now come from Safe SVG or SVG Support (the note names the plugin, and claims sanitization only where it is certain), and the ↻ Thumbnails button works through Force Regenerate Thumbnails when Regenerate Thumbnails is not installed, calling FRT's own handler so its delete-stale-files behavior applies exactly as on its Tools screen.
- Media filters that answer the two daily questions: an Unattached filter shows the files no post or page claims (core's own parent query, ready for a cleanup pass), and a month picker lists exactly the months that hold uploads, with counts, so "that screenshot from May" is two clicks. Both keep the toolbar painted while the list reloads, and the media toolbar moves to the same two-row layout as Content.
- Every file says where it lives: the media detail modal gains an Attached to row naming the post or page the file was uploaded to, and clicking it drops you straight into that post's editor. Files nothing claims read Unattached, plainly.
- Replace a file in place: with Enable Media Replace active, the media detail modal gains a ⇅ Replace file button. The new upload goes through EMR's own replace machinery: the old file and its thumbnails are removed, the new file lands under the same name and URL (so every post, theme and hotlink reference keeps working), metadata and thumbnails are rebuilt, and EMR's hooks fire for other plugins. Minn enforces the honest constraint of in-place replacement (the new file must be the same type); renaming or moving the file stays on EMR's own screen. Capabilities mirror EMR exactly, including a wp-config
EMR_CAPABILITYoverride. - Status cards across the whole redirects family: Safe Redirect Manager (rules, status-code mix, regex count), Simple 301 Redirects (rule count and the wildcard toggle) and 301 Redirects by WebFactory (rules, lifetime hits, top redirect, 404 log size) join Redirection with an at-a-glance card, each read from the plugin's own storage.
- Status cards across the whole snippets family: WPCode, FluentSnippets, Custom CSS & JS and Header Footer Code Manager each open with the same at-a-glance card as Code Snippets: active and inactive counts plus each store's own facts (running types or languages, the last change, FluentSnippets' file-based storage note).
- Code Snippets status card: the Snippets surface opens with active, inactive and trashed counts, the scopes currently running, the most recent change, and a warning row whenever safe mode is armed (safe mode means nothing executes, which deserves saying out loud).
- SureForms entries join the Forms surface: submissions read from SureForms' own table, with per-form tabs, unread/read/trash filtering and bulk status changes, search, an entry contact card, and a status card of unread and total counts.
- Two more email loggers: SureMails and Site Mailer: both join the Email family reading their own free log tables, with sent/failed tabs, search, single and bulk delete, a status card with a 14-day chart, and the sections detail (status pill, the real HTML body in the sandboxed preview). Timestamps are normalized to UTC no matter what timezone the database runs in.
- All-In-One Security joins the Activity Log: its audit feed reads from AIOS's own log table as a fifth activity-log provider, with level tabs (warnings, errors, info), search, per-event detail (the JSON context flattened into readable fields) and a status card counting 24-hour, 7-day and all-time events plus recent warnings.
- Sortable columns on plugin surfaces: a collection can declare
sortQuery(anorderby/directiontemplate) and mark columns with the sort token its route understands. Marked headers become clickable: numeric and date columns start descending, everything else ascending, and a repeat click flips. The Redirects surface is the first consumer, sorting by source, hits and last hit through Redirection's own API. - Redirection status card: the Redirects surface opens with rule counts, all-time hits, the top redirect, served and 404 counts for the log window, and a stacked 14-day chart of redirects served over 404s, all read from Redirection's own tables.
- The whole mail family opens rich detail: FluentSMTP, Post SMTP and WP Mail Logging log details moved to the new sections layout alongside Gravity SMTP: a status pill, the real HTML email body in the sandboxed preview (plain-text bodies as a code block), and each store's own extras (FluentSMTP's provider-reply peek, Post SMTP's failure text and suggested fix, WP Mail Logging's raw headers). The flat detail routes stay for API consumers.
- Detail row types for plugin surfaces: a
sectionsRouteresponse row can now declaretype: pill(the shared status vocabulary),code(escaped monospace block),html-preview(your HTML in a fully sandboxed iframe, no scripts, opaque origin) orkv-table(a two-column table from an object map or pair list), alongside the existingurlandemaillink rows. Values stay escaped everywhere; the sandbox is the one place plugin markup renders. Gravity SMTP's log detail is the first consumer: delivery facts with a status pill, the real HTML email body rendered safely, and the stored headers as a table.
Improved
- The System theme glyph is a half-circle now: the theme toggle's System state wore a monitor icon, which read as "view the site" rather than "follow the OS". It wears the conventional half-filled circle instead; Light and Dark keep the sun and moon.
- A full-suite runner ships with the repo:
tests/run-all.shruns all 171 Playwright suites sequentially with settle guards, a one-retry rule for environment noise, per-suite logs and resume support, so a release pre-flight (or an overnight run) is one command.
Fixed
- The block picker no longer waits on the slowest design library: it used to hold the whole dialog on every design and pattern source before rendering anything, so one slow or unreachable CDN left it stuck on the loading screen. It opens instantly with the basics now, and each design library and pattern group fills in as its source answers; a dead source just never arrives.
- The Overview traffic chart dropped today's visitors before noon UTC: the chart bucketed provider days against a noon-UTC anchor, so for half of every day the current day computed as "in the future" and vanished from the chart (and a bar's drill-down could land on the wrong day). Days are bucketed by calendar distance now, in the site's timezone.
- Gravity SMTP's Resend button vanished from the log detail: the new sections-based detail no longer feeds the full event back to the modal, and the list route never carried the resend permission its
when-gate read, so the button silently disappeared. The list route carries it now. - A failed license activation could eat the typed key: the Licenses tab was the one list still missing the soft-reload guard, so a stray re-render during the tab's refresh window could detach the activation form mid-flight, typed key and all. It keeps the form (and the key) through the refresh now.