Extending Lay Theme and AI Mode
Build project-specific functionality as a WordPress plugin and expose only the safe operations an AI assistant needs.
This is the next step when a request goes beyond the Browser Bridge. First let Claude, ChatGPT or another coding assistant use the existing AI Mode capabilities. If the required server-side feature is not available, ask it to build a separate WordPress plugin instead of changing Lay Theme files.
This does not give website visitors access to Lay content. Plugin functions run as server-side code and are not web endpoints. If a plugin deliberately exposes an operation to the Browser Bridge, it must use WordPress permissions and Lay Theme's authenticated validate → confirm → apply workflow.
What Is a WordPress Plugin?
A WordPress plugin is an installable package of PHP, JavaScript and CSS that adds functionality to a website independently of its theme. It stays installed when Lay Theme is updated.
Changes made through AI Mode and the Browser Bridge are saved in the WordPress database and also remain intact when Lay Theme is updated. Only direct code changes inside Lay Theme's own files are replaced by a theme update. Custom PHP therefore belongs in a separate plugin.
Modern AI coding assistants are very good at creating focused WordPress plugins. Describe the feature, let the assistant create and test the plugin, then install the resulting ZIP under Plugins → Add New Plugin. The official WordPress Plugin Developer Handbook explains the plugin structure, security, hooks, admin screens, data storage, REST APIs and scheduled tasks.
A plugin can add, for example:
- New content types, fields and database tables.
- Scheduled emails, reports, imports and exports.
- Custom admin screens, URLs, REST endpoints and integrations with external services.
- Server-side or WordPress-wide functionality that is not covered by the existing AI Mode capabilities.
The APIs below give that plugin a supported way to read or update Lay content, react to Lay Theme events, and optionally expose its own data and safe actions back to the Browser Bridge.
Plugin or AI Mode?
- Use existing AI Mode capabilities for content, layouts, Custom Fields, Custom Elements, Custom Views, settings and media.
- Use a plugin for a new content model, scheduled task, custom URL, report, export, dashboard screen or other server-side WordPress functionality that AI Mode does not provide.
- Use the extension provider API when the plugin should also be readable or safely changeable through AI Mode.
- Ask for a new Lay Theme hook when a plugin cannot reach the required lifecycle event through the supported plugin API. Do not access private theme internals as a workaround.
Register an AI Mode Provider
Register providers on lay_ai_register_extensions. A provider can publish focused read-only resources and validated actions. Action IDs must start with the provider ID followed by a dot.
add_action( 'lay_ai_register_extensions', function () {
lay_ai_register_extension_provider( 'studio-tools', array(
'name' => 'Studio tools',
'description' => 'Project-specific presentation data.',
'resources' => array(
'presentations' => array(
'description' => 'Compact presentation index.',
'callback' => 'studio_tools_get_presentations',
),
),
'actions' => array(
'studio-tools.presentation.update' => array(
'description' => 'Update one presentation.',
'schema' => array(
'postId' => 'presentation post ID',
'definition' => array( 'title' => 'string' ),
),
'prepare' => 'studio_tools_prepare_update',
'apply' => 'studio_tools_apply_update',
'rollback' => 'studio_tools_rollback_update',
),
),
) );
} );
The provider appears in GET /wp-json/laytheme/v1/ai/extensions. Each resource receives its own endpoint at /wp-json/laytheme/v1/ai/extensions/{provider}/{resource}. Resource callbacks are read-only by convention and use the normal AI Mode read permission unless a permission_callback is supplied.
Prepare, Apply and Roll Back
An action's prepare callback validates and normalizes the request. It must return complete before and after snapshots. Nothing should be written during this step.
function studio_tools_prepare_update( $change ) {
$post_id = absint( $change['postId'] );
if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
return new WP_Error( 'studio_tools_forbidden', 'Choose an editable presentation.' );
}
$before = get_post_meta( $post_id, '_studio_presentation', true );
$after = $before;
$after['title'] = sanitize_text_field( $change['definition']['title'] );
return array(
'label' => 'Update presentation',
'target' => 'presentation:' . $post_id,
'postId' => $post_id,
'before' => $before,
'after' => $after,
);
}
function studio_tools_apply_update( $change ) {
update_post_meta( $change['postId'], '_studio_presentation', $change['after'] );
return array(
'postId' => $change['postId'],
'_rollback' => array( 'postId' => $change['postId'] ),
);
}
function studio_tools_rollback_update( $operation ) {
update_post_meta( $operation['payload']['postId'], '_studio_presentation', $operation['before'] );
}
AI Mode includes provider actions in its regular validate → confirm → apply workflow. The assistant must validate the plan, apply that exact planHash with confirm: true, then read the affected resource again. If an action creates a new object, its apply result can include _rollback data for the rollback callback.
Gridder and Content API
Use these functions instead of reading or writing private Gridder meta keys:
lay_get_gridder_document( $post_id, 'desktop' )returns the normalized Desktop or Phone document.lay_update_gridder_document( $post_id, $document, 'desktop', 'my-plugin' )saves through Lay Theme's normal normalization, preview and cache path.lay_get_content_context( $post_id )returns the structured post context used by Liquid-compatible Custom Elements and Views.lay_prepare_gridder_rows( $document )returns the same canonical Row structure Lay uses on the frontend.lay_get_gridder_rows_margin_css( $document, $rows, '.presentation', false )creates native Row spacing CSS for a composed layout.lay_get_custom_field_group_values()andlay_update_custom_field_group_values()read or validate and save one native Custom Field group.lay_get_site_chrome_visibility()andlay_update_site_chrome_visibility()control the site title, menus and footer per post.
These helpers return WP_Error when a target or document is invalid. Preserve unknown document properties when changing part of a layout. Do not call internal classes such as Gridder, Lay_Layout, Lay_LayoutFunctions or Lay_Custom_Fields_Store directly.
$document = lay_get_gridder_document( $post_id, 'desktop' );
if ( ! is_wp_error( $document ) ) {
$rows = lay_prepare_gridder_rows( $document );
$css = lay_get_gridder_rows_margin_css( $document, $rows, '.studio-presentation', false );
}
lay_update_custom_field_group_values( $post_id, 'project', array(
'client' => 'Example Client',
'year' => '2026',
) );
The lay_gridder_document_saved action fires after Gridder saves from the normal editor, AI Mode and these supported plugin helpers. Use it for derived data such as automatically generated project title blocks.
Hooks and Filters
Lay Theme publishes a curated plugin API rather than treating every internal WordPress hook as permanent. See the separate Hooks & Filters reference for all supported functions, actions, filters and signatures.
Built-in Generic Site Tools
The lay-tools provider gives connected assistants a generic foundation that plugins can build on:
- A filterable content index with post type, status, title, slug, order, URL, categories, year and Custom Field values.
- Reversible content duplication that preserves Lay data, post meta, taxonomies and media references.
- Per-page SEO title, description, social preview, canonical URL, structured data and
noindex. - Reversible exact-path 301 and 302 redirects.
- A read-only site audit with indexing, security and layout-health references.
Project-specific UI, scheduled reports, exports and data models still belong in a plugin. A plugin can combine these generic resources with its own provider instead of copying theme code.
Compatibility Rules
- Check
function_exists()before using a Lay Theme helper so the plugin can fail gracefully on older versions. - Keep provider resources compact and focused. Use identifiers and summaries first, then request one detailed object.
- Validate permissions in addition to AI Mode's default administrator check when an action targets a specific post.
- Make every write reversible where practical and return a
WP_Errorinstead of partially applying invalid input. - Read back saved data after every applied plan.
Return to the AI Mode overview or review all AI Mode capabilities.