+
Dashboard
+
Users: = $this->userCount ?>
+
Orders: = $this->orderCount ?>
+
+ recentOrders as $order): ?>
+ - = $order['id'] ?>: = $order['total'] ?>
+
+
+
+```
+
+### Template Variants
+
+Add variant templates that take priority over the default. Useful for device-specific or A/B test rendering:
+
+```php
+$page = new DashboardPage();
+$page->addVariant('mobile');
+// Looks for DashboardPage.mobile.phtml first,
+// falls back to DashboardPage.phtml
+echo $page->render();
+```
+
+### Self-Rendering
+
+`TemplatedViewModel` acts as its own view. Calling `createView()` without an override returns `$this`:
+
+```php
+$page = new DashboardPage();
+$view = $page->createView(); // Returns $page itself
+echo $view->render(); // Renders the template
+```
+
+## JsonView
+
+Renders any `Model` as JSON:
+
+```php
+use Cubex\ViewModel\JsonView;
+
+$model = new UserProfileModel();
+$model->name = 'Alice';
+$model->email = 'alice@example.com';
+
+$view = new JsonView();
+$view->setModel($model);
+$view->setFlags(JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
+echo $view->render();
+```
+
+## ArrayModel
+
+A ViewModel backed by a simple array instead of typed properties:
+
+```php
+use Cubex\ViewModel\ArrayModel;
+
+$model = new ArrayModel();
+$model->addItem('Alice', 'name');
+$model->addItem('alice@example.com', 'email');
+$model->set(['tags' => ['admin', 'user']]);
+
+echo json_encode($model);
+// {"name":"Alice","email":"alice@example.com","tags":["admin","user"]}
+```
+
+## ViewModel Flow in Controllers
+
+When a controller method returns a `ViewModel`, the framework handles view creation and rendering automatically:
+
+```mermaid
+flowchart LR
+ Controller["Controller returns