AJAX
AJAX lets pages communicate with the server in the background without a full reload. Lumbermill provides a typed action system for registering and calling AJAX endpoints.
Getting started
Section titled “Getting started”AJAX is disabled by default. Run the activate command to enable it and scaffold an example action:
wp instance activate ajaxThis sets enabled => true in config/ajax.php and creates app/Ajax/Action/ExampleAjaxAction.php.
How to use AJAX
Section titled “How to use AJAX”To add an AJAX endpoint you need to:
- Create an AJAX action class
- Register the action in config
- Add a nonce attribute to your markup
- Call the action from JavaScript
Create an AJAX action
Section titled “Create an AJAX action”Use the generate command to scaffold a new action class:
wp instance make ajax GetPosts# → app/Ajax/Action/GetPostsAjaxAction.phpOr create it manually in app/Ajax/Action/. Every action class must extend BaseAjaxAction:
<?php
namespace App\Ajax\Action;
use App\Lib\Ajax\BaseAjaxAction;
class GetPostsAjaxAction extends BaseAjaxAction{ protected function callback(): void { // Your code here }}Returning data
Section titled “Returning data”Use success() or error() to return JSON to the client:
protected function callback(): void{ $this->success([ 'message' => 'Hello world!' ]);}Register the AJAX action
Section titled “Register the AJAX action”Add the action to config/ajax.php:
use App\Ajax\Action\GetPostsAjaxAction;
return [ 'enabled' => true, 'actions' => [ 'getPosts' => [ 'class' => new GetPostsAjaxAction, ], ],];Add markup
Section titled “Add markup”Add a nonce attribute to the element that triggers the action:
<button data-nonce="{{ nonce_ajax('ajax.actions.getPosts') }}" class="ajax-button"> Get posts</button>Note: The argument passed to nonce_ajax is the action key from the config.
Connect with JavaScript
Section titled “Connect with JavaScript”import { createClient } from '@/lib/AjaxClient';
const button = document.querySelector('.ajax-button');const nonce = button.dataset.nonce;
const getPostsClient = createClient('getPosts', nonce);
button.addEventListener('click', async () => { const response = await getPostsClient.post(); const data = await response.json(); console.log(data);});Sending data to the server
Section titled “Sending data to the server”Pass an object to post() to send data:
getPostsClient.post({ foo: 'bar',});Access it server-side with the typed request helpers:
protected function callback(): void{ $foo = $this->requestVarString('foo'); // 'bar'}Available helpers: requestVarString, requestVarInt, requestVarFloat, requestVarBool.
What is a nonce?
Section titled “What is a nonce?”A nonce is like a secret code that changes every time you want to send a message. It adds an extra layer of security by ensuring that even if someone figures out the code once, it won’t work again because it’s always different.

