v0.0.1 — Open Specification + Reference Implementation

Stop giving every plugin
the keys to everything.

WP Apps is an open spec for sandboxed, permission-scoped WordPress extensions. Apps run as isolated services with zero runtime cost — they write data via API, WordPress renders it. No database access, no filesystem access, no PHP execution. The Shopify model, for WordPress.

View on GitHub → Get Started
WordPress Site
WP Core
REST API
Block Editor
Post Meta
Apps Runtime (plugin)
API Gateway + Auth
Block Manager + Cache
Permission Enforcement
Event Webhooks + Audit
HTTPS — Structured Protocol
SEO App
Cloud
Forms App
Container
Analytics
Same Server
01
The Problem

WordPress plugins run with the keys to the kingdom

Every plugin gets full, unrestricted access to everything. A single vulnerable plugin compromises the entire site.

Traditional Plugin — Access Audit
Database (all tables)Full Access
wp-config.phpFull Access
FilesystemFull Access
PHP runtimeFull Access
Network (outbound)Full Access
User passwordsFull Access
Other pluginsFull Access
wp_options (all settings)Full Access
CSS/JS on every pageFull Access
Cron (unlimited, never cleaned)Full Access
Verdict: Unrestricted — total surface exposure
WP App — Access Audit
DatabaseAPI only
wp-config.phpDenied
FilesystemDenied
PHP runtimeDenied
NetworkApp's own
User dataread:basic
Other appsIsolated
Settings storageApp's own DB
Frontend assetsBlocks only
CronManaged
Verdict: Scoped, isolated, zero runtime cost

Plugin vulnerabilities are the #1 attack vector for WordPress sites. Not because developers are careless — because the architecture gives every extension the keys to everything.

02
How It Works

Data first. Zero runtime cost. The Shopify model.

Apps write data via API, WordPress renders it. No HTTP calls during page loads. No PHP executing in your process. No performance penalty.

Apps are external services

Apps run anywhere — a cloud server, a container, a serverless function, or even a separate process on the same machine. They never run inside WordPress.

Declare permissions in a manifest

Apps ship a wp-app.json declaring identity, scopes, event subscriptions, and blocks. The admin reviews and approves before installation.

OAuth tokens, not database credentials

Apps get scoped, short-lived access tokens (1hr) with automatic refresh. No database credentials, no filesystem paths, no PHP runtime sharing.

Event webhooks, not blocking hooks

When a post is saved, user registers, or content changes — apps get an async webhook. They process in the background and write results back via API. Page loads are never blocked.

Blocks for frontend, not global injection

Apps register blocks that the admin places via the block editor. Assets load only where the block appears. Works in Gutenberg, Elementor (via shortcode fallback), and Classic Editor.

Built-in caching eliminates the need for caching plugins

Block renders are cached. Post meta is served from WordPress's cache layer. A site with 20 apps installed loads at the same speed as a site with zero apps.

03
Features

Everything apps need, nothing they don't

Zero runtime cost

Apps add zero overhead to frontend page loads. Data is written at save time and served from cache. No HTTP round-trips during rendering.

Granular permissions

Scopes like posts:read, users:read:basic, email:send. Apps declare what they need; admins approve exactly that. Never-grantable capabilities protect secrets.

Async event webhooks

Apps subscribe to WordPress events (save_post, user_register, etc.) and process them in the background. Never blocking, always fire-and-forget.

Blocks + shortcodes

Apps register Gutenberg blocks with automatic shortcode fallback for Elementor, Divi, and Classic Editor. Block output is cached — rendered once, served forever.

Apps own their data

Apps store settings and business data in their own database. WordPress is used only for post meta (namespaced, per-app) when data is tied to a specific post.

Rate limits + audit log

Every API call, webhook, and data access is rate-limited and logged. 1,000 reads/hr, 200 writes/hr, 50 emails/hr per app. Full visibility into what every app does.

Permission Scopes

posts:read posts:write posts:delete postmeta:read postmeta:write users:read:basic users:read:full media:read media:write comments:read comments:write taxonomies:read taxonomies:write email:send cron:register blocks:register rest:extend site:read
04
Developer Experience

Build apps in any language

Declare everything in a manifest. Handle events and blocks with a clean SDK. Ship anywhere that serves HTTP.

wp-app.json
{
  "app": {
    "id": "com.example.my-seo-app",
    "name": "My SEO App",
    "version": "1.0.0"
  },

  "permissions": {
    "scopes": ["posts:read", "postmeta:read", "postmeta:write"]
  },

  // Tier 1: Async event webhooks (zero page-load cost)
  "hooks": {
    "events": [
      { "event": "save_post", "description": "Analyze content and write SEO score to post meta" }
    ]
  },

  // Post meta rendered automatically in wp_head by the runtime
  "postmeta": {
    "seo_title": "SEO title override",
    "seo_description": "Meta description",
    "schema_json": "JSON-LD schema markup"
  },

  "surfaces": {
    "blocks": [
      { "name": "my-seo-app/faq", "title": "FAQ (with Schema)", "cache_ttl": 3600 }
    ]
  }
}
use WPApps\SDK\App;
use WPApps\SDK\Request;
use WPApps\SDK\Response;

$app = new App(__DIR__ . '/wp-app.json');

// Event: analyze post on save (async, zero page-load cost)
$app->onEvent('save_post', function (Request $req): Response {
    $postId = $req->args[0];
    $post = $req->api->get("/apps/v1/posts/{$postId}");
    $score = analyze_seo($post['content']);

    // Write to post meta — runtime renders in wp_head automatically
    $req->api->put("/apps/v1/posts/{$postId}/meta/seo_score", ['value' => $score]);
    $req->api->put("/apps/v1/posts/{$postId}/meta/schema_json", ['value' => '...']);
    return Response::ok();
});

// Block: render FAQ with schema (cached, served from WP cache layer)
$app->onBlock('my-seo-app/faq', function (Request $req): Response {
    return Response::block('<div class="faq">...</div>');
});

$app->run();
# Scaffold a new app
$ wp-apps init my-seo-app --language php

# Validate your manifest
$ wp-apps validate ./wp-app.json
  ✓ Manifest valid
  ✓ 3 scopes declared
  ✓ 1 event webhook
  ✓ 1 block registered

# Run locally with tunnel to your dev site
$ wp-apps dev --site https://mysite.com
  App running at localhost:3000
  Tunnel: https://abc123.wp-apps.dev
  Connected to mysite.com ✓

# Deploy
$ wp-apps deploy --platform instawp
  ✓ Deployed v1.0.0 to InstaWP Apps Platform
05
Comparison

Plugins vs Apps

AspectTraditional PluginWP App
ExecutionIn-process PHPExternal HTTP service
DatabaseFull access ($wpdb, any table)Scoped REST API only
FilesystemFull (wp-config, core files)None
Settings storagewp_options (autoloaded, bloats every page)App's own database
Frontend assetsCSS/JS on every pageBlocks — load only where placed
Page load impactAdds PHP execution + queries + assetsZero (data pre-written, cached)
PermissionsAll or nothingGranular scopes, admin-approved
Crash impactTakes down entire siteApp fails gracefully
CachingRequires caching pluginBuilt-in block + page cache
Audit trailNoneFull audit log, rate limits
GDPRPlugin-dependentBuilt-in privacy declarations + export/erasure

Apps can run on the same server as WordPress — as a separate process. Same machine, separate runtime. Co-located apps add just 1–5ms latency per event webhook.

Get Involved

The spec is open.
Build with us.

WP Apps is an open specification with a working reference implementation. Read the spec, try the SDK, build an app, and contribute.