We assemble and install the first version of the package
Last updated Sep 3rd, 2026 | Page history | Improve this page | Report an issue
Support the team building MODX with a monthly donation.
The budget raised through OpenCollective is transparent, including payouts, and any contributor can apply to be paid for their work on MODX.
Backers
Budget
$204 per month—let's make that $500!
Learn moreIn the previous lesson we sketched the feature set, wrote a table schema, and generated an xPDO model for MySQL.
Today we build and install the first package version and look at how Custom Manager Pages fit together.
Build scripts (current modExtra)¶
The Sendex course originally used older filenames. Current scaffolds do not ship build.transport.php or build.config.php.
| MODX | Scaffold | Build entry | Config |
|---|---|---|---|
| 3.x | modx-pro/ModExtra3 | _build/build.php |
_build/config.inc.php |
| 2.x | modx-pro/modExtra | _build/build.php |
_build/config.inc.php |
Both put the working copy under an Extras/ directory at the site root, rename with rename_it.php, then build.
php ~/www/Extras/modExtra/rename_it.php Sendex
php ~/www/Extras/Sendex/_build/build.php
You can also open the build URL in a browser:
https://your-dev-site/Extras/Sendex/_build/build.php
Add ?download=1 to download the transport zip after the build.
In config.inc.php, auto-install is the 'install' => true flag (not a PKG_AUTO_INSTALL constant):
return [
'name' => 'Sendex',
'name_lower' => 'sendex',
'version' => '1.0.0',
'release' => 'pl',
'install' => true,
// ...
];
With 'install' => true, the script builds the package and installs it into Package Management in one run. If install is false, open Extras → Installer, search locally, and install the zip yourself.


Element lists live under _build/elements/ (for example menus.php, snippets.php). PHP files that do not start with . or _ are picked up automatically. Resolvers live in _build/resolvers/. See Component structure.
Menu¶
In MODX 3, modAction is gone. A menu item is a modMenu whose action field is the controller name inside your namespace.
Current modExtra / ModExtra3 define menus in _build/elements/menus.php:
return [
'sendex' => [
'description' => 'sendex_menu_desc',
'action' => 'home',
// 'parent' => 'components', // default in the build script
],
];
-
action→ controller filecore/components/sendex/controllers/home.class.php(class likeSendexHomeManagerController). -
parent→ usuallycomponents. Leave empty for a top-level item that only opens a submenu. -
handler→ optional JavaScript. Usereturn false;for a parent row that should not open a page.
Older Sendex commits still show _build/data/transport.menu.php with a nested action array for modAction. That pattern is historical. New work on MODX 3 should follow menus.php as above.
Customization for development¶
The project directory (for example Extras/Sendex) is the working tree. After install, MODX also has copies under core/components/sendex/ and assets/components/sendex/. Edits in Extras/Sendex do not change the installed files until you rebuild, unless you point the namespace at the project path.
Options:
- Rebuild and reinstall after every change.
- Point the namespace (and path settings) at
Extras/Sendexso the manager loads PHP/JS from the project.
For option 2: System → Namespaces, open the sendex namespace, set its path to the project core path (the ModExtra3 symlinks resolver can also link core and assets back into Extras/ for you).

Create system settings such as sendex_core_path and sendex_assets_url if your bootstrap still reads them (delete unused demo settings):


$corePath = $this->modx->getOption(
'sendex_core_path',
$config,
$this->modx->getOption('core_path') . 'components/sendex/'
);
$assetsUrl = $this->modx->getOption(
'sendex_assets_url',
$config,
$this->modx->getOption('assets_url') . 'components/sendex/'
);
During development you may enable error display in the web root index.php and manager/index.php (hosting panels often hide notices). Keep that off on production.
CMP controllers¶
When you click the menu item, MODX loads the controller named in action from the component's controllers/ directory.
ModExtra3's home controller extends MODX\Revolution\modExtraManagerController and already uses addCss() / addJavascript() / addHtml(). See controllers/home.class.php.
The Sendex lesson still walks an older chain (index.class.php → SendexMainController → home.class.php). The idea is the same: one entry controller loads component config and assets, then hands off to the page controller. You rarely need to change the entry file once paths are correct.
After a first install from the scaffold, open the CMP. Demo grids may error in the log until you replace processors. That is expected.


To verify that the namespace points at your project, temporarily add at the top of the active controller:
echo 'Hello world';
die;
Save, reload the CMP. If you see the message, the manager is reading your working copy.

Rebuilding can reset namespace paths. Adjust the resolver or namespace after install if you rely on the Extras/ tree. The Sendex history shows installer tweaks for that.
Basic controller methods¶
Useful methods on the home controller:
getPageTitle¶
Text for the manager page title (often a lexicon key).

getTemplateFile¶
Returns a Smarty template path, or an empty string if you inject markup in the controller (ModExtra3 appends a <div id="..."> in the controller and returns '').
getLanguageTopics¶
Lexicon topics to load, for example ['sendex:default'].
checkPermissions¶
Return true/false, or rely on menu permission fields so only allowed users open the CMP.

loadCustomCssJs¶
Registers CSS/JS for the page. This is where most CMP UI work happens.
Conclusion¶
You can build and install from _build/build.php, with install controlled in _build/config.inc.php. Menus on MODX 3 are modMenu rows with a string action, not modAction. Point the namespace at Extras/YourExtra when you want live edits without constant rebuilds.
Next lesson: ExtJS UI for the CMP.
Track Sendex history on GitHub: commit list. For new MODX 3 extras, start from ModExtra3.
Support the team building MODX with a monthly donation.
The budget raised through OpenCollective is transparent, including payouts, and any contributor can apply to be paid for their work on MODX.
Backers
Budget
$204 per month—let's make that $500!
Learn more










