How to Create a WordPress Playground Blueprint For Your Plugin Live Preview

Blueprint File
Blueprints can be complicated

The WordPress plugin directory has recently added live previews for plugins hosted there. This is game-changing, as plugin authors can now curate a demo experience that shows their plugin in the best light right from the .org plugin page.

Highlight and Share live preview example
Highlight and Share Live Preview

Enabling the Live Preview option for your plugin is not as straightforward as enabling an option. You’ll need to create your own Playground environment, generate a blueprint file, and add that to your plugin’s assets folder.

In this tutorial, I’ll explain the WordPress Playground, give tips on creating your own local environment, generate your blueprint file, and enable the Live Preview feature on .org.

Let’s start with the WordPress Playground.

What is the WordPress Playground?

The WordPress Playground is a neat way to generate an instance of WordPress in the browser that you can play and tinker with on a temporary basis.

To create a Playground instance, visit https://playground.wordpress.net. To launch it, provide some URL query parameters to tell it how to be configured.

Here’s a sample URL using Playground’s Query API:

https://playground.wordpress.net/?plugin=simple-comment-editing&theme=astraCode language: plaintext (plaintext)

You can also pass it a URL to a blueprint file using the blueprint-url query parameter:

https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/DLXPlugins/simple-comment-editing/master/blueprint.jsonCode language: plaintext (plaintext)

Introducing blueprints

A powerful feature of the WordPress Playground is its support for blueprints. Blueprints are JSON files used to set up a WordPress instance on the Playground. This allows you to activate plugins and themes, set a landing page, run custom code, and so much more. By populating a blueprint, you are telling the WordPress Playground to create an instance according to your exact specifications.

For example, here’s a blueprint.json file for my plugin Ajaxify Comments.

{
    "$schema": "https://playground.wordpress.net/blueprint-schema.json",
    "preferredVersions": {
        "php": "8.1",
        "wp": "6.5"
    },
    "features": {
        "networking": true
    },
    "phpExtensionBundles": [
        "kitchen-sink"
    ],
    "landingPage": "/",
    "steps": [
        {
            "step": "login",
            "username": "admin",
            "password": "password"
        },
        {
            "step": "installTheme",
            "themeZipFile": {
                "resource": "wordpress.org/themes",
                "slug": "blocksy"
            },
            "options": {
                "activate": true
            }
        },
        {
            "step": "installPlugin",
            "pluginZipFile": {
                "resource": "wordpress.org/plugins",
                "slug": "confetti"
            },
            "options": {
                "activate": true
            }
        },
		{
            "step": "installPlugin",
            "pluginZipFile": {
                "resource": "wordpress.org/plugins",
                "slug": "generateblocks"
            },
            "options": {
                "activate": true
            }
        },
        {
            "step": "installPlugin",
            "pluginZipFile": {
                "resource": "wordpress.org/plugins",
                "slug": "simple-comment-editing"
            },
            "options": {
                "activate": true
            }
        },
        {
            "step": "installPlugin",
            "pluginZipFile": {
                "resource": "wordpress.org/plugins",
                "slug": "wp-ajaxify-comments"
            },
            "options": {
                "activate": true
            }
        },
        {
            "step": "importFile",
            "file": {
                "resource": "url",
                "url": "https://raw.githubusercontent.com/DLXPlugins/wp-ajaxify-comments/main/blueprint-content.xml"
            }
        },
        {
            "step": "setSiteOptions",
            "options": {
                "blogname": "Ajaxify Comments Demo",
                "users_can_register": "0",
                "admin_email": "ronald@dlxplugins.local"
            }
        },
        {
            "step": "setSiteOptions",
            "options": {
                "permalink_structure": "/%postname%/"
            }
        },
        {
            "step": "setSiteOptions",
            "options": {
                "show_on_front": "page",
				"page_on_front": 8
            }
        },      
        {
			"step": "runPHP",
			"code": "<?php require_once 'wordpress/wp-load.php'; update_option( 'theme_mods_blocksy', maybe_unserialize( 'a:18:{i:0;b:0;s:38:\"blocksy_woocommerce_thumbnail_cropping\";s:10:\"predefined\";s:23:\"woocommerce_filter_type\";s:6:\"type-1\";s:32:\"single_blog_post_share_box_title\";s:0:\"\";s:27:\"single_page_share_box_title\";s:0:\"\";s:18:\"nav_menu_locations\";a:1:{s:6:\"menu_1\";i:3;}s:18:\"custom_css_post_id\";i:-1;s:12:\"maxSiteWidth\";s:4:\"1290\";s:18:\"contentAreaSpacing\";a:3:{s:7:\"desktop\";s:4:\"24px\";s:6:\"tablet\";s:4:\"24px\";s:6:\"mobile\";s:4:\"24px\";}s:18:\"contentEdgeSpacing\";a:3:{s:7:\"desktop\";s:1:\"5\";s:6:\"tablet\";s:1:\"5\";s:6:\"mobile\";s:1:\"5\";}s:10:\"wideOffset\";s:2:\"20\";s:17:\"header_placements\";a:2:{s:15:\"current_section\";s:6:\"type-1\";s:8:\"sections\";a:1:{i:0;a:6:{s:2:\"id\";s:6:\"type-1\";s:4:\"mode\";s:10:\"placements\";s:5:\"items\";a:0:{}s:8:\"settings\";a:0:{}s:7:\"desktop\";a:4:{i:0;a:2:{s:2:\"id\";s:7:\"top-row\";s:10:\"placements\";a:5:{i:0;a:2:{s:2:\"id\";s:5:\"start\";s:5:\"items\";a:0:{}}i:1;a:2:{s:2:\"id\";s:6:\"middle\";s:5:\"items\";a:0:{}}i:2;a:2:{s:2:\"id\";s:3:\"end\";s:5:\"items\";a:0:{}}i:3;a:2:{s:2:\"id\";s:12:\"start-middle\";s:5:\"items\";a:0:{}}i:4;a:2:{s:2:\"id\";s:10:\"end-middle\";s:5:\"items\";a:0:{}}}}i:1;a:2:{s:2:\"id\";s:10:\"middle-row\";s:10:\"placements\";a:5:{i:0;a:2:{s:2:\"id\";s:5:\"start\";s:5:\"items\";a:1:{i:0;s:4:\"logo\";}}i:1;a:2:{s:2:\"id\";s:6:\"middle\";s:5:\"items\";a:0:{}}i:2;a:2:{s:2:\"id\";s:3:\"end\";s:5:\"items\";a:1:{i:0;s:4:\"menu\";}}i:3;a:2:{s:2:\"id\";s:12:\"start-middle\";s:5:\"items\";a:0:{}}i:4;a:2:{s:2:\"id\";s:10:\"end-middle\";s:5:\"items\";a:0:{}}}}i:2;a:2:{s:2:\"id\";s:10:\"bottom-row\";s:10:\"placements\";a:5:{i:0;a:2:{s:2:\"id\";s:5:\"start\";s:5:\"items\";a:0:{}}i:1;a:2:{s:2:\"id\";s:6:\"middle\";s:5:\"items\";a:0:{}}i:2;a:2:{s:2:\"id\";s:3:\"end\";s:5:\"items\";a:0:{}}i:3;a:2:{s:2:\"id\";s:12:\"start-middle\";s:5:\"items\";a:0:{}}i:4;a:2:{s:2:\"id\";s:10:\"end-middle\";s:5:\"items\";a:0:{}}}}i:3;a:2:{s:2:\"id\";s:9:\"offcanvas\";s:10:\"placements\";a:1:{i:0;a:2:{s:2:\"id\";s:5:\"start\";s:5:\"items\";a:0:{}}}}}s:6:\"mobile\";a:4:{i:0;a:2:{s:2:\"id\";s:7:\"top-row\";s:10:\"placements\";a:5:{i:0;a:2:{s:2:\"id\";s:5:\"start\";s:5:\"items\";a:0:{}}i:1;a:2:{s:2:\"id\";s:6:\"middle\";s:5:\"items\";a:0:{}}i:2;a:2:{s:2:\"id\";s:3:\"end\";s:5:\"items\";a:0:{}}i:3;a:2:{s:2:\"id\";s:12:\"start-middle\";s:5:\"items\";a:0:{}}i:4;a:2:{s:2:\"id\";s:10:\"end-middle\";s:5:\"items\";a:0:{}}}}i:1;a:2:{s:2:\"id\";s:10:\"middle-row\";s:10:\"placements\";a:5:{i:0;a:2:{s:2:\"id\";s:5:\"start\";s:5:\"items\";a:1:{i:0;s:4:\"logo\";}}i:1;a:2:{s:2:\"id\";s:6:\"middle\";s:5:\"items\";a:0:{}}i:2;a:2:{s:2:\"id\";s:3:\"end\";s:5:\"items\";a:1:{i:0;s:7:\"trigger\";}}i:3;a:2:{s:2:\"id\";s:12:\"start-middle\";s:5:\"items\";a:0:{}}i:4;a:2:{s:2:\"id\";s:10:\"end-middle\";s:5:\"items\";a:0:{}}}}i:2;a:2:{s:2:\"id\";s:10:\"bottom-row\";s:10:\"placements\";a:5:{i:0;a:2:{s:2:\"id\";s:5:\"start\";s:5:\"items\";a:0:{}}i:1;a:2:{s:2:\"id\";s:6:\"middle\";s:5:\"items\";a:0:{}}i:2;a:2:{s:2:\"id\";s:3:\"end\";s:5:\"items\";a:0:{}}i:3;a:2:{s:2:\"id\";s:12:\"start-middle\";s:5:\"items\";a:0:{}}i:4;a:2:{s:2:\"id\";s:10:\"end-middle\";s:5:\"items\";a:0:{}}}}i:3;a:2:{s:2:\"id\";s:9:\"offcanvas\";s:10:\"placements\";a:1:{i:0;a:2:{s:2:\"id\";s:5:\"start\";s:5:\"items\";a:1:{i:0;s:11:\"mobile-menu\";}}}}}}}}s:11:\"buttonColor\";a:2:{s:7:\"default\";a:1:{s:5:\"color\";s:7:\"#fa4728\";}s:5:\"hover\";a:1:{s:5:\"color\";s:28:\"var(--theme-palette-color-2)\";}}s:10:\"forms_type\";s:13:\"classic-forms\";s:14:\"rootTypography\";a:7:{s:6:\"family\";s:5:\"Arial\";s:9:\"variation\";s:2:\"n4\";s:4:\"size\";a:3:{s:7:\"desktop\";s:4:\"18px\";s:6:\"tablet\";s:4:\"18px\";s:6:\"mobile\";s:4:\"18px\";}s:11:\"line-height\";s:4:\"1.65\";s:14:\"letter-spacing\";s:3:\"0em\";s:14:\"text-transform\";s:4:\"none\";s:15:\"text-decoration\";s:4:\"none\";}s:14:\"contentSpacing\";s:8:\"spacious\";s:17:\"content_link_type\";s:6:\"type-4\";s:12:\"has_back_top\";s:3:\"yes\";}' ) ); ?>"
		},
		{
			"step": "runPHP",
			"code": "<?php require_once 'wordpress/wp-load.php'; update_option( 'nav_menu_options', maybe_unserialize( 'a:1:{s:8:\"auto_add\";a:0:{}}' ) ); ?>"
		},
		{
			"step": "runPHP",
			"code": "<?php require_once 'wordpress/wp-load.php'; update_option( 'nav_menu_options', maybe_unserialize( 'a:3:{i:6;b:1;i:23;b:1;i:31;b:1;}' ) ); ?>"
		},
        {
            "step": "setSiteOptions",
            "options": {
                "elementor_disable_color_schemes": "yes",
                "elementor_disable_typography_schemes": "yes",
                "elementor_viewport_lg": "1000",
                "elementor_viewport_md": "690",
                "blocksy_db_version": "2.0.38",
                "dismissed-blocksy_plugin_notice": "1"
            }
        },
		{
			"step": "runPHP",
			"code": "<?php require_once 'wordpress/wp-load.php'; update_option( 'wpac', maybe_unserialize( 'a:80:{s:6:\"enable\";b:1;s:5:\"debug\";b:0;s:10:\"menuHelper\";b:1;s:19:\"selectorCommentForm\";s:12:\"#commentform\";s:25:\"selectorCommentsContainer\";s:9:\"#comments\";s:19:\"selectorCommentList\";s:16:\".ct-comment-list\";s:26:\"selectorCommentPagingLinks\";s:9:\"#comments\";s:20:\"selectorCommentLinks\";s:9:\"#comments\";s:24:\"selectorRespondContainer\";s:8:\"#respond\";s:22:\"selectorErrorContainer\";s:8:\"p:parent\";s:20:\"selectorSubmitButton\";s:7:\"#submit\";s:16:\"selectorTextarea\";s:8:\"#comment\";s:21:\"selectorPostContainer\";s:0:\"\";s:11:\"scrollSpeed\";s:3:\"500\";s:18:\"autoUpdateIdleTime\";s:1:\"0\";s:27:\"popupOverlayBackgroundColor\";s:25:\"rgba(254, 254, 254, 0.75)\";s:29:\"popupOverlayBackgroundOpacity\";s:4:\"0.76\";s:27:\"popupBackgroundColorLoading\";s:7:\"#000000\";s:21:\"popupTextColorLoading\";s:7:\"#ffffff\";s:27:\"popupBackgroundColorSuccess\";s:7:\"#008000\";s:21:\"popupTextColorSuccess\";s:7:\"#FFFFFF\";s:25:\"popupBackgroundColorError\";s:7:\"#FF0000\";s:19:\"popupTextColorError\";s:7:\"#FFFFFF\";s:12:\"popupOpacity\";s:2:\"85\";s:18:\"popupOpacityTablet\";s:2:\"85\";s:18:\"popupOpacityMobile\";s:2:\"85\";s:17:\"popupCornerRadius\";s:1:\"5\";s:23:\"popupCornerRadiusTablet\";s:1:\"5\";s:23:\"popupCornerRadiusMobile\";s:1:\"5\";s:14:\"popupMarginTop\";s:2:\"10\";s:20:\"popupMarginTopTablet\";s:2:\"10\";s:20:\"popupMarginTopMobile\";s:2:\"10\";s:10:\"popupWidth\";s:2:\"30\";s:16:\"popupWidthTablet\";s:2:\"45\";s:16:\"popupWidthMobile\";s:2:\"75\";s:12:\"popupPadding\";s:2:\"20\";s:18:\"popupPaddingTablet\";s:2:\"20\";s:18:\"popupPaddingMobile\";s:2:\"20\";s:11:\"popupFadeIn\";s:3:\"400\";s:12:\"popupFadeOut\";s:3:\"400\";s:12:\"popupTimeout\";s:4:\"3000\";s:14:\"popupTextAlign\";s:6:\"center\";s:18:\"popupVerticalAlign\";s:14:\"verticalCenter\";s:17:\"popupTextFontSize\";s:4:\"20px\";s:23:\"popupTextFontSizeTablet\";s:4:\"20px\";s:23:\"popupTextFontSizeMobile\";s:4:\"20px\";s:11:\"popupZindex\";s:4:\"1000\";s:10:\"textPosted\";s:40:\"Your comment has been posted. Thank you!\";s:20:\"textPostedUnapproved\";s:67:\"Your comment has been posted and is awaiting moderation. Thank you!\";s:14:\"textReloadPage\";s:28:\"Reloading page. Please wait.\";s:15:\"textPostComment\";s:34:\"Posting your comment. Please wait.\";s:19:\"textRefreshComments\";s:30:\"Loading comments. Please wait.\";s:16:\"textUnknownError\";s:55:\"Something went wrong, your comment has not been posted.\";s:20:\"textErrorTypeComment\";s:30:\"Please type your comment text.\";s:23:\"textErrorCommentsClosed\";s:41:\"Sorry, comments are closed for this item.\";s:23:\"textErrorMustBeLoggedIn\";s:47:\"Sorry, you must be logged in to post a comment.\";s:27:\"textErrorFillRequiredFields\";s:46:\"Please fill the required fields (name, email).\";s:28:\"textErrorInvalidEmailAddress\";s:35:\"Please enter a valid email address.\";s:23:\"textErrorPostTooQuickly\";s:85:\"You are posting comments too quickly. Please wait a minute and resubmit your comment.\";s:25:\"textErrorDuplicateComment\";s:82:\"Duplicate comment detected. It looks like you have already submitted this comment.\";s:30:\"callbackOnBeforeSelectElements\";s:0:\"\";s:29:\"callbackOnBeforeSubmitComment\";s:0:\"\";s:26:\"callbackOnAfterPostComment\";s:0:\"\";s:30:\"callbackOnBeforeUpdateComments\";s:0:\"\";s:29:\"callbackOnAfterUpdateComments\";s:0:\"\";s:20:\"commentPagesUrlRegex\";s:0:\"\";s:16:\"disableUrlUpdate\";b:1;s:21:\"disableScrollToAnchor\";b:0;s:22:\"useUncompressedScripts\";b:0;s:20:\"placeScriptsInFooter\";b:1;s:20:\"optimizeAjaxResponse\";b:0;s:7:\"baseUrl\";s:0:\"\";s:12:\"disableCache\";b:0;s:13:\"enableByQuery\";b:0;s:15:\"lazyLoadEnabled\";b:1;s:15:\"lazyLoadDisplay\";s:7:\"overlay\";s:15:\"lazyLoadTrigger\";s:8:\"comments\";s:22:\"lazyLoadTriggerElement\";s:0:\"\";s:28:\"lazyLoadInlineDisplayElement\";s:9:\"#comments\";s:16:\"firstTimeInstall\";s:0:\"\";}' ) ); ?>"
		},
		{
			"step": "runPHP",
			"code": "<?php require_once 'wordpress/wp-load.php'; update_option( 'generateblocks_dynamic_css_posts', array() ); ?>"
		},
		{
			"step": "runPHP",
			"code": "<?php require_once 'wordpress/wp-load.php'; $locations = array(); $locations['menu_1'] = 2; set_theme_mod( 'nav_menu_locations', $locations ); ?>"
		}

		
    ]
}Code language: JSON / JSON with Comments (json)

The blueprint.json file takes in initialization properties and then moves on to an option called Steps. I recommend a quick readthrough of all the possibilities of Steps and how to use them. We’ll be going over Steps later in this tutorial.

Blueprints and WordPress.org plugin live previews

WordPress plugin advanced screen with no blueprint warning
Blueprints Section in the Advanced Tab on WordPress.org

WordPress introduced Live Previews to the masses in November of 2023. Live Previews allow users to preview your plugin directly from .org. Since its initial launch, it’s been opt-in for plugin authors to show a live preview or not.

The screenshot above shows what you would see if you visited the Advanced section of your .org plugin and are logged in.

In order to set up a live preview, you’ll need a valid blueprint.json file. In order to create the file, you’ll want to configure your local environment and set up the file based on that site’s settings.

Let’s dive into how to set up a blueprint.json file using my plugin WP Plugin Info Card as an example.

Step 1: set up a new local site

For this example, I’m going to use the free local environment tool Local.

Local New Site Modal
Local New Site Modal

Let’s create a new site. You’ll be taken to a screen that asks what type of installation you’d like.

New Site Modal for Local
New Site Modal for Local

Clicking on Continue will take you to a screen where you can enter your site title and modify any local URLs.

Set a Site Name and Local URLs
Set a Site Name and Local URLs

Clicking on Continue will take you to the screen where you can configure the site’s PHP, web server, and MySQL versions.

Custom Screen When Setting a New Site
Custom Screen When Setting a New Site

I chose Custom and set the following:

  • PHP version: v8.1.23
  • Web server: Apache v2.4.43
  • Database: MySQL v5.728

Clicking on Continue will take you to a screen where you’ll enter the site’s credentials.

Credentials Screen on Local
Credentials Screen on Local

Clicking on Add Site will create the site for you. This may take several minutes as Local may need to download assets.

Site Creation Screen in Local
Site Creation Screen in Local

If the site’s creation was successful, you’ll be taken to a Dashboard-like screen with shortcuts to the new site’s admin.

Local Dashboard Screen for New Site
Local Dashboard Screen for New Site

If all is well, you should be able to visit the admin by clicking on WP Admin.

New Site for Blueprint Creation
New Site for Blueprint Creation

We’re now ready to start setting up our demo site for the plugin.

Step 2: configure and set up the created local site

New Site's Posts List View Screen
New Site’s Posts List View Screen

You’ll want to start setting up the site for the demo. This means things like deleting the “Hello World” post, setting permalinks and general settings, adding plugins and themes, and populating content.

Since this tutorial covers WP Plugin Info Card, that’s one of the plugins we’ll need to install.

Plugin Info Card on the Add New Plugins Screen
Plugin Info Card on the Add New Plugins Screen

I’m going to install a few other plugins (shown below) to complete the demo.

I ended up having a plugin screen like the following:

Plugins Screen on Plugin Demo Site
Plugins Screen on Plugin Demo Site

Next, I’ll be adding the Astra theme.

Astra Installation Screen in WordPress
Astra Installation Screen in WordPress

Astra is a nice utility theme that is compatible with a ton of plugins.

Now, it’s time for me to create a new page that will house the plugin’s demo content.

I gave the page a title of ‘Demo’ so that the permalink is easy to remember and type in.

Sample Demo Page for Plugin Live Preview
Sample Demo Page for Plugin Live Preview

Step 3: generate an export file

With our page created, I can head to Tools->Export and export all the page content.

Export Content Functionality of WordPress
Export Content Functionality of WordPress

I recommend saving this file in your plugin’s GitHub repo so that GitHub can “host” the file for you publicly.

Saving the Generated XML File From WordPress
Saving the Generated XML File From WordPress

Step 4: Configure blueprint.json properties

The blueprint.json file supports the following properties, per its schema:

  • landingPage – Where should the user end up when launching the demo? This can be a landing page, admin settings, or some type of wizard.
  • preferredVersions – This will house the preferred WordPress and PHP versions for the Playground.
  • phpExtensionBundles – This tells Playground what PHP extensions to load.
  • features – This tells Playground how it should be configured.
  • steps – Steps to take prior to displaying the site to the user.

Here’s a sample blueprint.json file with all of the properties:

{
    "$schema": "https://playground.wordpress.net/blueprint-schema.json",
    "preferredVersions": {
        "php": "8.1",
        "wp": "latest"
    },
    "features": {
        "networking": true
    },
    "phpExtensionBundles": [
        "kitchen-sink"
    ],
    "landingPage": "/demo/",
    "steps": [
        {
            "step": "login",
            "username": "admin",
            "password": "password"
        },
    ]
}Code language: JSON / JSON with Comments (json)

This blueprint.json file is pretty simple, with the landing page set and the user logged in when launching the demo. The one property you want to pay special attention to is features and networking. In general, you want to have networking enabled.

For the steps property, this can be a rabbit hole as there are many, many options available. In this example, the only step taken is to log the user in.

Step 5: generating the blueprint.json file

For generating the blueprint.json file, I highly recommend using a GitHub-hosted plugin called Blueprint Builder. You can download the zip of the plugin by visiting Blueprint Builder’s GitHub.

Download ZIP option from the GitHub repository
Download ZIP Option on GitHub

With the plugin installed, navigate to the top-level menu item Blueprint Builder. You’ll see a textarea with all the blueprint.json settings that you can copy into your own file.

Blueprint Builder JSON Output
Blueprint Builder JSON Output

Just as with the XML content file, I recommend saving the blueprint.json file in your plugin’s GitHub root so that the file can be accessed publicly.

Blueprint JSON File Save Dialogue
Blueprint JSON File Save Dialogue

With the blueprint.json file saved, it’s time to prune it and modify any steps.

The first thing I need to do with the output is change the WordPress version to “latest,” as I don’t want to have to update the blueprint.json file for each WP version update. I’m also needing to update the landing page.

Updating the Blueprint.json Landing Page
Updating the Blueprint.json Landing Page

The next “step” is ensuring a valid login and installing the needed themes and plugins.

"steps": [
	{
		"step": "login",
		"username": "admin",
		"password": "password"
	},
	{
		"step": "installTheme",
		"themeZipFile": {
			"resource": "wordpress.org/themes",
			"slug": "astra"
		},
		"options": {
			"activate": true
		}
	},
	{
		"step": "installPlugin",
		"pluginZipFile": {
			"resource": "wordpress.org/plugins",
			"slug": "alerts-dlx"
		},
		"options": {
			"activate": true
		}
	},
	{
		"step": "installPlugin",
		"pluginZipFile": {
			"resource": "wordpress.org/plugins",
			"slug": "slash-edit"
		},
		"options": {
			"activate": true
		}
	},
	{
		"step": "installPlugin",
		"pluginZipFile": {
			"resource": "wordpress.org/plugins",
			"slug": "highlight-and-share"
		},
		"options": {
			"activate": true
		}
	},
	{
		"step": "installPlugin",
		"pluginZipFile": {
			"resource": "wordpress.org/plugins",
			"slug": "pattern-wrangler"
		},
		"options": {
			"activate": true
		}
	},
	{
		"step": "installPlugin",
		"pluginZipFile": {
			"resource": "wordpress.org/plugins",
			"slug": "slash-edit"
		},
		"options": {
			"activate": true
		}
	},
	{
		"step": "installPlugin",
		"pluginZipFile": {
			"resource": "wordpress.org/plugins",
			"slug": "wp-plugin-info-card"
		},
		"options": {
			"activate": true
		}
	},
	{
		"step": "installPlugin",
		"pluginZipFile": {
			"resource": "wordpress.org/plugins",
			"slug": "simple-comment-editing"
		},
		"options": {
			"activate": true
		}
	},
]Code language: JSON / JSON with Comments (json)

For importing content, we’ll need a public URL to grab from, which is why I recommend storing these in GitHub, as you can click on the file and get the raw URL of the file.

GitHub Raw Option When Viewing the XML File
GitHub Raw Option When Viewing the XML File

The public URL would look something like this:

https://raw.githubusercontent.com/DLXPlugins/wp-plugin-info-card/dev/blueprint-content.xmlCode language: JavaScript (javascript)

Now, we can create a new step, which will download the content from the hosted XML file.

{
	"step": "importWxr",
	"file": {
		"resource": "url",
		"url": "https://raw.githubusercontent.com/DLXPlugins/wp-plugin-info-card/dev/blueprint-content.xml"
	}
},Code language: JSON / JSON with Comments (json)

Next are options. These can be fairly straightforward, but things get mucky when serialized data is involved.

Here’s an example of setting a group of options:

{
	"step": "setSiteOptions",
	"options": {
		"blogname": "WP Plugin Info Card Demo",
		"admin_email": "dev@test.local",
		"permalink_structure": "/%postname%/",
		"template": "astra",
		"stylesheet": "astra"
	}
},Code language: JSON / JSON with Comments (json)

We’ll also need to save the options for WP Plugin Info Card, but the options are serialized and blueprint.json doesn’t recognize this.

The solution is to run custom PHP code and pass in the serialized options to the WordPress function maybe_unserialize.

Here’s an example for WP Plugin Info Card:

{
	"step": "runPHP",
	"code": "<?php require_once 'wordpress/wp-load.php'; update_option( 'wppic_settings', maybe_unserialize( 'a:18:{s:14:\"default_layout\";s:4:\"card\";s:11:\"colorscheme\";s:7:\"default\";s:6:\"widget\";b:0;s:4:\"ajax\";b:0;s:7:\"enqueue\";b:0;s:6:\"credit\";b:0;s:16:\"cache_expiration\";s:4:\"3600\";s:18:\"enable_screenshots\";s:1:\"1\";s:24:\"enable_local_screenshots\";s:0:\"\";s:18:\"skip_animated_gifs\";s:1:\"1\";s:41:\"enable_local_screenshots_download_missing\";s:0:\"\";s:37:\"enable_local_screenshots_keep_current\";s:0:\"\";s:36:\"enable_local_screenshots_cli_command\";s:0:\"\";s:25:\"screenshots_table_version\";s:5:\"0.0.0\";s:9:\"saveNonce\";s:10:\"d9f5901be7\";s:10:\"resetNonce\";s:10:\"cfbb070da3\";s:4:\"list\";a:0:{}s:10:\"theme-list\";a:0:{}}' ) ); ?>"

}Code language: PHP (php)

That is it for setting up the blueprint.json file.

Here’s what I ended up with:

{
	"$schema": "https://playground.wordpress.net/blueprint-schema.json",
	"preferredVersions": {
		"php": "8.1",
		"wp": "latest"
	},
	"features": {
		"networking": true
	},
	"phpExtensionBundles": [
		"kitchen-sink"
	],
	"landingPage": "/demo/",
	"steps": [
		{
			"step": "login",
			"username": "admin",
			"password": "password"
		},
		{
			"step": "installTheme",
			"themeZipFile": {
				"resource": "wordpress.org/themes",
				"slug": "astra"
			},
			"options": {
				"activate": true
			}
		},
		{
			"step": "installPlugin",
			"pluginZipFile": {
				"resource": "wordpress.org/plugins",
				"slug": "alerts-dlx"
			},
			"options": {
				"activate": true
			}
		},
		{
			"step": "installPlugin",
			"pluginZipFile": {
				"resource": "wordpress.org/plugins",
				"slug": "slash-edit"
			},
			"options": {
				"activate": true
			}
		},
		{
			"step": "installPlugin",
			"pluginZipFile": {
				"resource": "wordpress.org/plugins",
				"slug": "highlight-and-share"
			},
			"options": {
				"activate": true
			}
		},
		{
			"step": "installPlugin",
			"pluginZipFile": {
				"resource": "wordpress.org/plugins",
				"slug": "pattern-wrangler"
			},
			"options": {
				"activate": true
			}
		},
		{
			"step": "installPlugin",
			"pluginZipFile": {
				"resource": "wordpress.org/plugins",
				"slug": "slash-edit"
			},
			"options": {
				"activate": true
			}
		},
		{
			"step": "installPlugin",
			"pluginZipFile": {
				"resource": "wordpress.org/plugins",
				"slug": "wp-plugin-info-card"
			},
			"options": {
				"activate": true
			}
		},
		{
			"step": "installPlugin",
			"pluginZipFile": {
				"resource": "wordpress.org/plugins",
				"slug": "simple-comment-editing"
			},
			"options": {
				"activate": true
			}
		},
		{
			"step": "importWxr",
			"file": {
				"resource": "url",
				"url": "https://raw.githubusercontent.com/DLXPlugins/wp-plugin-info-card/dev/blueprint-content.xml"
			}
		},
		{
			"step": "setSiteOptions",
			"options": {
				"blogname": "WP Plugin Info Card Demo",
				"admin_email": "dev@test.local",
				"permalink_structure": "/%postname%/",
				"template": "astra",
				"stylesheet": "astra",
				"comment-edit-lite-activate": "noredirect"
			}
		},
		{
			"step": "runPHP",
			"code": "<?php require_once 'wordpress/wp-load.php'; update_option( 'wppic_settings', maybe_unserialize( 'a:18:{s:14:\"default_layout\";s:4:\"card\";s:11:\"colorscheme\";s:7:\"default\";s:6:\"widget\";b:0;s:4:\"ajax\";b:0;s:7:\"enqueue\";b:0;s:6:\"credit\";b:0;s:16:\"cache_expiration\";s:4:\"3600\";s:18:\"enable_screenshots\";s:1:\"1\";s:24:\"enable_local_screenshots\";s:0:\"\";s:18:\"skip_animated_gifs\";s:1:\"1\";s:41:\"enable_local_screenshots_download_missing\";s:0:\"\";s:37:\"enable_local_screenshots_keep_current\";s:0:\"\";s:36:\"enable_local_screenshots_cli_command\";s:0:\"\";s:25:\"screenshots_table_version\";s:5:\"0.0.0\";s:9:\"saveNonce\";s:10:\"d9f5901be7\";s:10:\"resetNonce\";s:10:\"cfbb070da3\";s:4:\"list\";a:0:{}s:10:\"theme-list\";a:0:{}}' ) ); ?>"
		}
	]
}Code language: JSON / JSON with Comments (json)

Step 6: testing the blueprint.json file

As with the XML file, if you host the blueprint.json file with your plugin, the file will be publicly available when viewed in raw form.

Blueprint Public JSON File
Blueprint Public JSON File

Armed with the public URL of the blueprint.json file, we can test it by appending ?blueprint-url= to the WordPress Playground URL. For example:

https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/DLXPlugins/wp-plugin-info-card/dev/blueprint.jsonCode language: JavaScript (javascript)
Animated Gif of WordPress Playground
Animated GIF of WP Plugin Info Card on the WordPress Playground

Step 7: add the blueprint to SVN

In order to have a blueprint display on .org, you’ll need to add it to your SVN repository. It needs to be in a blueprints folder under your assets folder.

.
└── assets/
    └── blueprints/
        └── blueprint.xmlCode language: AsciiDoc (asciidoc)

Once the blueprints folder has been created and the blueprint.json file has been added, it’s time to commit the changes and enable the live preview on .org.

SVN in the Versions App for Mac
SVN in the Versions App for Mac

Step 8: enable live previews on your plugin page

Make sure you are logged in to WordPress.org, visit your plugin, and head to the Advanced settings.

Advanced View Screenshot
Advanced View Screenshot

From there, you can enable the Live Preview:

Toggle Live Preview On or Off With the Advanced Option
Toggle Live Preview On or Off With the Advanced Option

Once toggled, you should see a Live Preview at the top of your plugin page.

Live Preview Link on WordPress.org Plugin
Live Preview Link on WordPress.org Plugin

Conclusion

In this tutorial, I explained what the WordPress Playground is, what blueprints are, and how to enable a live preview for your WordPress plugin.

If you need more examples of blueprint.json, here are a few. Feel free to comment out yours too if you have one.

Thanks for reading. Feel free to comment below if you have questions or find me on Twitter @mediaronllc.

Like this tutorial? There's more like it. Subscribe today!

Name(Required)

Ronald Huereca
By: Ronald Huereca
Published On: on May 23, 2024

Ronald Huereca founded DLX Plugins in 2022 with the goal of providing deluxe plugins available for download. Find out more about DLX Plugins, check out some tutorials, and check out our plugins.

Leave Your Valuable Feedback

Your email address will not be published. Required fields are marked *

Shopping Cart
  • Your cart is empty.
Scroll to Top