| `hasTrailingSlash` | bool | `$ctx->hasTrailingSlash` | Whether original request had trailing slash |
These use PHP 8.4 `private(set)` — readable but not writable from outside the class.
**Exception:** The language plugin modifies `requestPath` via reflection to strip the language prefix. This is an intentional framework-level operation.
| `homeLabel` | string | From root `metadata.ini``slug` field, default `"Home"`. Note: reads `slug`, not `title` — typically set to a short label like "Home" or "Hjem" |
Defined in `app/context.php`. Readonly value object.
```php
readonly class Templates {
public function __construct(
public string $base, # Path to base.php
public string $page, # Path to page.php
public string $list # Path to list.php
) {}
}
```
Resolved by `resolveTemplate()` — see `06-templates.md` "Template Resolution (canonical reference)" for the full lookup chain.
The list template can be overridden per-directory via `page_template` in metadata — this is resolved at render time in `router.php`, not stored in the Templates object.
## Global Access
Context is stored in `$GLOBALS['ctx']` after creation. Plugins that need context outside hook callbacks access it via: