Building for Bondry
What a module is, what a theme is, and the rules that apply to both before you write a line.
Bondry is a Laravel application with a kernel that loads modules and themes at runtime. Everything you build is a directory with a manifest, packaged as a zip and installed from the panel.
The two things you can build#
| Artefact | Lives in | Manifest |
|---|---|---|
| Module | modules/<slug>/ |
module.json |
| Theme | themes/<slug>/ |
theme.json |
A language pack is a third package type, but it carries only translation files
and a language.json, and it needs no code.
The rules that never bend#
These are enforced by the kernel, not by convention. A package that breaks them is refused at install time.
- A module owns only its own tables. They are prefixed
mod_<slug>_, with hyphens turned into underscores. Reading core data is fine; creating, altering or dropping anything outside that prefix is not. - Uninstalling removes only the module. It drops its own tables and its own migration records. The core is untouched, so a reinstall starts clean.
- A broken module never takes the site down. Boot is resilient: a module that throws is skipped and the site keeps serving.
- A module ships its own language files. They live in
modules/<slug>/resources/langand are loaded under a namespace (slug::file.key). Nothing goes into the core language files. - No cross-module foreign keys, ever. A module can be uninstalled while another is running.
- No build step on the buyer's host. CSS and JS ship compiled inside the package. You run the build; the buyer does not.
- No inline script. The product runs a strict CSP. Behaviour lives in your bundled JS file.
Extending without touching the core#
Two mechanisms, and you will use both:
- Events for behaviour. The kernel and the modules dispatch events such as
a member registering or a post being created; you listen in your
boot(). - UI slots for interface. The core declares slots (
admin.menu,profile.tabs,search.sources,head.metaand others) and any module can fill them.
Nothing requires editing a core file, and a module that edits one will lose the edit on the next update.
Guarding a cross-module integration#
A module never knows whether another module is installed. Ask, do not assume:
PHP
if (class_exists(\App\Support\Breadcrumbs::class)) {
\App\Support\Breadcrumbs::push(__('directory::labels.title'), route('directory.index'));
}
if (\Illuminate\Support\Facades\Route::has('lms.catalog')) {
// Offer the integration only when the LMS is there.
}
Where to go next#
- Module anatomy for the folder and the manifest.
- Independence rules for the detail behind the list above.
- Routes, permissions and admin screens for wiring a module into the panel.
- Themes for the theme contract.
- Packaging and release format when you are ready to ship.