A modern PHP engine.
Built from scratch.
Minn fluently speaks with WordPress sites: the same database, the same file layout, the same REST API and WP-CLI verbs. Hosting tools, backups, migrations, and plugins keep working. The code underneath is new, small, and yours to read.
Minn\ namespace. A clean-room reimplementationStart with Minn Admin today. Installing Minn comes later.
Minn Admin is a plugin for WordPress sites: a reimagined admin served at /minn-admin/ on the site you have right now. On WordPress software, classic wp-admin stays as a fallback. On Minn there is no wp-admin: Minn Admin is the admin. Everything you learn there carries over unchanged.
- Install it like any plugin. Free, MIT licensed, no build step, no Pro tier.
- Live in it. Content, media, comments, users, settings, and more than a hundred plugin adapters that appear on their own.
- Nothing to relearn. When Minn is ready for your site, the admin you already use comes with it.
/wp-admin/.in progressA strangler fig, not a big bang. Each phase is earned by suites, not declared.
WordPress is not only software.
It is a coordination standard.
WordPress software remains the dominant web platform because customers, hosts, developers, and now AI agents all coordinate there. The portable unit of site, the frozen schema, the REST API, and the labor pool are the product. The PHP is one implementation of those contracts. Here is what that coordination actually consists of, ranked by how much it matters.
A portable unit of site
Files plus a database dump, runnable on any PHP host on earth. Backup, migration, staging, and whole fleet-management stacks exist because the unit is standard.
A stable data contract
The posts, postmeta, options, and users schema has not meaningfully changed in twenty years. Backward compatibility is the actual product.
An operational surface
WP-CLI, the REST API, the file layout, the config conventions. The layer hosts automate against; the layer that makes hosting WordPress sites an industry.
A labor pool
Any freelancer can inherit any WordPress site cold. Choosing a WordPress site is choosing to never be hostage to whoever built it. The customer-control argument is the strongest one.
The plugin ecosystem
The weakest leg now, and weakening: AI erodes the long tail. What it does not erode is what a top-tier plugin really is, a maintenance liability transferred to a vendor who ships security releases.
The AI shift sharpens the thesis. When anyone can generate anything on any platform, the rational customer targets the platform where generated work stays portable, inheritable, and operable after the developer leaves. Today that is a WordPress site, because of legs one through four. The question is whether those legs require the WordPress codebase at all.
Every challenger replaced the software and abandoned the contracts.
Ghost, Craft, Statamic, October: none of them dented WordPress, and they all failed the same way. Each replaced the code, which was never the moat, and walked away from the contracts, which were. A clean break means starting over on portability, tooling, hosting support, and the labor pool at once. No product is good enough to win four moats simultaneously.
You do not ask the world to move. You inherit it through compatibility.
Not “a better CMS”. Nginx against Apache. MariaDB against MySQL. FrankenPHP against PHP-FPM. A from-scratch engine that speaks the incumbent’s interface so precisely that the surrounding infrastructure cannot tell. That is the play.
Two tiers of compatibility, with a hard line between them.
WordPress speaks to three audiences. Minn answers two. The operational contract is sacred. The runtime plugins call into is reimplemented, clean-room, the way Wine speaks Win32. Humans never go through /wp-admin/: Minn Admin is the only UI.
Hosts, backups, CLI.
The schema, the file layout, wp/v2, WP-CLI, feeds, sitemaps, cookies. Kinsta and CaptainCore cannot tell.
wp_*tables, untouchedwp-config.php- REST, WP-CLI, probes, login cookies
Unmodified plugins load.
Hooks, options, WP_Query, $wpdb. A site owner does not want ported plugins. They want their plugins.
- Clean-room runtime, symbol-gated
- Front end and data. Not a settings screen.
No /wp-admin/.
List tables, meta boxes, the dashboard, the Customizer, Gutenberg-as-an-app: not a Minn surface. Minn Admin is the only UI.
/wp-admin/302s to/minn-admin/- Plugin settings screens are not coming
Browse the lexicon for every family: Speak, Hear, and Mute, sourced from the markdown agents read.
Indistinguishable at the seams.
- The database schema. Real
wp_*tables, read and written, tolerating serialized-PHP blobs forever. - File layout and
wp-config.phpshape, so backup and migration tooling just works. The engine boots from the file WordPress generated, untouched. wp/v2REST core routes: posts, pages, media, users, terms, comments, settings, revisions, search, plugins.- WP-CLI verbs for the ops core:
option,user,plugin,theme,db,search-replace, and thewp-cli.ymlthat routes them. - Permalinks, feeds, sitemaps, block rendering, block themes. Login, sessions, cookies, and nonces the hosting layer probes, cross-accepted in both directions.
Plugins just work. Layer by layer.
A site owner does not want ported plugins, they want their plugins. So the engine implements the functions plugin code calls: the hook engine, the content and options API, admin registrations (not screens), the editor globals. Loaded from active_plugins, unmodified. Every function’s signature is checked against an inventory reflected from the reference; every behavior is a captured probe.
$wpdbmost of itadd_menu_page records. Nothing is rendered. /wp-admin/ redirects.doneDefinition of done, phase one
Kinsta, CaptainCore, Disembark, and UpdraftPlus operate the site the way they operate a WordPress site. Backups restore, migrations round-trip, WP-CLI automation runs, monitors stay green, and Minn Admin boots unmodified. That sentence is the whole spec.
Capture from the oracle. Implement from the capture. Never from the source.
A parked copy of WordPress runs against the same database as the engine. It is the oracle: every behavior is observed there, recorded as a fixture, implemented from that record, and then diffed live, request by request. WordPress source is never opened while engine code is written.
Capture
Boot the reference on the shared database. Curl the exact response, run the exact CLI verb, record it under contracts/fixtures/. Observed behavior is data.
Implement
Write the engine from the fixture and the behavioral note. Interface names (routes, columns, keys, verbs) match exactly; every implementation line is original.
Prove two ways
A fixture suite pins the captured shape and runs anywhere. A live parity suite diffs the engine against the running reference. Any divergence is a finding, not a flake.
Record the contract
Every oracle-learned fact and every honest gap lands in contracts/*.md, machine-checkable and agent-legible. The contract is the product.
# what a milestone looks like $ cd wp-reference && php -S 127.0.0.1:8123 router.php # the oracle $ php tests/theme.test.php ok / matches fixture ok / matches the reference body ok /hello-world/ matches fixture ok /category/uncategorized/ matches the reference body … 28 passed, 0 failed $ php tests/rest-parity.test.php ok GET /wp/v2/posts?context=edit engine == reference ok GET /wp/v2/types _fields quirk reproduced 26 passed, 0 failed
Agent-first is a build method, not a feature
Nobody had done the ops-compatible rewrite because it is an enormous amount of boring, well-specified work. That is precisely what coding agents do well when gated by suites. Every unit ships with a behavioral suite; the suites, not the prose, are ground truth.
Security by declaration
A route’s capability requirement is metadata on the route, mechanically auditable and diffable across releases. Prepared statements only. No unserialize() of untrusted data, ever: serialized blobs are read by tolerant parsers, never executed.
Agent legibility answers the turnover argument
The take-over story for a customer stops being “find another WordPress freelancer” and becomes “point any coding agent at the contracts”.
Facts no documentation would have surfaced.
substr($hash, -4)Modern $wp$ bcrypt hashes derive the auth-cookie key from the last four characters of the hash, not the legacy phpass window. Everything else verifies; only the HMAC fails. Found by brute-forcing the fragment window.
6'2" → 6’2″Texturize turns a digit-apostrophe into a curly quote but a digit-double-quote into a double prime, and skips pre, code, kbd, style, and script.
?_fields=name → []On wp/v2/types the associative payload is filtered whole, so any _fields value yields an empty array. The engine reproduces the quirk by construction.
term_taxonomy.countStored, and trusted on read. Every write that changes a term’s published total has to recount or the stale number leaks into every list response.
401 vs 403A bad cookie is rest_not_logged_in; a bad nonce is rest_cookie_invalid_nonce. Cross-acceptance is byte-identical in both directions: a session WordPress minted works on Minn, and one Minn minted works on WordPress.
perm=editableWith more than one post type, the “editable” query restricts every status to the caller’s own posts, admins included. The activity feed depends on that observed behavior.
Can a WordPress-compatible engine be MIT? Yes.
GPL obligations attach to distributing WordPress’s code or derivative works of it. Minn distributes neither. Compatibility is not derivation. Copyright never protects a procedure, system, or method of operation (17 U.S.C. §102(b)); interfaces, schemas, and protocols are exactly that, and where a compatible route must be named /wp/v2/posts, the expression merges with the idea.
- Google v. Oracle (2021): reimplementing an API surface for a new platform was fair use.
- Lotus v. Borland, Sega v. Accolade, Sony v. Connectix: command hierarchies are methods of operation; reverse engineering for compatibility is fair use.
- In practice: Wine reimplements Win32, Samba reimplements SMB, FerretDB speaks MongoDB under Apache 2.0, and WP-CLI itself is MIT at the heart of the GPL ecosystem.
- Fork versus reimplementation is the whole question. ClassicPress kept the contracts and stayed a fork: the license came with the tree, so it is GPL forever. A reimplementation written from specifications of behavior is a new work, and its author chooses the license.
What would actually cause a problem.
- Copied code, including mechanically transformed code. Minn’s predecessor generated its build from WordPress’s own source; that output was a derivative work and could never have been MIT. This is the cautionary tale the whole method is built around.
- Bundled GPL assets. No core JavaScript, no block-library CSS, no bundled themes, no Dashicons ship in the engine. The block stylesheet you are looking at is Minn’s own.
- Trademark, not copyright, is the live wire. “WordPress” appears only to identify the software and sites Minn is compatible with, never in the project name or domain.
The hygiene program: spec-first development from fixtures captured on a live instance, implementation from the spec and never the source, a similarity gate against the WordPress tree, tracked provenance for every file, and an hour with an open-source-savvy IP lawyer before the runtime milestone ships. This page is analysis, not legal advice.
What works today, and what does not.
The engine boots from an unmodified wp-config.php, serves a database WordPress software created, and is written from scratch with only the code it needs to be compatible with WordPress sites. A real site (a client site cloned with the engine swapped in) renders at parity with its parked WordPress software, element by element, in a browser.
Compare the code size: WordPress core next to Minn with Minn Admin, measured from the release zip the same way on both sides and refreshed at each release.
Working, pinned by suites
- A visitor can read the site. Permalinks, hierarchies, archives, search, pagination, redirects, 404s: 93 URL shapes at parity.
- Block themes render as data. Templates, parts, patterns, site-editor overrides, theme.json to CSS with presets byte-identical, and a geometry suite that measures every visible element against the reference in Chrome.
- Classic PHP themes run. Template hierarchy,
wp_headdefaults, and live body parity against the reference. Proven on a real site that still uses PHP templates. - The admin half.
wp/v2posts, pages, media, users, terms, comments, settings, revisions, autosaves, locks, search, plugins. Minn Admin boots and every view answers. - Auth, both directions. Cookies, sessions, nonces, capabilities,
wp-login.php, password reset, sign-in throttling, application passwords. - The probe surface. Feeds byte for byte, sitemaps, robots, cron, mail, the REST index, the version file tooling parses.
- WP-CLI on Minn, and a one-command
minn install/ejectthat swaps a WordPress webroot over and back, byte for byte. - Plugins load as code. 1,687 runtime functions checked against the inventory; on a production site cloned onto the engine, 24 of 25 plugins run unmodified, and a second 48-plugin clone loads everything but one.
Not yet, said plainly
- No
/wp-admin/. Plugin settings screens are not coming. If a plugin only has a wp-admin page, Minn Admin covers it with an adapter, or that page does not exist on the engine. - No block editor globals. Editor-side plugin scripts have nothing to attach to.
- Commerce is not the target slice. WooCommerce boots in the lab; a store needs far more than booting. Brochure, forms, and content sites come first.
- Multisite, XML-RPC, the customizer, the upgrader: the long tail, by fatal count.
- The engine’s own strings are English only for now; the app already speaks your language.
- Not on GitHub yet. The source opens with the first tagged cut. Until then, Minn Admin is the public piece.
Serialized PHP is forever
Reading real WordPress databases means tolerating serialized blobs in options and postmeta indefinitely. Greenfield sites keep it out of new data; migrated sites drag the long tail in.
The runtime is the long road
Front-end plugins work once hooks and the content API exist. A plugin’s own settings screen is never hosted: Minn Admin adapters own that UI. Editor plugins need the editor globals. “Any plugin” means front end and data, reached layer by layer, not declared.
Commerce comes last
A large share of real small-business sites are brochure, forms, and content. That slice is exactly what is tractable, and it is the slice the engine targets first. WooCommerce booting in the lab is a milestone, not a green light.
Bus factor
The customer-control argument only transfers once someone other than the founder can maintain the engine. MIT, machine-readable contracts, and exhaustive suites are the mitigation.
Things people ask first.
What is Minn, and what is Minn Engine?
Minn is the project: this site, what you install, the product. Minn Engine is the developer name for the runtime, the way people say WordPress core. Minn Admin is the interface, a plugin that already runs on WordPress and on Minn.
Is this a fork of WordPress?
No. Minn is written completely from scratch, with only the minimal amount of code needed to be compatible with WordPress sites. That is what makes the MIT license possible; a fork would be GPL forever.
Will my plugins work?
Increasingly, on the front end and in data. The engine reimplements the runtime plugins call into, clean-room, and loads them unmodified behind a symbol gate: a plugin that calls a function the runtime lacks is skipped with the reason rather than fataled. A plugin’s own wp-admin settings screen is not hosted. Minn Admin covers that job with an adapter, or that page does not exist on the engine.
Will my host notice?
That is the definition of done, and the point. The webroot keeps index.php, wp-config.php, wp-settings.php, wp-includes/version.php, and wp-content/ exactly where tooling expects them, and wp/v2, feeds, sitemaps, and wp-cron.php answer the way monitors and backup tools probe them. /wp-admin/ redirects to Minn Admin: there is no wp-admin UI. Real fleet tooling is run against a real site until those tools operate it the same way they operate a WordPress site.
Can I go back?
Yes, in one command. minn eject restores the parked WordPress files byte for byte. Nothing is written to your database that WordPress would not have written itself.
Why PHP?
Because the moat being inherited is PHP hosting. Modern PHP on FrankenPHP-class runtimes is fast, and the infrastructure already speaks it. Modern PHP, 8.3 minimum, no framework, no build step, no dependencies.
Where is the admin?
Minn Admin, a plugin for WordPress sites, is the interface. It boots on the engine unmodified because it never touched wp-admin internals in the first place. On WordPress software, classic wp-admin stays as a fallback. On the engine there is no wp-admin: Minn Admin is the admin. It speaks wp/v2 plus its own namespace, and it works on the WordPress site you have today. Start there.
Where is the source?
The engine is developed in the open on a local repository and opens on GitHub with its first tagged cut. Minn Admin’s source is public now, and its contracts are the same ones the engine serves.
A second engine for WordPress sites.
Try Minn Admin on the site you have today. When 100% of what you do happens in /minn-admin/, consider an engine swap with Minn.