Skip to content
Bondry

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.

  1. 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.
  2. Uninstalling removes only the module. It drops its own tables and its own migration records. The core is untouched, so a reinstall starts clean.
  3. A broken module never takes the site down. Boot is resilient: a module that throws is skipped and the site keeps serving.
  4. A module ships its own language files. They live in modules/<slug>/resources/lang and are loaded under a namespace (slug::file.key). Nothing goes into the core language files.
  5. No cross-module foreign keys, ever. A module can be uninstalled while another is running.
  6. No build step on the buyer's host. CSS and JS ship compiled inside the package. You run the build; the buyer does not.
  7. 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.meta and 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#