Skip to content
Nibiru docsv0.9.2

In production

Real Nibiru apps shipping real revenue. Maschinen Stockert sells industrial machinery in 12 countries on this framework.

Stable Reading time ~ 4 min Edit on GitHub

A framework worth using ships things. The flagship Nibiru deployment is the Maschinen Stockert group — a pair of repositories powering one of Austria’s larger industrial-machinery e-commerce platforms.

The two repos share modules and a database; they split responsibility by audience.


An industrial CNC machine on a factory floor at golden hour.

10 controllers · 18 modules · 150 templates · 36,289 lines of PHP

maschinen-stockert.de — public catalogue

The buyer-facing site. Browse and search refurbished industrial machinery, view rich detail pages with SEO-friendly slugs, register for the annual Hausmesse trade show, request quotes.

maschinen-stockert.de — public catalogue

Section titled “maschinen-stockert.de — public catalogue”

The public face: where industrial buyers land, search, and convert.

  • Multilingual content, with every visible string fetched from the cms_template_texts database keyed by <controller>/<action> + language. Editors update copy from the admin without a deploy.
  • Elasticsearch-powered machine search, with type-aware filtering — dimensions parsed from "2500 × 1200 mm" strings into numeric ranges so buyers can search by size.
  • SEO-friendly URLs/maschine/drehmaschine-2500/42 — generated from the machine name with German umlaut normalisation (ä → ae, ß → ss). The numeric ID always trails so the router can resolve a stale slug.
  • Yumpu PDF flipbooks for downloadable catalogues.
  • Hausmesse module for trade-show registration with role-aware access.
application/controller/maschineController.php
public function detailAction()
{
$machineId = $this->getRequest('id', true);
if (!$machineId) {
http_response_code(404);
return;
}
$controllerPath = $this->getController() . '/detail';
$cmsTemplateTexts = Cms::init($this->getController())
->loadCmsTemplateTextsByControllerPath($controllerPath, $this->language);
foreach ($cmsTemplateTexts as $t) {
View::assign([
$t['cms_template_texts_text_identifier']
=> $t['cms_template_texts_text_content']
]);
}
try {
$machine = Machine::init()->getMachine((int) $machineId);
} catch (\Throwable $e) {
$machine = null; / DB blip page still renders with fallback.
}
$machineName = $machine['ms_machines_name'] ?? "Maschine #$machineId";
$protocol = (($_SERVER['HTTPS'] ?? '') === 'on') ? 'https' : 'http';
View::assign([
'machine' => $machine,
'pageTitle' => "$machineName - Maschinen Stockert",
'metaDescription'=> "Details und Spezifikationen für $machineName",
'canonicalUrl' => $protocol . '://' . $_SERVER['HTTP_HOST']
. self::generateMachineSeoUrl($machineId, $machineName),
]);
}

50 lines, no DI container, no validation pipeline, no middleware stack. Loads CMS-managed copy first (so a DB outage on machines doesn’t kill the page), pulls the machine with a graceful fallback, generates SEO metadata always. The whole detail page renders with two database round-trips.


A wall of well-worn leather technical books, one open in soft focus.

36 controllers · 18 modules · 348 templates · 161 SQL migrations · 37,369 lines of PHP

data.maschinen-stockert.de — admin & API

The internal cockpit. Sales staff manage inventory, content, jobs, team pages, trade-show registrations. Developers and integrations call REST APIs to search machines, sync manufacturers, generate PDFs, hit Ollama for AI machine descriptions.

data.maschinen-stockert.de — admin & API

Section titled “data.maschinen-stockert.de — admin & API”

The same modules, three times the controllers and templates — because admin UIs and APIs need many entry points.

  • Page-tree CMS: editors build pages from a Smarty template; the Parser plugin scans {$identifier} placeholders in the template and auto-generates the editable-fields admin UI. The template is the form spec.
  • Role-based ACL: every admin controller’s constructor calls $this->user = new User(); $this->acl = new Acl(); $this->acl->init(); $this->user->validate(); — three lines, done. Sales has read-only on inventory; admins can edit; partners see only their assigned listings.
  • Public-API whitelist: apiController allows machine search, category fetch, team info, Ollama AI calls without auth, then requires auth for everything else. The whitelist is right in the constructor — no middleware ordering bugs.
  • Machineryscout indexer: the heaviest module. 2,200-line trait that pulls machines + attributes + images + documents from MySQL via JSON_ARRAYAGG, normalises types ("2500 x 1200"dimension_width: 2500.0, dimension_height: 1200.0), substitutes placeholders for missing images, and ships rows into Elasticsearch.

The Parser pattern — auto-generating editor UIs from a template

Section titled “The Parser pattern — auto-generating editor UIs from a template”
application/controller/adminController.php
$parser = Parser::init();
$cmsEditable = $parser->parseSmartyTemplateByTemplateId($templateId);
View::assign([
'cmsEditable' => $cmsEditable,
'cmsTemplateTextForm'=> Cms::textsEditingForm('/admin/texts/create/text/new'),
]);

Drop a new Smarty template in the system, the editor immediately knows which placeholders are editable. No “register the form fields” step.


The five differentiators below are pulled from the codebases above. Each links to its evidence on the Why Nibiru page.

What Nibiru doesWhat Laravel/Symfony does
Page copyLoaded from DB by <controller>/<action> per request, editor-managed.Hardcoded in Blade / translation JSON; deploy to change.
Module composition13 traits per module, no DI.Service providers + IoC container.
ORMDirect SQL, MySQL JSON_ARRAYAGG, Pdo::fetchAll.Eloquent / Doctrine entities + lazy-loading proxies.
Auth3 lines in the controller constructor.Middleware stack + policy classes + gates.
EventsSplSubject + SplObserver from PHP stdlib.Custom event dispatcher + listener registry + queue.

Read the full breakdown with code references →


Maschinen Stockert is a real, revenue-generating site selling machinery in 12 countries. It moved 161 timestamped SQL migrations into production with no migration framework, 74,000 lines of PHP across two repos with no service container, and 18 modules that compose with traits instead of inheritance. The team that built and runs it is small.

That’s the proof.

If you’re shipping with a small team, on tight budget, into production where deploys and downtime cost real money — that’s the Nibiru sweet spot. Read the Quick Start, then come back.