AGENTS
August 7, 2026 · View on GitHub
Read root AGENTS.md first. Security: SECURITY.md. Config classes live in app/Utils/ — see ../Utils/AGENTS.md.
Files
| File | Role |
|---|---|
bootstrap.php | Load env, merge config, create Config, set flight.*, require services + routes, $app->start() |
config_sample.php | Literal defaults committed to git (template for create-project) |
config.php | Local copy (gitignored) — literals only |
services.php | Tracy, SimplePdo, Twig, Session, Dice + container handler |
routes.php | All HTTP routes |
Nuances (easy to get wrong)
config.phpmust return a plain array of literals. No$_ENV['x'] ??in that file —runway config:setrewrites the return array and would bake resolved values (including secrets) into disk.- Env overlay happens in bootstrap via
Config::mergeEnv+App\Utils\Env::load('.env'). Env wins for mapped keys when set and non-empty. - Side effects (timezone,
flight.*, CSP nonce) belong in bootstrap, not inside the returned config array. services.phpdual load:- Web:
$appis Engine,$configisApp\Utils\Config→ full wiring. - Runway CLI:
$configis array, often no$app→ return early (do not call$config->isDebug()on an array).
- Web:
- Dice: always reassign
$container = $container->addRule(...). Always substituteEngine::class => $app. - Twig render map:
$app->map('render', ...)so controllers share one view path. - Routes: use
[Class::class, 'method']so the container builds controllers. Closures are OK for tiny demos but break the “one pattern” rule for real features. - New shared service: add construct/substitution in
services.php, then type-hint in controllers — do not$app->set('foo', ...)as a global bag for app logic. - New config key: update
config_sample.php, localconfig.phpif needed,.env.example+Config::ENV_MAPif overridable by env.
Do not
- Reintroduce dual simple/robust front controllers.
- Register database as deprecated PdoWrapper for new code.
- Put route definitions in controllers.