A Laravel-first application framework for WordPress. Build powerful WordPress plugins with Laravel's elegance and power.
- Laravel Service Container - Full IoC container with dependency injection
- Service Providers - Modular service registration and bootstrapping
- Fluent Builders - Easy APIs for CPTs, taxonomies, metaboxes, settings, menus, and more
- Blade Views - Laravel's powerful templating engine
- Validation - Laravel-style validation with WordPress-specific rules
- Events & Listeners - Decouple your application logic
- CLI Commands - Generate boilerplate with Artisan-like commands
- React & Vue Support - First-class frontend framework integration
- PHP 8.1+
- WordPress 6.0+
- Composer
cd wp-content/plugins
git clone https://github.com/wpjarvis/wp-jarvis.gitcd wp-jarvis
composer installcp .env.example .envnpm install
npm run buildGo to WordPress Admin > Plugins and activate "WP Jarvis".
wp-jarvis/
├── app/ # Application code
│ ├── Modules/ # Feature modules
│ │ └── Portfolio/ # Example module
│ ├── Providers/ # Service providers
│ ├── helpers.php # App helper functions
│ └── Plugin.php # Main plugin class
├── bootstrap/ # Bootstrap files
│ └── cache/ # Cached config
├── config/ # Configuration files
│ ├── app.php
│ ├── database.php
│ └── requirements.php
├── database/ # Migrations & seeds
├── public/ # Public assets
│ └── build/ # Compiled assets
├── resources/ # Views, JS, CSS
│ ├── css/
│ ├── js/
│ │ └── components/
│ └── views/
├── routes/ # Route definitions
│ ├── admin.php
│ ├── api.php
│ └── web.php
├── storage/ # Storage directory
│ ├── framework/
│ └── logs/
├── composer.json
├── package.json
├── plugin.php # Plugin entry point
└── vite.config.js # Vite configuration
use WPJarvis\Framework\WordPress\PostTypes\PostTypeBuilder;
PostTypeBuilder::make('portfolio')
->labels('Portfolio Item', 'Portfolio')
->icon('dashicons-portfolio')
->supports(['title', 'editor', 'thumbnail'])
->hasArchive(true)
->rest(true)
->register();use WPJarvis\Framework\WordPress\Taxonomies\TaxonomyBuilder;
// Category-like (hierarchical)
TaxonomyBuilder::category('portfolio_category')
->labels('Category', 'Categories')
->forPostTypes('portfolio')
->register();
// Tag-like (non-hierarchical)
TaxonomyBuilder::tag('portfolio_tag')
->labels('Tag', 'Tags')
->forPostTypes('portfolio')
->register();use WPJarvis\Framework\WordPress\Metaboxes\MetaboxBuilder;
MetaboxBuilder::make('portfolio_details', 'Portfolio Details')
->forPostTypes('portfolio')
->text('client_name', 'Client Name')
->url('project_url', 'Project URL')
->date('completion_date', 'Completion Date')
->select('status', 'Status', [
'active' => 'Active',
'completed' => 'Completed',
])
->checkbox('featured', 'Featured Project')
->media('gallery_image', 'Gallery Image')
->register();use WPJarvis\Framework\WordPress\Settings\SettingsPageBuilder;
SettingsPageBuilder::make('my-settings', 'My Settings')
->underSettings()
->section('general', 'General Settings')
->text('api_key', 'API Key')
->checkbox('enabled', 'Enable Feature')
->select('mode', 'Mode', [
'basic' => 'Basic',
'advanced' => 'Advanced',
])
->register();use WPJarvis\Framework\WordPress\Admin\MenuBuilder;
MenuBuilder::make()
->menu('my-plugin', 'My Plugin')
->icon('dashicons-admin-generic')
->position(30)
->callback([$this, 'renderDashboard'])
->submenu('my-plugin-settings', 'Settings', [$this, 'renderSettings'])
->register();use WPJarvis\Framework\WordPress\Admin\ColumnsManager;
ColumnsManager::for('portfolio')
->thumbnail('image', 'Image', [60, 60])
->after('title', 'client', 'Client', function ($postId) {
echo get_post_meta($postId, '_client', true) ?: '—';
})
->boolean('featured', 'Featured', '_featured', '★', '—')
->taxonomy('categories', 'Categories', 'portfolio_category')
->sortable('client', '_client')
->remove('comments')
->register();use WPJarvis\Framework\WordPress\Shortcodes\ShortcodeBuilder;
ShortcodeBuilder::make('my_shortcode')
->defaults(['title' => 'Hello', 'class' => ''])
->render(function ($atts, $content) {
return '<div class="' . esc_attr($atts['class']) . '">'
. '<h3>' . esc_html($atts['title']) . '</h3>'
. do_shortcode($content)
. '</div>';
})
->register();use WPJarvis\Framework\WordPress\Blocks\BlockBuilder;
BlockBuilder::make('my-block', 'My Block')
->namespace('wpjarvis')
->category('common')
->icon('block-default')
->textAttribute('title', 'Default Title')
->booleanAttribute('showBorder', false)
->render(function ($attributes) {
return '<div>' . esc_html($attributes['title']) . '</div>';
})
->register();WP Jarvis provides Artisan-like CLI commands for scaffolding:
# Generate a service provider
php jarvis make:provider MyServiceProvider
# Generate a custom post type
php jarvis make:posttype Portfolio
# Generate a taxonomy
php jarvis make:taxonomy PortfolioCategory --hierarchical
# Generate a metabox
php jarvis make:metabox PortfolioDetails --post-type=portfolio
# Generate a settings page
php jarvis make:settings MySettings
# Generate an admin menu
php jarvis make:menu MyMenu
# Generate admin columns
php jarvis make:columns PortfolioColumns --post-type=portfolio
# Generate a shortcode
php jarvis make:shortcode MyShortcode
# Generate a widget
php jarvis make:widget MyWidget
# Generate a Gutenberg block
php jarvis make:block MyBlock --dynamic
# Generate a complete module
php jarvis make:module Portfolio --full
# Generate a controller
php jarvis make:controller PortfolioController --resource
# Generate a model
php jarvis make:model Portfolio --migration --controller
# Clear cache
php jarvis cache:clear
# Show app info
php jarvis app:infoModules are self-contained features with their own service provider:
php jarvis make:module Blog --fullThis creates:
app/Modules/Blog/
├── Providers/
│ └── BlogServiceProvider.php
├── Http/
│ └── Controllers/
├── Models/
└── Views/
Register the module in config/app.php:
'providers' => [
// ...
BraCalculator\App\Modules\Blog\Providers\BlogServiceProvider::class,
],- Create a mount point in your admin page:
echo '<div data-wpjarvis-react="Dashboard" data-props=\'{"user":"admin"}\'></div>';- Enqueue the React script:
wp_enqueue_script('wpjarvis-react', plugins_url('public/build/js/react-app.js', WPJARVIS_FILE));- Create a mount point:
echo '<div data-wpjarvis-vue="Settings" data-props=\'{"settings":[]}\' ></div>';- Enqueue the Vue script:
wp_enqueue_script('wpjarvis-vue', plugins_url('public/build/js/vue-app.js', WPJARVIS_FILE));# Development with hot reload
npm run dev
# Production build
npm run buildCreate a service provider to register services:
<?php
namespace BraCalculator\App\Providers;
use WPJarvis\Framework\Foundation\BaseServiceProvider;
class MyServiceProvider extends BaseServiceProvider
{
public function register(): void
{
// Register bindings
$this->app->singleton('my-service', function () {
return new MyService();
});
}
public function boot(): void
{
// Bootstrap services
}
}All configuration files are in the config/ directory:
app.php- Application settings, providers, aliasesdatabase.php- Database connectionsrequirements.php- Plugin requirements
Access config values:
$value = config('app.name');
config(['app.debug' => true]);WP Jarvis provides Laravel-compatible helper functions:
// Application instance
app();
app('config');
// Configuration
config('app.name');
// Views
view('admin.dashboard', ['data' => $data]);
// Paths
base_path('app');
config_path('app.php');
storage_path('logs');
resource_path('views');
// Utilities
collect([1, 2, 3])->map(fn($n) => $n * 2);
now();
today();To run the test suite:
composer install
vendor/bin/phpunitGPL-2.0-or-later