WordPress Wants a Real Secrets API in 7.2. Plugins Still Dump Keys in wp-config.

WordPress still does not have a type called "secret."
That sounds like a nit until you look at a real wp_options dump. Stripe keys, SMTP passwords, Google tokens, OpenAI keys, webhook signing secrets — sitting next to the site tagline, autoload sometimes on, copied into every backup, every staging clone, every "can you send me a DB so I can reproduce." Eric Mann's Make/Core proposal (August 25, 2026) says this is not a morality play about plugin authors. It is the only API they were given.
The title of this post mentions wp-config because that is the other drawer. Agencies that got burned once moved keys into define( 'STRIPE_SECRET', '...' ) or into host env. That is better than a plaintext option. It is still not inventory, rotation, or an audit trail. It is a PHP file that gets copied into git if someone is sloppy, and never copied if someone is careful, with no middle.
7.2 is being asked to grow a small, encrypted, filter-hostile API. No settings screen in this release. WP-CLI in this release. Hosts already arguing in the comments. That combination is more interesting than a merge announcement.
The Options Table Is a Credential Dump
How we got here
add_option / update_option is how WordPress stores almost everything that isn't a post. Plugin settings UIs write strings. There is no update_secret(). So the Stripe secret is a string. The tagline is a string. Backup plugins copy strings. wp option get stripe_secret_key prints a string in a shared terminal.
Mann's post is explicit: this was survivable when the average site had a Mailchimp key and a reCAPTCHA secret. Model-provider keys are metered spend. A leak is not just embarrassment. It is someone else's invoice.
What "plugins dump keys in wp-config" actually means
Two bad patterns live side by side:
- Settings page →
update_option( 'my_api_key', $raw ). - README: "paste your key into
wp-config.php."
The second is often sold as the secure pattern. Delicious Brains' Connectors writeup (WordPress 7.0 era) still ranks environment variables first, PHP constants second, database options last. For Connectors, env short-circuits the DB lookup so the raw key is not read from wp_options. That is a host- and ops-shaped fix. It does not give plugin authors a core object. It also does not help the long tail of Woo gateways and SMTP plugins that never read env.
wp-config.php keys have their own failure mode: they travel with the filesystem. Database dumps stop including them. Git history might start including them. Neither layer has rotation semantics.
Independent encryption is not a platform
Site Kit encrypts Google credentials. Woo gateways handle payment keys. SMTP plugins hold mail passwords. Each is a cipher, a key-derivation story, and an incident report waiting for a unique bug. Mann's point: none of them can be reviewed once on behalf of the ecosystem. A core API is the review surface.
A proof-of-concept has been floating for about six months, originally after Two Factor / TOTP token discussions, later overlapping the AI plugin's key-encryption experiment (Jeffrey Paul noted that in comments). The wp_ names in the proposal are proposed, not shipping.
What the Proposal Actually Is
Four functions and a value object
wp_set_secret( string $name, string $value ): bool|WP_Error
wp_get_secret( string $name, string $version = WP_Secret_Version::CURRENT ): WP_Secret|null|WP_Error
wp_delete_secret( string $name ): bool|WP_Error
wp_import_option_as_secret( string $option, string $name ): bool|WP_Error
WP_Secret::reveal(): string
WP_Secret::fingerprint(): string
Call site from the proposal:
wp_set_secret( 'my-plugin/api-key', $key_from_form );
$secret = wp_get_secret( 'my-plugin/api-key' );
if ( is_wp_error( $secret ) ) {
// Exists, but unusable. Key material changed. Tell the user.
} elseif ( null === $secret ) {
// Doesn't exist. Show the connect flow.
} else {
$client = new API_Client( $secret->reveal() );
}
Three return shapes on get: object, null, WP_Error. Collapsing "missing" and "cannot decrypt" into false is how you re-run onboarding when the real problem is a rotated salt. That distinction is doing more work than the function count suggests.
Namespaces by convention
plugin-slug/secret-name. Future admin UI can group. Cross-plugin reads are not cryptographically denied. Mann says slugs are not authentication. A malicious plugin that can run PHP can wp_get_secret( 'woocommerce/...' ) as easily as it can read DB_PASSWORD. The API is not a sandbox.
Default storage is still the options table
Ciphertext blobs, autoload=no, excluded from options.php and the REST settings endpoint. Same idea as object cache versus options: default substrate, replaceable. If you expected Vault-by-default on a $5 VPS, you misread the audience. The audience is "stop writing plaintext into the same table as the tagline."
Capabilities: manage_secrets and manage_network_secrets. A change hook on write carries actor, timestamp, old and new fingerprints. Fingerprints are loggable. Values are not.
Encryption Is Not Optional
Envelope, not a WP_ENCRYPT_OPTIONS constant
Per-secret data key, wrapped by a master key. No plaintext mode. Mann's line: an API that can be configured to store plaintext is an options API with a misleading name.
The objection is data loss. Rotate salts, migrate hosts, secrets stop decrypting. Plaintext options never do that. Envelope encryption is the answer they want: rotate wrapping without rewriting every blob. Preferred key source is a dedicated constant (WP_SECRETS_KEY in secondary writeups). Fallback derived from LOGGED_IN_KEY / LOGGED_IN_SALT for sites that cannot set a constant. Site Kit already ships a version of that fallback and documents that salt rotation breaks stored credentials. The ecosystem lived with the docs instead of rejecting encryption.
When key material is gone: Site Health should report undecryptable secrets. Recovery is re-enter. Nothing silently becomes ''.
libsodium has been bundled since PHP 7.2. WordPress still has sodium_compat when the extension is disabled. No new PECL story.
What a stolen dump becomes
In scope, from the proposal: database dumps, backups in object storage, SQL injection reading wp_options, options.php, export files, screenshots, debug logs, a compromised read-only replica.
Out of scope: RCE in the WordPress process. If they can run PHP, they can reveal(). Masking in var_dump and logs is shoulder-surfing hygiene, not a privilege boundary. WP_Secret refuses serialization so it does not fall into a shared persistent object cache on cheap hosting.
No export. Staging does not get a "download all secrets" button. Fingerprints let you confirm a re-entered value matches. Migrations mean re-entry at the destination. That will annoy agencies who clone prod to staging with one command. It is also the point.
No Filter on the Retrieval Path
Why this will get pushback
WordPress extends by filters. A wp_get_secret filter would receive every credential in plaintext. Any plugin could register it. Mann expects this to be the loudest objection. Providers replace that flexibility: you swap storage or keyring, you do not intercept reveal.
If you were planning to "log secret access" via a filter that receives the string, you will need the write hook and fingerprints instead, or an observer that does not see plaintext. That is stricter than the rest of core. Good.
Fail closed
Unreachable external store or key backend: reads and writes error. No fallback to local wrapping. Fail open would be the first incident report.
The Drop-In Hosts Already Hate
secrets.php: storage versus keyring
Two extension points, independently replaceable:
- Where ciphertext lives (Vault, Parameter Store, host API)
- What wraps the master key (KMS, HSM)
Neither is handed plaintext. Neither can turn encryption off.
That last pair of sentences is the fight in the comments.
Pantheon (Chris Reynolds, August 25)
They have run an external secrets store in production since 2024 (GA to all customers earlier in 2026). Application role is read-only. Writes go through Terminus or the dashboard. Typical Vault posture.
Gaps they named:
- No way to express "readable here, not writable here." Every plugin settings screen assumes
set()works. - Platform stores often are the encryption boundary. They need plaintext over an authenticated channel so the same secret works in other environments. If the drop-in only sees WordPress ciphertext, they double-encrypt and the value is opaque outside WP.
Altis (Ryan McCue, August 27)
-1 on the proposal as written. Their store is Parameter Store / HSM-backed. WordPress must not hold wrapping keys. API today is get_secret( string $key ): string and that's it. If encryption happens above the provider, he asked what this is besides encrypted options.
Kaspars (August 29) tried to split the baby: standardized encrypted options for normal installs; hosts noop the setter and return WP_Error with platform instructions. Encryption key in the same PHP process as the ciphertext is not ideal. It is still better than plaintext.
This is not a bikeshed. It is whether 7.2 is a shared-hosting hardening API, a host-integration API, or both. Mann asked hosts to say what the drop-in is missing before freeze. They did.
Two Version Slots and Import, Not Migrate
CURRENT and PREVIOUS
Not unbounded history. Overwrite keeps the old value so a mistyped key is recoverable and in-flight requests can finish. Retiring PREVIOUS is an operator action. No cron guessing when Stripe has drained the old key.
Native enums need PHP 8.1. Core's minimum is still 7.4, even if 8.3+ is recommended. String constants on a final class WP_Secret_Version are the portable stand-in.
Named history of every credential ever held would live in backups forever. Two slots is the product decision.
wp_import_option_as_secret()
No automatic sweep. Core cannot tell a Stripe key from a widget setting. Plugin authors move one option, on purpose, on their upgrade schedule. Imported secrets are flagged for rotation because the plaintext is already in every backup you own. Encrypting in place without rotation is theater.
function myplugin_upgrade_320( string $old, string $new ): void {
if ( version_compare( $old, '3.2.0', '<' ) ) {
$r = wp_import_option_as_secret( 'myplugin_api_key', 'myplugin/api-key' );
if ( is_wp_error( $r ) ) {
// leave the option; show an admin notice
return;
}
delete_option( 'myplugin_api_key' );
// Site Health / plugin UI: rotate, because backups still have plaintext
}
}
Do not delete_option until you know get works. Do not skip the rotation flag in the UX. The proposal treats rotation as the actual fix.
Multisite Is in v0
Network-level secrets exist. Salts are network-wide, so separate option rows would be logical separation only. They want per-site subkeys via sodium_crypto_kdf_derive_from_key() from a network root key. Site and network APIs are separate functions, separate capabilities, no implicit fallback.
Adding this later means a second key hierarchy and a migration. Doing it now means rotating a network wrapping key re-wraps one value, not 500 sites independently.
If you run a 500-site network and keep putting the same SendGrid key in each site's options, the API is offering you a network secret. Use it. If each site has a different Stripe account, don't.
WP-CLI In, Admin UI Out
Why CLI is in 7.2
First-party consumer in the same release. The fastest way to find out the API is awkward. Also closes a real leak: wp option update my_key sk-live-... lands in shell history and ps on shared hosts. Reading and writing through the secrets API is the same change as "don't argv the credential."
Exact command names are still feedback-wanted. Expect something in the shape of set/get/delete/list with fingerprints, not values, on list.
# speculative shape — not frozen
wp secret set myplugin/api-key --from-file=./key.txt
wp secret fingerprint myplugin/api-key
wp secret delete myplugin/api-key --retire-previous
--from-file is the habit you want even before core ships. Never paste live keys into bash.
Why the screen waits for 7.3
Storage and retrieval have to be right once. Every plugin and every future screen inherit them. Designing a UI on a moving API is how you get two migration stories. Mann would rather slip the whole API to 7.3 than freeze a bad surface for Beta 1.
Connectors security audit is named as a requirement this API helps. Connectors already have a settings UI that stores plaintext unless you override with env. A 7.3 screen that lists secrets, fingerprints, last rotation — that is the missing object Mann described: you cannot ask "which credentials exist" today because there is no object.
wp-config.php Is Still Going to Be There
Constants are not going away
// still valid, still useful on many hosts
define( 'WP_SECRETS_KEY', getenv( 'WP_SECRETS_KEY' ) );
define( 'MYPLUGIN_API_KEY', getenv( 'MYPLUGIN_API_KEY' ) );
Until plugins call wp_get_secret(), they will keep reading constants. A responsible 2026 plugin does:
function myplugin_key(): string {
if ( defined( 'MYPLUGIN_API_KEY' ) && MYPLUGIN_API_KEY !== '' ) {
return MYPLUGIN_API_KEY;
}
if ( function_exists( 'wp_get_secret' ) ) {
$s = wp_get_secret( 'myplugin/api-key' );
if ( $s instanceof WP_Secret ) {
return $s->reveal();
}
}
$legacy = get_option( 'myplugin_api_key', '' );
return is_string( $legacy ) ? $legacy : '';
}
Priority: env/constant, then Secrets API, then legacy option. Document that the option path is deprecated. Don't surprise-delete production keys on upgrade.
Why people still paste into wp-config
Shared hosting with no env UI. Agencies that refuse to put keys in the database after one leak. Cargo cult from "don't put secrets in the DB" Twitter threads that never mentioned envelope encryption.
The proposal does not make wp-config wrong. It makes "options table plaintext" less defensible as the default plugin path. Hosts who already have a secret store will keep telling you to use their getter until the drop-in matches their write policy.
Plugin Author Checklist
If you ship a settings field that is a credential
- Namespace:
your-slug/purpose. - Do not add a
pre_option_filter that logs the value "for debugging." - Handle
WP_Errorfrom get as a broken keyring, not as logged-out. - Import once, rotate, then delete the plaintext option.
- Assume another plugin can read your name. Don't store a "more secret" secret next to a "less secret" one and expect isolation.
If you are Woo / SMTP / ESP scale
You already have incident history. Map one key in a beta of the feature plugin. Report whether two version slots are enough for your rotation. Mann asked that question on purpose.
If you are Two Factor / TOTP
Brian Haas's comment: strong +1, stop going your own way. TOTP secrets in options are a known smell. This API is closer to the right home than another defuse/php-encryption wrapper (emrl's comment: they already did that with hooks around specific options).
If you write host glue
Read Reynolds and McCue before you implement secrets.php. If your store is write-out-of-band, you need a read-only provider and plugin UX that does not sit in a spinner on wp_set_secret(). That UX is not in the proposal. Someone has to invent "this key is managed in the panel."
Timeline and the Honest Slip Risk
Beta 1: October 20–22, 2026. Working backward from the post:
- Now through mid-September: feedback, feature plugin for testing.
- Late September: Trac patch matching the plugin surface.
- Before Beta 1: committed, or explicitly deferred to 7.3.
Mann volunteered to implement, not to propose and vanish. That matters in WordPress more than in projects with a staffed secrets team.
If host objections force a provider model that does take plaintext for KMS-style stores, the API will change before freeze. Do not screenshot the current function list into a client SOW as "7.2 will have this." Write "proposed for 7.2, feature plugin first."
What I Would Do on a Client Site This Week
Inventory: wp option list is the wrong tool but it's what you have. Search dumps for sk-, rk_live, SG., AKIA, ghp_. Get those out of tickets and Slack.
Move what you can to env or constants now. That is the Delicious Brains ordering and it still applies.
Do not wait for 7.2 to stop emailing database dumps. Ciphertext in 7.2 does not un-send last year's gzip.
When the feature plugin exists, run it on a staging site that has one real third-party key, not on a toy option. Practice the WP_Error path by rotating LOGGED_IN_SALT in a disposable clone (then throw the clone away).
For WordPress 7.0 Connectors specifically, keep env overrides, and keep wpmdb_preserved_options so a pull does not overwrite local keys with production. That filter remains relevant until Connectors speak the Secrets API.
How This Fits the Rest of 7.x Security Work
The same week as this proposal, Make/Core also pushed the Core Security Initiative (AI-flooded HackerOne volume). Those are related only in the sense that WordPress is trying to grow first-party security machinery instead of hoping plugins invent it.
Secrets API is not a WAF. It is not capability isolation between plugins. It is a type, encryption at rest by default, and a chokepoint you can log. That is a smaller claim than the title "Secrets API" sounds like. Smaller claims are the ones that can ship.
If 7.2 lands the API and 7.3 lands a screen that still echos a reveal into HTML, the plot was wasted. The no-filter rule has to survive the UI too.
Strings in, strings out, and other small knives
No object graphs
The proposal will not serialize for you. You may json_encode a blob and store it. Core will not unpack it. That stops a secret from expanding into an object graph on read, which is how you accidentally hydrate a class that talks to the network. If your plugin wants structured credentials, you own the JSON. Keep it boring.
Nothing plaintext in the object cache
Shared Redis on cheap hosting is a side channel. WP_Secret refusing serialization is the mitigation they chose. If you wp_cache_set the revealed string yourself, you undid the API. Code review should grep reveal() and look at the next five lines.
Capabilities are not a design system
manage_secrets / manage_network_secrets will get mapped badly on membership plugins. Super Admin versus Administrator versus a custom "SEO manager" role that currently manage_options is enough to see SMTP passwords. When you ship 7.2, audit who has manage_options today. Those people can already read plaintext options. After encryption, the capability split only helps if you stop granting manage_options like candy.
A Walk Through a Woo-Shaped Key
Today
// typical gateway: settings API writes the option
register_setting( 'woo_gw', 'woo_gw_secret' );
function woo_gw_charge( $amount ) {
$key = get_option( 'woo_gw_secret' );
return WooGw\Client::charge( $key, $amount );
}
get_option is also what wp option get woo_gw_secret prints. Support staff paste it into tickets. Staging clones production and charges real cards if the key is live. You already know this story.
After a careful import
function woo_gw_charge( $amount ) {
if ( defined( 'WOO_GW_SECRET' ) && WOO_GW_SECRET ) {
$key = WOO_GW_SECRET;
} else {
$secret = wp_get_secret( 'woo-gw/secret' );
if ( is_wp_error( $secret ) ) {
throw new RuntimeException( 'Payment key unreadable; check Site Health' );
}
if ( $secret === null ) {
throw new RuntimeException( 'Payment key missing' );
}
$key = $secret->reveal();
}
return WooGw\Client::charge( $key, $amount );
}
Throwing is better than charging with an empty string. The WP_Error branch is the salt-rotation case. If you map that to "please reconnect Stripe" you will train users to paste keys they already entered. Show "encryption key changed" copy instead.
Rotation with two slots
wp_set_secret( 'woo-gw/secret', $new_from_stripe_dashboard );
// CURRENT is new; PREVIOUS is old until you retire it
$live = wp_get_secret( 'woo-gw/secret', WP_Secret_Version::CURRENT );
$drain = wp_get_secret( 'woo-gw/secret', WP_Secret_Version::PREVIOUS );
Webhooks in flight might still sign with the old key. Keep PREVIOUS until Stripe says the old restricted key is unused. Then an explicit retire. Do not cron this on day 7 because a blog post said 7.
Backups, Migrate, and the Agency Habit
WP Migrate, WP-CLI db export, phpMyAdmin
Ciphertext in wp_options still copies. The dump is less useful to a thief who only has SQL. The dump is still a map of which integrations you use (woo-gw/secret as a name is intelligence). Fingerprints in logs are intelligence. Name secrets like woo-gw/secret, not woo-gw/sk_live_51H....
Find-and-replace on dumps will not rotate envelope blobs. If your migrate plugin rewrites URLs inside options, confirm it will not touch ciphertext rows. Autoload is off; some migrate tools skip non-autoload. Test once.
The email-a-dump problem
Encrypting at rest does not stop someone attaching prod.sql.gz to Gmail. It changes what the attachment contains. Tell clients the new rule is still: no dumps through email. The API is not a substitute for access control on backups.
Object cache and HTML debug
Query Monitor, WP_DEBUG_DISPLAY, stack traces that interpolate options — those are the disclosure surfaces Mann listed. After 7.2, a plugin that print_r( wp_get_secret( 'x' ) ) should print a mask. A plugin that print_r( wp_get_secret( 'x' )->reveal() ) is a bug. Grep the second.
What hosts can ship without waiting
Env remains the best override
# sketch: php-fpm env
env WP_SECRETS_KEY;
env OPENAI_API_KEY;
Connectors already document this chain. Keep it. If 7.2's drop-in cannot express read-only stores, hosts should keep pantheon_get_secret()-style functions and map them in a mu-plugin until core catches up.
A mu-plugin shim for the gap year
<?php
/**
* Plugin Name: Secret get shim
*/
function nandann_get_secret( string $name ): ?string {
$env = getenv( strtoupper( str_replace( '/', '_', $name ) ) );
if ( is_string( $env ) && $env !== '' ) {
return $env;
}
if ( function_exists( 'wp_get_secret' ) ) {
$s = wp_get_secret( $name );
if ( $s instanceof WP_Secret ) {
return $s->reveal();
}
}
return null;
}
Ugly names. Honest fallback. Delete it when plugins speak core.
Failure modes to tabletop
You rotate AUTH_KEY in a hardening pass and half the site's integrations die
If they fell back to salts, this is the Site Kit lesson. Tabletop it before you run a "refresh all salts" security plugin on Monday. Dedicated WP_SECRETS_KEY in env is how you make salt rotation a session problem, not a Stripe problem.
Feature plugin API matches core, then core tweaks one return type
Mann's promise: core patch identical to plugin so nothing rewrites. If that promise slips, the rewrite is on plugin authors who adopted early. Pin the feature plugin version in composer or as a "tested up to" note.
A security plugin adds a retrieval filter "for auditing"
If core holds the no-filter line, that plugin cannot exist. If core folds, you get a documented steal hook. Watch the Trac discussion. This is the design decision most likely to get "just one small filter."
7.2 versus 7.3 as a planning split
7.2, if it lands: storage, get/set/delete/import, CLI, capabilities, drop-in, Site Health for undecryptable blobs, no screen.
7.3, if they keep the plan: a UI that must not become options.php for secrets. Group by plugin slug. Show fingerprints and timestamps. Never a "view secret" button without a loud confirm, and maybe not even then. Reveal is for code, not for HTML.
Agencies should sell 7.2 work as "stop writing keys into options" and 7.3 work as "teach the client's admin which keys exist." Different tickets. Different people.
One more operational detail: autoload=no means secrets should not ride along with every page load's options cache the way blogname does. Confirm in object cache dumps after you import. If a plugin called update_option( $k, $v, 'yes' ) on a key, the old autoload row may linger until you delete it. Import is not a vacuum.
If you use a "security hardening" plugin that rewrites salts on a schedule, disable that schedule until WP_SECRETS_KEY is independent. Those plugins were written for cookie invalidation. They were not written for envelope keyrings.
Multisite agencies: decide now whether SMTP is a network secret or a per-site secret. Getting that wrong in v0 means copying keys into 200 sites and then pretending the API failed. The API will do what you asked.
Sources: Eric Mann, "Proposal: A Secrets API for WordPress 7.2" (Make/Core, August 25, 2026) and its comment thread (Pantheon, Altis, Two Factor, AI plugin); The WP Clan recap (August 26); The Repository (August 27); Delicious Brains on Connectors env vs database; WordPress 7.0 Connectors option naming; Site Kit's documented salt-rotation behavior as cited in the proposal; daily.dev's summary of the same Make/Core post. The feature plugin and Trac ticket may exist after this date — treat Make/Core as canonical until commit.
FAQs
Is the Secrets API in WordPress 7.2 yet?
No. It is a Make/Core proposal dated August 25, 2026. Eric Mann wants a feature plugin first, a Trac patch in late September, and a go/no-go before 7.2 Beta 1 on October 20-22. He would rather slip to 7.3 than rush it.
Where do plugin API keys live today?
Usually as plaintext rows in wp_options, or as constants in wp-config.php, or as environment variables on hosts that support them. Core has no first-class secret type, which is the gap the proposal is trying to close.
Does encryption mean a stolen database is harmless?
No. It raises the cost of dumps, backups, and SQL injection reads. Code running inside WordPress can still call wp_get_secret() and reveal(). The proposal says process execution is out of scope.
Will there be a settings screen in 7.2?
The proposal says no. Storage and retrieval semantics land first. An admin UI is planned for 7.3 after the API has real usage. WP-CLI is in scope for 7.2 so core has a first-party consumer in the same release.
Can hosts plug in Vault or Parameter Store?
The design is a secrets.php drop-in with separate storage and keyring providers. Pantheon and Altis already said the write path and in-PHP encryption do not match how their platforms work. That feedback is still open.
Should plugin authors wait for core?
Stop writing new plaintext options for keys. Prefer env or wp-config constants now. Watch the feature plugin and map one option to wp_import_option_as_secret() when the surface freezes. Do not invent a third encryption scheme if you can wait a release.
What about salt rotation breaking secrets?
Envelope encryption is meant so rotating the site wrapping key re-wraps a master key instead of every blob. Site Kit already documented salt rotation as a breakage mode at scale. Undecryptable secrets should surface in Site Health, not as silent empty strings.
Is wp-config a secrets API?
It is a file-backed constant bag. Better than the options table for not showing up in SQL dumps. Worse for rotation, inventory, and CLI hygiene. The proposal is trying to be an actual object with fingerprints, versions, and capabilities.
WordPress Development & Maintenance
Need help with your WordPress site?
Whether you're upgrading to WordPress 7.0, building a new site from scratch, or need someone to keep things running smoothly — we handle the technical side so you can focus on your business.
Custom plugin development, theme builds, performance tuning, security hardening, ongoing maintenance retainers — we've done it all.
Related Articles
WordPress • 16 min
Securing Your WordPress Site with Rust-Based WebAssembly Plugins
Nearly half of mobile WordPress sites fail Core Web Vitals. Learn how Rust-compiled WebAssembly plugins deliver sandboxed, memory-safe, near-native performance — fixing security and speed at the architecture level.
4/19/2026
WordPress • 7 min
Is Nextpress the True WordPress Killer? A 2026 Stack Analysis
Analyze why Next.js is not a WordPress killer. Explore Nextpress as a unified CMS stack, Vercel deployment, and the shift from monolithic to headless architectures in 2026.
5/23/2026
WordPress • 10 min
2026 Web Dev Chaos: WordPress, Next.js, and Rust Trade-offs
Analyze 2026 web dev trade-offs between WordPress, Next.js, and Rust. Explore security risks, performance, and headless CMS strategies for engineering leads.
5/2/2026