Developers / CalendarWP
Build your first add-on
Build a small Visitor Note add-on: an editor enters a public note once, Upcoming Events displays it, and Compass can include it in event knowledge. No AI account, external service or custom database table is needed.
What the example connects
| Step | WordPress or CalendarWP extension point | Result |
|---|---|---|
| 1. Load safely | WordPress init and dependency checks |
No fatal error when core is absent |
| 2. Register the feature | calendarwp_options_addons_registry |
Its own Add-ons entry and enable toggle |
| 3. Enter a public note | WordPress meta box and save_post |
Sanitized event metadata, protected by nonce and capability checks |
| 4. Display it | calendarwp_upcoming_events_item_meta |
Escaped note on event cards |
| 5. Share public facts | calendarwp_event_knowledge_public_sections |
A named section in event Markdown |
Get the example
Download the complete PHP example as plain text. It is served as text intentionally; it is not a plugin installer. The sample is GPL-3.0-or-later. Rename and adapt it for your own project.
- On a staging site, create
wp-content/plugins/acme-calendarwp-note/. - Save the downloaded contents as
acme-calendarwp-note.phpinside that directory, removing the final.txtsuffix. - Activate it in Plugins while CalendarWP core is active.
- Open CalendarWP > Add-ons and enable Visitor Note (example). Its default is disabled.
- Edit an event. Find Public visitor note, add a short verified note and update the event.
- View an Upcoming Events list containing that event. If Compass is enabled, also preview the event's Markdown under Compass > Knowledge.
In the block editor, the meta box appears below the main editor rather than inside CalendarWP's React Event Data panel. The example does not alter that panel.
Key registration details
Register your unique add-on ID and keep the feature gate separate from WordPress plugin activation:
$addons['acme-visitor-note'] = array(
'label' => __( 'Visitor Note (example)', 'acme-calendarwp-note' ),
'description' => __( 'Public notes on event cards and in event knowledge.', 'acme-calendarwp-note' ),
'default' => '0',
'plugin_file' => 'acme-calendarwp-note/acme-calendarwp-note.php',
'admin_url' => admin_url( 'edit.php?post_type=' . RHC_EVENT_POST_TYPE ),
'admin_label' => __( 'Edit events', 'acme-calendarwp-note' ),
);
Check RHC_Admin_Options::is_addon_enabled( 'acme-visitor-note', '0' ) before registering the feature's UI and rendering callbacks. The download includes dependency guards and the complete implementation.
The sample checks core 1.0.58-rc27 or newer, WordPress 6.7 and PHP 8.2. A custom Requires CalendarWP header can describe compatibility, but it does not replace runtime dependency checks. WordPress's standard plugin header fields are described in the Plugin Handbook.
Test before shipping your version
- Core absent or inactive: your plugin must not cause a fatal error.
- Feature disabled: no note editor or public contribution; retained data is not deleted.
- Editor with permission: can save a note. Missing nonce, autosave or insufficient capability: no update.
- HTML entered into the note: stored as plain text and escaped on output.
- Private, draft, password-protected and Personal Calendar events: no newly exposed public facts.
- Recurring events: the same series note appears consistently without changing schedules or availability.
- Compass absent: event-card notes continue working. Compass present: preview the refreshed Markdown.
- Upgrade and deactivate: retain notes unless the owner explicitly chooses data removal.
The example has no remote requests, booking actions, payment handling or uninstall deletion. It is deliberately small. Add your own translations, documentation, accessibility tests and update distribution before offering a commercial add-on.
Grow without coupling to internals
Use your own block namespace and block.json if you need an editor block. Register your own namespaced REST routes only when necessary, with explicit permissions and validation. Enqueue assets only on the screens that need them. Avoid copying CalendarWP's private classes or changing its generated JavaScript.
For public facts from your own settings or external integration, read the knowledge hook contract. Keep live inventory and payment state out of static Markdown.