---
title: In production
description: Real Nibiru apps shipping real revenue. Maschinen Stockert sells industrial machinery in 12 countries on this framework.
---

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.

---

<div class="showcase-plate">
  <img src="/img/showcase-tpms.png" alt="An industrial CNC machine on a factory floor at golden hour." />
  <div class="showcase-plate__body">
    <p class="showcase-plate__meta">10 controllers · 18 modules · 150 templates · 36,289 lines of PHP</p>
    <h3 class="showcase-plate__title">maschinen-stockert.de — public catalogue</h3>
    <p class="showcase-plate__desc">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.</p>
  </div>
</div>

## maschinen-stockert.de — public catalogue

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

### What ships on it

- **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.

### One representative action

```php
// 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.

---

<div class="showcase-plate">
  <img src="/img/showcase-thorax.png" alt="A wall of well-worn leather technical books, one open in soft focus." />
  <div class="showcase-plate__body">
    <p class="showcase-plate__meta">36 controllers · 18 modules · 348 templates · 161 SQL migrations · 37,369 lines of PHP</p>
    <h3 class="showcase-plate__title">data.maschinen-stockert.de — admin & API</h3>
    <p class="showcase-plate__desc">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.</p>
  </div>
</div>

## data.maschinen-stockert.de — admin & API

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

### What it does

- **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

```php
// 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.

---

## What's actually special, summarised

The five differentiators below are pulled from the codebases above. Each links to its evidence on the [Why Nibiru](/en/why-nibiru/) page.

| | What Nibiru does | What Laravel/Symfony does |
|---|---|---|
| Page copy | Loaded from DB by `<controller>/<action>` per request, editor-managed. | Hardcoded in Blade / translation JSON; deploy to change. |
| Module composition | 13 traits per module, no DI. | Service providers + IoC container. |
| ORM | Direct SQL, MySQL `JSON_ARRAYAGG`, `Pdo::fetchAll`. | Eloquent / Doctrine entities + lazy-loading proxies. |
| Auth | 3 lines in the controller constructor. | Middleware stack + policy classes + gates. |
| Events | `SplSubject` + `SplObserver` from PHP stdlib. | Custom event dispatcher + listener registry + queue. |

Read the [full breakdown with code references →](/en/why-nibiru/)

---

## What it took

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](/en/start/quick-start/), then come back.
