Docs / Developers
The example add-on plugin
A complete, working add-on ships inside Craftor's own plugin folder.
Craftor's plugin folder includes examples/craftor-hello-addon — a real, single-file WordPress plugin you can copy into wp-content/plugins, rename, and build on directly. Activate it alongside Craftor and it registers:
- A "Callout (Hello Add-on)" widget — heading, message, and background color controls.
- A "Log Submission (Hello Add-on)" workflow action — appends each submission to a small rolling log (a WordPress option), so it works immediately with nothing else to configure.
- Two lifecycle hooks in use: craftor/form/after_submit (writes to the PHP error log) and craftor/email/headers (Bcc's every form notification to the site admin).
add_action( 'plugins_loaded', 'craftor_hello_addon_bootstrap' );
function craftor_hello_addon_bootstrap(): void {
if ( ! class_exists( '\Craftor\Widgets\AbstractWidget' ) ) {
return; // Craftor isn't active.
}
craftor_hello_addon_define_classes(); // declares the widget + action classes
add_action( 'craftor/register_widgets', 'craftor_hello_addon_register_widget' );
add_action( 'craftor/register_workflow_actions', 'craftor_hello_addon_register_action' );
add_action( 'craftor/form/after_submit', 'craftor_hello_addon_log_submission', 10, 6 );
add_filter( 'craftor/email/headers', 'craftor_hello_addon_bcc_admin_on_notifications', 10, 3 );
}Notice the widget/action classes are declared inside a function (craftor_hello_addon_define_classes()), called only after the class_exists() check passes — not as top-level `class Foo extends ...` statements. This sidesteps a real plugin-load-order bug: WordPress loads active plugins in an unspecified order, and a top-level extends of a Craftor base class can fatal if your file happens to load before Craftor's own. Keep the same structure in your own add-on.