This is the snapshot the production landing site (nibiru-framework.com) is deployed from. Brings together the recent splash + docs migration to the v4 "Cosmos" design system, the new in-framework AI module, and the framework groundwork that backs the framework-reference extraction. What lands: - docs/: Astro + Starlight site with the v4 dark cosmic palette, GalaxyHero canvas constellation, Mission Control chat (wired to /api/oracle → api.neuronetz.ai via providers.mjs Ollama), 5-panel MMVC stage (Model · AI · Module · Controller · View), translated EN/DE/JA/ES/FR content, PWA + sitemap + llms.txt + Umami analytics. - docs/design-system/: canonical mockup bundle (source/index-v2.html for splash, source/docs-system.html + preview/ for docs, SPEC.md, tokens). - docs/scripts/extraction/framework-reference-v2.md: deep framework reference (~1.6k lines, file:line citations, every public factory and idiom — basis for the LoRA training corpus. - application/module/ai/: AI module with chat / embed / RAG / agent plugins, plus pdoQuery / httpGet / fileRead tools and Modelfile + smoke-test in training/. - application/module/users/: user / ACL / form-factory traits used as the reference plugin pattern for the framework docs. - application/settings/config/database/: schema + seed migrations including the AI module tables (200–203). - Form factory + autogenerator changes the framework-reference-v2 covers. Production secrets stay out: docs/.env, settings.production.ini and ai.production.ini are all gitignored (.example files are in tree). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.5 KiB
title, description
| title | description |
|---|---|
| Quick Start | Build a minimal Products page in five minutes — controller, view, navigation entry. |
By the end of this page you'll have a working /products page rendered by Smarty, fed by a controller, listed in the sidebar.
1. Generate a controller
./nibiru -c products
This creates two files:
application/controller/productsController.php
application/view/templates/products.tpl
2. Wire the controller
Open productsController.php and replace the body with:
<?php
namespace Nibiru;
use Nibiru\Adapter\Controller;
class productsController extends Controller
{
public function pageAction()
{
View::assign([
'title' => 'Products — Nibiru',
'products' => [
['id' => 1, 'name' => 'Marduk Gold Plating', 'price' => 99.0],
['id' => 2, 'name' => 'Tiamat Hull Sealant', 'price' => 49.0],
['id' => 3, 'name' => 'Anu Stardust Polish', 'price' => 19.5],
],
'css' => Config::getInstance()->getConfig()[View::NIBIRU_SETTINGS]['smarty.css'],
'js' => Config::getInstance()->getConfig()[View::NIBIRU_SETTINGS]['smarty.js'],
]);
}
public function navigationAction()
{
JsonNavigation::getInstance()->loadJsonNavigationArray();
}
}
Two methods are conventional and always called by the dispatcher:
navigationAction()— populates the global navigation menu.pageAction()— renders the page itself.
Anything matching ?_action=foo will additionally call a fooAction() method between them.
3. Write the view
Open application/view/templates/products.tpl:
{include 'shared/header.tpl'}
<body>
{include file="navigation.tpl"}
<main class="container">
<h1>{$title}</h1>
<table class="table">
<thead>
<tr><th>#</th><th>Name</th><th>Price</th></tr>
</thead>
<tbody>
{foreach $products as $p}
<tr>
<td>{$p.id}</td>
<td><a href="/products/detail/{$p.id}">{$p.name|escape}</a></td>
<td>{$p.price|string_format:"%.2f"} €</td>
</tr>
{/foreach}
</tbody>
</table>
</main>
{include 'shared/footer.tpl'}
</body>
Variables passed to View::assign() show up as {$variable} in Smarty.
4. Add a navigation entry
Edit application/settings/config/navigation/main.json and add:
{
"label": "Products",
"href": "/products",
"icon": "shopping-bag"
}
The navigation is loaded by JsonNavigation and rendered by navigation.tpl.
5. Run it
If you have PHP's built-in server handy:
APPLICATION_ENV=development php -S localhost:8080 -t .
Visit http://localhost:8080/products/. You should see your three products with the cosmic theme of your CSS.
Add a detail page
In the same controller:
public function detailAction()
{
$id = (int) ($_REQUEST['id'] ?? 0);
View::assign([
'title' => "Product #$id",
'id' => $id,
]);
}
Router already understands /products/detail/42 and /products/marduk-gold-plating/42 (SEO URL form — id and slug get auto-populated in $_REQUEST).
Create application/view/templates/products/detail.tpl with whatever markup you like, and you have a two-page app.
Where to next?
- Architecture (MMVC) — how all the moving parts fit.
- Modules — when to graduate from controllers + traits to a real module.
- Database & Migrations — wire the page to a real
productstable.